feat(roadmap): public /roadmap page with a workstream timeline - #350
Conversation
Adds a dedicated Roadmap page rendering the 12-month plan as a workstream timeline, so the roadmap is legible without reading ROADMAP.md. Layout follows the existing public-page pattern (thin page + component under components/pages/homepage, Reveal for staggered entrance, the shared Table and Tooltip primitives). Content lives in data.ts so the plan can be edited without touching layout code. The timeline is grouped by workstream rather than by owner so the continuity from delivered to planned stays visible; owner initials ride on each bar as a corner badge. Status is encoded by fill, icon and label together, never colour alone. Emerald and amber are used for the two chart states because they stay distinguishable under the common forms of colour blindness, where emerald/red would not; red is reserved for the single critical callout and is never a chart colour. "Planned" is a dashed outline rather than a fourth hue, since absence of status reads better as an outline than as grey fill. Three layout details worth noting, each verified in the browser: - Every grid cell is placed explicitly. The "today" rule spans all rows, and a grid item with a definite position is packed before auto-placed siblings, which otherwise shifted the month headers a column right. - The page root needs w-full + min-w-0. It is a flex item, and mx-auto suppresses flex stretch, which left the box sized to the grid's min-content and pushed the whole page wider than the viewport instead of letting the grid scroll on its own. - Bar labels need min-w-0 so a long word wraps inside the bar instead of spilling into the next month. Wires the route into the SEO registry, the sitemap, the public-route allowlist, the no-JS crawler fallback and the footer. Verified at 375px and 1440px, in light and dark: no page-level horizontal overflow, no bar overlaps, no clipped labels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Scrolling the timeline horizontally slid the bars over the sticky workstream column instead of under it, so labels and bars collided, and the frozen corner was translucent enough for scrolled month headers to show through it. Sticky cells need both a stacking order and an opaque fill. Cells sit at the base, bars and the today rule at z-10, the frozen workstream column at z-20, the corner at z-30 — and the corner moves from bg-muted/50 with a backdrop blur to solid bg-muted. Verified scrolled in light and dark. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a `/vault` folder at the repo root describing every feature and the state it is in, and an interactive graph at /roadmap/graph driven by it. The vault is an Obsidian-compatible folder of plain markdown with YAML frontmatter and [[wikilinks]] — 52 features across 10 areas and 4 states, openable directly in Obsidian with no plugins. Each feature's `area` and `state` become edges to those notes, and every wikilink in a body becomes an edge between features, so there is no separate index to keep in sync: changing one `state:` line is what moves a node. src/lib/vault.ts parses it at build time via getStaticProps — the only page in the app not using a no-op getServerSideProps. The vault only changes when the repo does, so this costs nothing at runtime, and a malformed note fails the build rather than a visitor's request. A feature naming an area or state with no note throws, so typos surface at build. The frontmatter parser covers a documented YAML subset (scalars, inline arrays, block lists) rather than adding a dependency — a deliberate trade-off in a wallet codebase. Types live in vault-types.ts because importing any *value* from the loader would pull `fs` into the client bundle. The graph is a small force simulation rather than a graph library: same reasoning on dependencies, and at 66 nodes the O(n²) pass is cheap. It settles before paint instead of animating, so there is no motion to sit through. Layout is seeded from a deterministic hash so server and client agree. Interaction: click to read a note, hover or focus to isolate a node and its neighbours, drag to rearrange, filter by state, search across titles, summaries, areas and owners, and toggle the state hubs off to untangle the layout into pure area structure. Details worth keeping: - Pointer-down deliberately changes no state. Seeding the drag there re-ran the layout and moved the node out from under the cursor, so the click never completed. Dragging now starts after a 5px threshold, and only the dropped node is pinned while the rest relax around it. - Hub labels get a placement pass that tries below, above, then further out, skipping slots that collide or fall outside the canvas. Without it two area labels sat on top of each other. - Feature labels appear on demand; 52 of them at once is an unreadable mat of text. Wires the route into the SEO registry, sitemap, public-route allowlist, no-JS crawler fallback and footer, and links it from the roadmap page. /roadmap moves to /roadmap/index so the graph is a sibling route. Verified at 375px and 1440px, light and dark: no page overflow, no overlapping or clipped labels, selection, filters, search and drag all working. 514 unit tests pass, 16 of them covering the parser. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed a second, larger piece to this branch: a feature vault at the repo root and an interactive knowledge graph driven by it at It is stacked here rather than opened separately because it moves The vault
---
type: feature
area: Governance
state: delivered # delivered | in-progress | planned | blocked
owner: Quirin
milestone: 2026-06
issues: [122]
prs: [272, 296]
---
How it is read
Two deliberate trade-offs:
The graphClick a node to read it, hover or focus to isolate it and its neighbours, drag to rearrange, filter by state, search across titles, summaries, areas and owners, and toggle the state hubs off to untangle the layout into pure area structure. It settles before paint rather than animating, and the layout is seeded from a deterministic hash so server and client agree. Three fixes found by measuring the rendered page, not by reading the code:
Verification
|
Adds a dedicated /roadmap page that renders the 12-month plan as a workstream timeline, so the roadmap is legible without reading
ROADMAP.md.Companion to #347, which updates
ROADMAP.mditself. This PR is the page; the two touch different files.Approach
Follows the existing public-page pattern — a thin
src/pages/roadmap.tsxover a component undercomponents/pages/homepage/roadmap, usingRevealfor staggered entrance and the sharedTableandTooltipprimitives. Content lives indata.tsso the plan can be edited without touching layout code.The timeline is grouped by workstream rather than by owner, so continuity from delivered to planned stays visible; owner initials ride on each bar as a corner badge instead of consuming label width.
Colour
Status is encoded by fill, icon and label together — never colour alone. Emerald and amber carry the two chart states because they stay distinguishable under the common forms of colour blindness, where emerald/red does not; red is reserved for the single critical callout and is never used as a chart colour. "Planned" is a dashed outline rather than a fourth hue, since absence of status reads better as an outline than as grey fill.
Three layout details, each found by measuring the rendered page
w-full+min-w-0. It is a flex item, andmx-autosuppresses flex stretch, so the box stayed sized to the grid's 1180px min-content and pushed the whole page wider than the viewport — clipped by the globaloverflow-x: hidden— instead of letting the grid scroll on its own. This is what makes the page usable on mobile.min-w-0so a long single word wraps inside its bar rather than spilling into the next month.Wiring
Route added to the SEO registry (
routeSeo), the sitemap (INDEXABLE_ROUTES), the public-route allowlist, the no-JS crawler fallback, and the footer's product links.Verification
next buildclean;npx tsc --noEmitreports nothing in the new files