This branch ships the signed-in create-flow experience, server draft sync (when enabled), anonymous → account draft transfer after magic link, and publish to POST /api/rules from final review. It aligns the app with the backend roadmap and Linear work through CR-77 (publish wiring), building on CR-75 (session affordances) and CR-76 (draft sync hardening).
Goals: magic-link auth from header and create-flow exit, PUT /api/drafts/me for signed-in save/exit and post-login transfer, Finalize persisting PublishedRule and showing the result on completed, with clearer errors and layout polish (viewport-anchored chrome, non-blocking error overlays, client-only create shell to avoid hydration mismatches after redirects).
Changes
Auth & marketing shell
AuthModalProvider + header Log in / Profile; login modal variants (default vs save progress); LoginForm supports magicLinkNextPath, syncDraft=1 transfer flag when next includes it.
Top nav / menu bar updates for profile entry; root layout wraps marketing routes with AuthModalProvider.
Login page shell + profile placeholder with sign-out for QA.
Create flow state & persistence
Anonymous draft mirror in localStorage (create-flow-anonymous); transfer-pending flag; CreateFlowContext hydration when guest persistence turns on.
SignedInDraftHydration: load server draft with optional conflict handling vs anonymous copy; i18n for hydration copy.
PostLoginDraftTransfer: after verify with ?syncDraft=1, PUT draft when NEXT_PUBLIC_ENABLE_BACKEND_SYNC=true, or merge local draft into memory when sync is off; strips query after run.
useCreateFlowExit: Save & Exit → saveDraftToServer with parsed API errors; draft save banner context.
Removed obsolete CreateFlowBackendSync in favor of explicit hooks/components.
publishRule: resilient JSON/error handling and network failures; returns status for 401 handling.
lastPublishedRule: sessionStorage bridge to completed (until a public GET /api/rules/[id] exists).
Final review: RuleCard driven from context; layout Finalize calls publish, overlays for errors, 401 → login with /create/final-review?syncDraft=1.
Completed page: prefers last-published payload; mobile main scroll preserved where relevant.
Create layout
Split into CreateFlowLayoutGate (dynamic + ssr: false) + CreateFlowLayoutClient to avoid hydration mismatches on pathname-heavy shell after magic-link redirects.
Full-height shell: header + footer stay in view; main scrolls for typical steps.
Draft/publish error Alerts are fixed overlays (no layout shift).
API client & types
saveDraftToServer / fetchDraftFromServer; CreateFlowState + hasCreateFlowUserInput for Save & Exit gating.
CONTRIBUTING: notes on POST /api/rules (new row per finalize) and syncDraft behavior when sync is off.
Docs
Updates to docs/backend-roadmap.md and docs/backend-linear-tickets.md for current behavior and ticket alignment.
Env:.env from .env.example; Postgres up (docker compose up -d postgres); npx prisma migrate dev; optional NEXT_PUBLIC_ENABLE_BACKEND_SYNC=true and Mailhog / dev log magic links.
Anonymous create flow
Progress through steps; Exit → save-progress modal → magic link → return with draft; confirm state and (if sync on) server draft.
Signed-in
Save & Exit from step ≥ select when sync on; confirm PUT /api/drafts/me and banner on failure.
Publish
On final-review, Finalize → completed + DB row; GET /api/rules lists rule.
Anonymous finalize → 401 → sign in → return to final-review → finalize succeeds; title not lost after transfer.
Layout / a11y
Narrow viewport: completed and long steps scroll in main; footer stays bottom; error banners overlay without pushing chrome.
Regression
npm run build, npx vitest run, npx tsc --noEmit (as in CI).
Notes
Next in roadmap (e.g. CR-78): Prisma seed for RuleTemplate — not in this PR.
Follow-ups:GET /api/rules/[id] (e.g. CR-81) to replace sessionStorage for completed; profile / my rules (CR-86); API error contract (CR-84). Each finalize still creates a new published row until an update API exists (documented in CONTRIBUTING).
Create layout ssr: false: brief black loading shell while the create layout chunk loads—tradeoff for stable client navigation after auth redirects.
## Overview
This branch ships the **signed-in create-flow experience**, **server draft sync** (when enabled), **anonymous → account draft transfer** after magic link, and **publish to `POST /api/rules`** from final review. It aligns the app with the backend roadmap and Linear work through **CR-77** (publish wiring), building on **CR-75** (session affordances) and **CR-76** (draft sync hardening).
Goals: magic-link auth from header and create-flow exit, `PUT /api/drafts/me` for signed-in save/exit and post-login transfer, **Finalize** persisting `PublishedRule` and showing the result on **completed**, with clearer errors and layout polish (viewport-anchored chrome, non-blocking error overlays, client-only create shell to avoid hydration mismatches after redirects).
## Changes
- **Auth & marketing shell**
- `AuthModalProvider` + header **Log in** / **Profile**; login modal variants (default vs save progress); `LoginForm` supports `magicLinkNextPath`, `syncDraft=1` transfer flag when `next` includes it.
- Top nav / menu bar updates for profile entry; root layout wraps marketing routes with `AuthModalProvider`.
- Login page shell + profile placeholder with sign-out for QA.
- **Create flow state & persistence**
- Anonymous draft mirror in **`localStorage`** (`create-flow-anonymous`); transfer-pending flag; `CreateFlowContext` hydration when guest persistence turns on.
- **`SignedInDraftHydration`**: load server draft with optional conflict handling vs anonymous copy; i18n for hydration copy.
- **`PostLoginDraftTransfer`**: after verify with `?syncDraft=1`, `PUT` draft when `NEXT_PUBLIC_ENABLE_BACKEND_SYNC=true`, or **merge local draft into memory** when sync is off; strips query after run.
- **`useCreateFlowExit`**: Save & Exit → `saveDraftToServer` with parsed API errors; draft save **banner** context.
- Removed obsolete **`CreateFlowBackendSync`** in favor of explicit hooks/components.
- **Publish (CR-77)**
- **`buildPublishPayload`**: maps `CreateFlowState` → `{ title, summary?, document }` with `CommunityRuleDocument`-shaped `sections` + fallback overview section.
- **`publishRule`**: resilient JSON/error handling and network failures; returns `status` for 401 handling.
- **`lastPublishedRule`**: `sessionStorage` bridge to **completed** (until a public `GET /api/rules/[id]` exists).
- Final review: RuleCard driven from context; layout **Finalize** calls publish, overlays for errors, **401** → login with `/create/final-review?syncDraft=1`.
- Completed page: prefers last-published payload; mobile main scroll preserved where relevant.
- **Create layout**
- Split into **`CreateFlowLayoutGate`** (`dynamic` + `ssr: false`) + **`CreateFlowLayoutClient`** to avoid **hydration mismatches** on pathname-heavy shell after magic-link redirects.
- **Full-height** shell: **header + footer** stay in view; **main** scrolls for typical steps.
- Draft/publish **error Alerts** are **fixed overlays** (no layout shift).
- **API client & types**
- `saveDraftToServer` / `fetchDraftFromServer`; `CreateFlowState` + `hasCreateFlowUserInput` for Save & Exit gating.
- **`CONTRIBUTING`**: notes on `POST /api/rules` (new row per finalize) and `syncDraft` behavior when sync is off.
- **Docs**
- Updates to **`docs/backend-roadmap.md`** and **`docs/backend-linear-tickets.md`** for current behavior and ticket alignment.
- **Tests & stories**
- Vitest: `saveDraftToServer`, `buildPublishPayload`, `publishRule`, draft hydration helpers, `hasCreateFlowUserInput`, Auth modal, Login/LoginForm, FinalReview, CreateFlowTopNav.
- Storybook: Login + CreateFlowTopNav stories updated.
## Screenshots
<!-- Add image tags if visual changes exist, otherwise leave this section empty -->
## How to Test
1. **Env:** `.env` from `.env.example`; Postgres up (`docker compose up -d postgres`); `npx prisma migrate dev`; optional `NEXT_PUBLIC_ENABLE_BACKEND_SYNC=true` and Mailhog / dev log magic links.
2. **Anonymous create flow**
- Progress through steps; **Exit** → save-progress modal → magic link → return with draft; confirm state and (if sync on) server draft.
3. **Signed-in**
- **Save & Exit** from step ≥ select when sync on; confirm `PUT /api/drafts/me` and banner on failure.
4. **Publish**
- On **final-review**, **Finalize** → completed + DB row; `GET /api/rules` lists rule.
- Anonymous finalize → **401** → sign in → return to final-review → finalize succeeds; title not lost after transfer.
5. **Layout / a11y**
- Narrow viewport: completed and long steps scroll in **main**; footer stays bottom; error banners overlay without pushing chrome.
6. **Regression**
- `npm run build`, `npx vitest run`, `npx tsc --noEmit` (as in CI).
## Notes
- **Next in roadmap (e.g. CR-78):** Prisma seed for `RuleTemplate` — not in this PR.
- **Follow-ups:** `GET /api/rules/[id]` (e.g. CR-81) to replace `sessionStorage` for completed; profile / my rules (CR-86); API error contract (CR-84). Each **finalize** still creates a **new** published row until an update API exists (documented in CONTRIBUTING).
- **Create layout `ssr: false`:** brief black loading shell while the create layout chunk loads—tradeoff for stable client navigation after auth redirects.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Overview
This branch ships the signed-in create-flow experience, server draft sync (when enabled), anonymous → account draft transfer after magic link, and publish to
POST /api/rulesfrom final review. It aligns the app with the backend roadmap and Linear work through CR-77 (publish wiring), building on CR-75 (session affordances) and CR-76 (draft sync hardening).Goals: magic-link auth from header and create-flow exit,
PUT /api/drafts/mefor signed-in save/exit and post-login transfer, Finalize persistingPublishedRuleand showing the result on completed, with clearer errors and layout polish (viewport-anchored chrome, non-blocking error overlays, client-only create shell to avoid hydration mismatches after redirects).Changes
Auth & marketing shell
AuthModalProvider+ header Log in / Profile; login modal variants (default vs save progress);LoginFormsupportsmagicLinkNextPath,syncDraft=1transfer flag whennextincludes it.AuthModalProvider.Create flow state & persistence
localStorage(create-flow-anonymous); transfer-pending flag;CreateFlowContexthydration when guest persistence turns on.SignedInDraftHydration: load server draft with optional conflict handling vs anonymous copy; i18n for hydration copy.PostLoginDraftTransfer: after verify with?syncDraft=1,PUTdraft whenNEXT_PUBLIC_ENABLE_BACKEND_SYNC=true, or merge local draft into memory when sync is off; strips query after run.useCreateFlowExit: Save & Exit →saveDraftToServerwith parsed API errors; draft save banner context.CreateFlowBackendSyncin favor of explicit hooks/components.Publish (CR-77)
buildPublishPayload: mapsCreateFlowState→{ title, summary?, document }withCommunityRuleDocument-shapedsections+ fallback overview section.publishRule: resilient JSON/error handling and network failures; returnsstatusfor 401 handling.lastPublishedRule:sessionStoragebridge to completed (until a publicGET /api/rules/[id]exists)./create/final-review?syncDraft=1.Create layout
CreateFlowLayoutGate(dynamic+ssr: false) +CreateFlowLayoutClientto avoid hydration mismatches on pathname-heavy shell after magic-link redirects.API client & types
saveDraftToServer/fetchDraftFromServer;CreateFlowState+hasCreateFlowUserInputfor Save & Exit gating.CONTRIBUTING: notes onPOST /api/rules(new row per finalize) andsyncDraftbehavior when sync is off.Docs
docs/backend-roadmap.mdanddocs/backend-linear-tickets.mdfor current behavior and ticket alignment.Tests & stories
saveDraftToServer,buildPublishPayload,publishRule, draft hydration helpers,hasCreateFlowUserInput, Auth modal, Login/LoginForm, FinalReview, CreateFlowTopNav.Screenshots
How to Test
.envfrom.env.example; Postgres up (docker compose up -d postgres);npx prisma migrate dev; optionalNEXT_PUBLIC_ENABLE_BACKEND_SYNC=trueand Mailhog / dev log magic links.PUT /api/drafts/meand banner on failure.GET /api/ruleslists rule.npm run build,npx vitest run,npx tsc --noEmit(as in CI).Notes
RuleTemplate— not in this PR.GET /api/rules/[id](e.g. CR-81) to replacesessionStoragefor completed; profile / my rules (CR-86); API error contract (CR-84). Each finalize still creates a new published row until an update API exists (documented in CONTRIBUTING).ssr: false: brief black loading shell while the create layout chunk loads—tradeoff for stable client navigation after auth redirects.