feat(registry): bsky client picker, dropped support/handle fields, prefill avatar
Profile schema simplifications and Explore UX improvements based on the
fact that a registry profile is, by construction, owned by the signed-in
account: the user's handle (which is both their Bluesky handle and their
Atmosphere handle — they're the same identity) is implicit, so there's
no reason to ask for it in the form.
- Lexicon: drop `supportUrl`, `bskyHandle`, `atmosphereHandle`. Add
`bskyClient` enum (bluesky | blacksky | anisota | deer | witchsky).
- DB: remove the dropped columns from the base schema; ship an idempotent
additive ALTER to add the new `bsky_client` column to existing tables
(catches "duplicate column" so it's safe to re-run).
- New lib/bsky-clients.ts is the single source of truth for the client
list (id, display name, domain, profile URL builder, favicon helper).
- CreateProfileForm:
- Drop the support/contact, Bluesky-handle, and Atmosphere-handle
inputs. Show a read-only "Signed in as @handle" row instead.
- Add a radio-card client picker styled to match the native modal
referenced by the user (favicon, name, domain, selection ring).
- Avatar preview now falls back to a server-passed `initialAvatarUrl`
(the Bluesky PDS getBlob URL) when no registry record exists yet,
so the prefilled icon actually renders instead of showing an empty
placeholder.
- /explore/[handle] (ProfileLinks): replace the generic link grid with
two prominent buttons — "Open on <client>" (using the project's
selected client + that client's favicon) and Website. The Bluesky
button is the visual primary action; Website is secondary.
- routes/explore/manage.tsx: compute the PDS getBlob URL for the
prefill case and pass it to the form.
- i18n: add handleLabel, bskyClientLabel/Hint, openOn; drop unused
support/bskyHandle/atmosphereHandle copy.
- API + indexer: serialise/deserialise `bskyClient` end-to-end.
Made-with: Cursor