import { useQuery } from '@tanstack/react-query'; import { useState } from 'react'; import { Button } from '#/components/atoms/button.jsx'; import { Heading } from '#/components/atoms/heading.jsx'; import { Notice } from '#/components/atoms/notice.jsx'; import { Panel } from '#/components/atoms/panel.jsx'; import { Skeleton } from '#/components/atoms/skeleton.jsx'; import { DetailList } from '#/components/molecules/detail-list.jsx'; import { FormShell } from '#/components/molecules/form-shell.jsx'; import { Section } from '#/components/molecules/section.jsx'; import { TextField } from '#/components/molecules/text-field.jsx'; import { get, post } from '#/lib/api.js'; import { queryKeys, useInvalidate } from '#/lib/query.js'; /** * The domain this PDS hosts, derived from its own endpoint. A handle that is * this domain or a subdomain of it is verified by the server itself. * @param {string} endpoint */ function pdsDomainOf(endpoint) { try { return new URL(endpoint).hostname; } catch { return ''; } } /** * The rename control. A username has to be a domain you own, proven with DNS — * this reads what you type and shows the exact record before you submit. The * server's own address and its subdomains are special cases it calls out. * @param {{did: string, pdsDomain: string, onSucceed: () => void}} props */ function RenameForm({ did, pdsDomain, onSucceed }) { const [value, setValue] = useState(''); const typed = value.trim().toLowerCase(); const isSelf = !!pdsDomain && typed === pdsDomain; const isInternal = !!pdsDomain && typed !== pdsDomain && typed.endsWith(`.${pdsDomain}`); const isExternal = typed !== '' && !isSelf && !isInternal; return ( post('/identity/handle', { handle })} onSucceed={() => { setValue(''); onSucceed(); }} > setValue(event.target.value)} placeholder="name.example.com" hint={ pdsDomain ? `A domain you own, verified with DNS. This server's address is ${pdsDomain}.` : 'A domain you own, e.g. name.example.com.' } /> {isSelf && (

{pdsDomain} is this server's own address — it's already your username.

)} {isInternal && (

{typed} is a subdomain of this server. A single-user PDS only answers at{' '} {pdsDomain}, so a name like this won't resolve unless you separately host it. To change your username, use a domain you own below.

)} {isExternal && (

{typed} is a domain you own. Prove it points here first, with either one of these, then submit:

DNS TXT record
_atproto.{typed} → did={did}
or serve this URL
https://{typed}/.well-known/atproto-did → {did}
)}
); } export function IdentityPage() { const { data, error } = useQuery({ queryKey: queryKeys.identity, queryFn: () => get('/identity'), }); const invalidate = useInvalidate(); if (error) { return {error.message}; } if (!data) { return (
); } return (
{data.handle ? `@${data.handle}` : 'none'}

This is the name people see in every app. It points at your permanent ID, so you can change it without losing anything you have made.

{!data.readOnly && ( invalidate([queryKeys.identity, queryKeys.overview]) } /> )}
Your permanent ID

Never changes, even if you rename or move hosts. Apps follow this, not your username.

{data.did}
Change host

Move your account, everything in it and your followers to another host. Your username and permanent ID come with you.

); }