A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

Record decision 0020: writing-first deferred publish

+29
+29
docs/decisions/0020-writing-first-deferred-publish.md
··· 1 + # 0020 — Writing-first flow: deferred publish, no remote account creation 2 + 3 + ## Context 4 + `/editor` gates the entire editor behind OAuth. We wanted a parallel surface where writing is 5 + the first action and auth/publication selection are deferred to publish time. 6 + 7 + ## Decision 8 + - Add a parallel route `/write` mounting a new `WriteStudio` island that renders the editor for 9 + every auth status (no login gate). `/`, `/editor`, `/dashboard` are untouched. 10 + - Images are held locally as `data:` URLs and uploaded to the PDS only at publish 11 + (`src/lib/write/upload-held.ts`), via one media path regardless of auth state. 12 + - The draft (title, lede, token-skeleton blocks, cover) survives the full-page OAuth redirect: 13 + light metadata + skeleton in `localStorage`, image bytes in IndexedDB 14 + (`src/lib/write/draft-store.ts` + `asset-store.ts`). A one-shot `publishIntent` flag makes the 15 + publish flow auto-resume on return. 16 + - Publish branches on publication count: one → confirm; many → pick; zero → inline create. The 17 + single-publication case still shows a confirm — publishing also posts to Bluesky (brief §10). 18 + 19 + ## Why not remote account creation 20 + atproto OAuth authenticates an existing account; `com.atproto.server.createAccount` lives on a 21 + PDS's hosted signup (invite/email gated) and is not exposed to third-party clients. Building an 22 + inline signup would make SkyPress a hosting/signup broker, contradicting the "never a PDS/relay" 23 + guardrail. The signed-out panel therefore links out to Bluesky signup and otherwise offers 24 + sign-in only. 25 + 26 + ## Consequences 27 + - Signed-in writers lose eager upload error feedback (errors surface at publish) — accepted for a 28 + single, simpler media path. 29 + - `data:`-URL drafts can be large; bytes go to IndexedDB to avoid the `localStorage` quota.