Skip to content

feat(web): typed routes — broken internal links are now compile errors - #115

Merged
okieselbach merged 1 commit into
mainfrom
chore/web-typed-routes
Jul 30, 2026
Merged

feat(web): typed routes — broken internal links are now compile errors#115
okieselbach merged 1 commit into
mainfrom
chore/web-typed-routes

Conversation

@okieselbach

Copy link
Copy Markdown
Owner

Summary

Enables typedRoutes: true (stable in Next 16). A typo''d <Link>/router.push target now fails the build instead of 404ing at runtime — the failure class behind the recent RSC/routing incidents. The CI foundation (next typegen before tsc) already ships since #114.

  • lib/routes.ts registry: helpers return Route; withQuery validates the base path literal at compile time
  • New route() — identity helper that compile-checks dynamic [section] literals (nav configs, section index redirects) via type inference
  • New trustedRoute() — the single named seam for runtime-data hrefs (backend-emitted notification deep links, persisted post-login return URL); no scattered as Route casts
  • New deviceBlockUrl() — OpsEventsSection previously hand-built /admin/security/device-block against the registry rule
  • Nav types (NavItem, ExpandableSubItem, PageSectionItem) carry Route hrefs — every sidebar/navbar entry is compile-checked; ClientRedirect is generic so dynamic-section literals infer

Verification

  • tsc --noEmit clean; negative test: typo''d static AND dynamic routes fail compilation (incl. "Did you mean ''/sessions''?")
  • vitest 611/611
  • Static export builds with an unchanged route list (typedRoutes is compile-time only)

🤖 Generated with Claude Code

typedRoutes: true (stable in Next 16; `next typegen` already runs in CI
before tsc since #114). A typo'd <Link>/router.push target now fails the
build instead of 404ing at runtime — the failure class behind the recent
RSC/routing incidents.

- lib/routes.ts: registry helpers return `Route`; withQuery validates the
  base path literal. New: deviceBlockUrl (OpsEventsSection previously
  hand-built /admin/security/device-block against the registry rule),
  route() to compile-check dynamic-section literals (nav configs,
  section index redirects), trustedRoute() as the single named seam for
  runtime-data hrefs (backend-emitted notification deep links, persisted
  post-login return URL).
- Nav types (NavItem, ExpandableSubItem, PageSectionItem) carry Route
  hrefs — every sidebar/navbar entry is compile-checked.
- ClientRedirect is generic so dynamic-section literals infer.

Verified: tsc clean; negative test (typo'd static + dynamic routes)
fails compilation as intended; 611/611 vitest; static export builds
with an unchanged route list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@okieselbach
okieselbach merged commit d65157a into main Jul 30, 2026
8 of 9 checks passed
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