Skip to content

fix(webapp): the palette always offers a way back (BEA-52) - #102

Merged
ssowonny merged 2 commits into
mainfrom
bea-52-ph-scan-bug-command-palette-on-a-not-found-route-offers-no
Aug 2, 2026
Merged

fix(webapp): the palette always offers a way back (BEA-52)#102
ssowonny merged 2 commits into
mainfrom
bea-52-ph-scan-bug-command-palette-on-a-not-found-route-offers-no

Conversation

@ssowonny

Copy link
Copy Markdown
Contributor

TL;DR

  • ⌘K on a path that doesn't resolve used to offer History ×2 and Sign out — no route back to the project, on the one screen where you need one.
  • The palette now always leads with Go to project root / Dashboard / Installation / Settings — the same four the sidebar has.
  • They show up everywhere, including when the file tree is empty or its fetch failed; each is a real URL that survives a reload.
  • Additive only: no second History entry, no ranking/styling changes, nothing else in the palette moved.
  • Known gap: the not-found page itself still has no back-link (Browser.tsx, "Check again" only) — out of scope here, still the obvious follow-up.

Fixes BEA-52.

Before / after

⌘K on /<project-id>/does-not-exist.md:

Before After
before after

The seeded harness has a tree, so "before" is less bare than the reported case (one project, empty tree → three entries) — but the four ways back are missing either way.

And on a brand-new project with nothing in it, which is where the tree-derived entries can't help at all:

empty project

Every entry lands on a real URL that renders the same view after a reload (Settings shown; root/dashboard/install verified the same way):

settings

What changed

paletteCandidates (internal/webapp/frontend/src/apps/Browser.tsx) built its list from path-scoped actions, whole-project history, other projects, sign out, and the tree. None of those is a view route, so on a dead route the two tree-derived sources vanish and, on a single-project hub, so does the switcher.

Four static entries now go first, gated on hub && project only — the same condition ProjectNav uses, and independent of loaded/the tree:

Entry icon Destination
Go to project root folder /<project-id>
Dashboard dashboard /<project-id>/dashboard
Installation terminal /<project-id>/install
Settings gear /<project-id>/settings

They're first because an empty query scores every candidate 0 and the sort is stable. Icons are the ones ProjectNav already uses for the same destinations. Every entry goes through urlForView/navigate — never panel state — and closes an open admin panel explicitly, since HubApp only clears panels on a location change and picking the page you're already on isn't one.

History: whole project was left exactly where it was: same destination as the sidebar's History, so no second entry.

Deviations from the plan

Two, both small:

  • The plan imported type ViewName and wrapped urlForView in a go(v: ViewName) helper. Passing the URL string straight to a go(to: string) helper covers the project-root case too and needs no new import — same four URLs.
  • The plan's test asserted on #palette-results. That id never reaches the DOM: cmdk's List overwrites id with its own generated one (a pre-existing quirk in Palette.tsx, untouched here). The test uses #palette [cmdk-list] instead, and there's a comment saying why.

Testing

  • go build ./..., go vet ./..., go test ./... — all pass.
  • npm run e2e — 98 passed, including the new palette on a dead route still offers the way back (e2e/browse.spec.ts): asserts the four entries on /<wiki-id>/does-not-exist.md, asserts exactly one whole-project History entry, selects Dashboard, waits for /<wiki-id>/dashboard, reloads, asserts the treemap renders.
  • UI pass against the seeded hub: the four entries also appear on a normal file route and on a fresh empty project, and all four destinations render after a reload.
  • frontend/check-dist.shinternal/webapp/static is fresh (rebuilt and committed).

No architecture diagram change: Palette and Browser are already drawn in architecture/webapp-frontend.md and no type or relationship changed.

Build session

cd $(git worktree list | grep bea-52-ph-scan-bug-command-palette-on-a-not-found-route-offers-no | awk '{print $1}') && claude --resume 67a2334d-1955-4222-8c64-f1fdcaa1b699

(only works on this machine)

⌘K on a path that doesn't resolve degraded to History ×2 and Sign out —
the tree-derived entries are gone on a dead route and the switcher lists
only OTHER projects, so on a single-project hub the palette, which is the
natural escape hatch there, was the one surface with no way out.

Four static entries now lead the candidate list whenever hub && project:
Go to project root, Dashboard, Installation, Settings — the same four
destinations (and icons) the sidebar has. They're independent of the tree
and of whether the path resolves, and each navigates to a real
VIEW_ROUTES URL, so a reload renders the same view. Panels only close on
a location change, so selecting the page you're already on closes them
explicitly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ssowonny
ssowonny requested a review from thefron July 31, 2026 04:14
@ssowonny
ssowonny merged commit c5f8114 into main Aug 2, 2026
2 checks passed
@ssowonny
ssowonny deleted the bea-52-ph-scan-bug-command-palette-on-a-not-found-route-offers-no branch August 2, 2026 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant