···11+# 0020 — Writing-first flow: deferred publish, no remote account creation
22+33+## Context
44+`/editor` gates the entire editor behind OAuth. We wanted a parallel surface where writing is
55+the first action and auth/publication selection are deferred to publish time.
66+77+## Decision
88+- Add a parallel route `/write` mounting a new `WriteStudio` island that renders the editor for
99+ every auth status (no login gate). `/`, `/editor`, `/dashboard` are untouched.
1010+- Images are held locally as `data:` URLs and uploaded to the PDS only at publish
1111+ (`src/lib/write/upload-held.ts`), via one media path regardless of auth state.
1212+- The draft (title, lede, token-skeleton blocks, cover) survives the full-page OAuth redirect:
1313+ light metadata + skeleton in `localStorage`, image bytes in IndexedDB
1414+ (`src/lib/write/draft-store.ts` + `asset-store.ts`). A one-shot `publishIntent` flag makes the
1515+ publish flow auto-resume on return.
1616+- Publish branches on publication count: one → confirm; many → pick; zero → inline create. The
1717+ single-publication case still shows a confirm — publishing also posts to Bluesky (brief §10).
1818+1919+## Why not remote account creation
2020+atproto OAuth authenticates an existing account; `com.atproto.server.createAccount` lives on a
2121+PDS's hosted signup (invite/email gated) and is not exposed to third-party clients. Building an
2222+inline signup would make SkyPress a hosting/signup broker, contradicting the "never a PDS/relay"
2323+guardrail. The signed-out panel therefore links out to Bluesky signup and otherwise offers
2424+sign-in only.
2525+2626+## Consequences
2727+- Signed-in writers lose eager upload error feedback (errors surface at publish) — accepted for a
2828+ single, simpler media path.
2929+- `data:`-URL drafts can be large; bytes go to IndexedDB to avoid the `localStorage` quota.