fix(app): wire the add-vault chooser + wizard escape hatches + friendly errors (F2/F6/F12/F13/F18) - #10
Merged
Merged
Conversation
…ly errors (F2/F6/F12/F13/F18) Owner-flagged "can't get back / dead-end" navigation bugs from the app audit, plus a stale doc — all redesign-independent so they land ahead of the coming IA rework: - F2: /vaults' "Add vault" (header + empty-state) now opens the purpose-built add-vault chooser (/add-vault) instead of the self-hosted connect form (/add), which had no path to "create" and no way back for a cloud user. - F13: the chooser's "Open" card links to /welcome?pick=1, forcing the picker instead of silently reopening the account's one vault. - F6: the Wordmark is a real Link to "/" everywhere it renders (every full-screen wizard screen shares it), plus an explicit "← Back" on the vault-naming form, the self-hosted connect form, the chooser, and /check-email — screens that previously had zero chrome and no exit but the browser Back button. - F12: jsonOrThrow now prefers the server's friendly `message` over its bare `error` code; a new describeAccountError() belt-and-suspenders maps known codes to calm copy for what that doesn't cover (vault-creation and vault-open failures). - F18: STYLE.md rewritten against the live coral palette in index.css (it documented the retired forest-green identity). Version bump 0.4.1 -> 0.4.2, CHANGELOG entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XLZtmuSs1RirWGMGyCB1QB
This was referenced Jul 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a cohesive set of "you can't get back / dead-end" navigation bugs the owner flagged in the app's experiential audit (findings F2, F6, F12, F13), plus a stale doc (F18). These are the clear, redesign-independent fixes — an escape hatch is never the wrong call in any future IA. Explicitly out of scope: the history/replace policy rewrite (F7), the IA redesign (F14/F15), and notes-anatomy work (F8/F9/F10) — those wait for the owner's larger plan.
F2 — the orphaned add-vault chooser is wired in
/vaults's "Add vault" buttons (header + empty-state) pointed at/add— the self-hosted connect URL form, a dead-end for a cloud user (no path to "create", no way back). Both now open/add-vault(AddVaultChooser.tsx), the purpose-built Open/Create/Connect chooser that had zero inbound links anywhere in the app until now./addstays exactly what it was — the leaf the chooser's "Connect a self-hosted vault" card targets.Checked
VaultPopover.tsxper the brief's example: it has no separate generic "add vault" affordance of its own — its only pointer is "Manage vaults →" →/vaults, which this fix already makes correct transitively. No changes needed there.F13 — the chooser's "Open" card no longer silently reopens your only vault
Chooser "Open" →
/welcome; with exactly one account vault, the dispatcher'sclassifyVaultsauto-runs the welcome-back beat and reopens the vault you're likely already in. Fixed per the plan: the card now links to/welcome?pick=1, and the dispatcher forces the picker whenever?pick=1is present and the account has ≥1 vault (falls through to first-vault naming when it has zero).F6 — the wizard screens have a way out
Wordmark(ParachuteMark.tsx) is now a real<Link to="/">everywhere it renders. Verified every call site first (Landing, Welcome, AddVault, AddVaultChooser, CheckEmail, OAuthCallback) — all six are full-screen wizard Shells with no active vault, so none of them have any other chrome (Rail returns null, Header islg:hidden). Linking the shared component covers all of them at once; no separate linked variant needed.Welcome.tsx, backs up to/add-vaultfor an add-vault naming or/for first-vault onboarding), the self-hosted connect form (AddVault.tsx, backs up to/), the add-vault chooser (AddVaultChooser.tsx, backs up to/vaultswhen a vault's already active on this device, else/), and/check-email(backs up to/).CreationBeatView's error branch (the "Something went sideways" full-screen card,Welcome.tsxaround the old:519-537) is pre-existing unreachable dead code — the actual creation-failure catch transitions back to thenamingstage (inline error banner on the SAME form, preserving the typed name), never to acreating-kind stage with its ownerrorset. So the literal "Never mind on the creating-error card" ask doesn't apply to a screen that ever renders; the naming form's new Back link is the real escape hatch for that path (left a code comment explaining this; reconciling the dead branch is a separate cleanup, not a nav fix).F12 — friendly error copy
Root cause:
client.ts'sjsonOrThrowpreferred the server's machineerrorcode over its accompanying friendlymessage(cloud'saccount-api.tsrestErrorsends both — e.g.{error: "vault_taken", message: "That vault name is already taken."}) — a plan-limit hit rendered as a barevault_limit_reached. Swapped the precedence (verified this doesn't breakmarkHubGateFromError's hub-gate check, which compares against a shape that has nomessagefield at all). Addedlib/account/error-copy.ts(describeAccountError) as belt-and-suspenders: maps known bare codes to calm copy, generic fallback for unknown ones — covers what the root-cause fix doesn't (an older/self-hosted response with nomessage). Wired into the vault-naming creation error andAccount.tsx'sVaultsBlock.openerror.F18 — STYLE.md rewritten against the real palette
Was documenting the retired forest-green identity (
#4a7c59/#7ab087);index.csshas been the coral brand pass (#bf4a2a/#e05d3c, grass/sun/sage) for a while. Rewrote against the actual tokens + component classes, including the arrival/wizard classes added since (.tile,.composer,.hero-title,.nudge-sun,.note-row,.drop-in/.fade-up) that weren't documented anywhere. Doc-only.Gates (literal counts)
bunx vitest run— 1284 passed, 0 failed (126 test files)bun run typecheck— clean, no errorsbunx biome check .— 0 errors, 2 warnings (pre-existinguseExhaustiveDependenciesinsrc/lib/vault/live-query.ts, a file this PR never touches — confirmed viagit diff --statshowing no diff)bun run build— succeeds (pre-existing chunk-size + dynamic/static-import-mix advisories, unrelated to this diff)Version bump 0.4.1 → 0.4.2 (
package.json), CHANGELOG entry added.Test plan
Vaults.test.tsx(F2 routing),AddVaultChooser.test.tsx(F13?pick=1+ Back link),Welcome.test.tsx(F13 picker-forcing, F6 Back links, F12 friendly copy),AddVault.test.tsx/CheckEmail.test.tsx(F6 Back links),client.test.ts+ newerror-copy.test.ts(F12 precedence fix + mapping)Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01XLZtmuSs1RirWGMGyCB1QB