Skip to content

fix: strip the fs-routes root deterministically via a required base option#155

Merged
uhyo merged 3 commits into
masterfrom
claude/issue-139-x4u5te
Jul 19, 2026
Merged

fix: strip the fs-routes root deterministically via a required base option#155
uhyo merged 3 commits into
masterfrom
claude/issue-139-x4u5te

Conversation

@uhyo

@uhyo uhyo commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Closes #139

Problem

modulesToRouteFiles inferred the routes root as the longest common directory prefix of the import.meta.glob keys. When every page happened to live under one shared subdirectory, that subdirectory was treated as part of the routes root and stripped, shifting all routes up one level:

  • {"./pages/blog/page.tsx", "./pages/blog/post/page.tsx"} → routes / and /post instead of /blog and /blog/post
  • A single nested page {"./pages/docs/page.tsx"} → route / instead of /docs

Changes

  • createFsRoutesEntries now takes a required base option — the routes directory the glob keys are relative to (e.g. "./pages"). The prefix is stripped deterministically; matching is lenient about a trailing slash and a missing ./.
  • The plugin's fsRoutes mode passes its resolved routes directory (globBase) as base in the generated virtual:funstack/entries module, so plugin users are unaffected.
  • The common-prefix heuristic is removed entirely. A base that does not prefix every globbed key now fails the build with a clear error instead of silently guessing the routes root.
  • Unit tests cover both reproductions from the issue, the plugin's root-relative base form, the lenient matching, and the mismatch error.
  • Docs: the File-System Routing page now documents base for direct createFsRoutesEntries users.

Requiring base is a breaking change for direct createFsRoutesEntries users, but the fs-routes module is experimental and not covered by semantic versioning.

Verification

  • pnpm typecheck, pnpm test:run (81 tests), pnpm lint, pnpm format:check, pnpm build all pass
  • fs-routing e2e suite (9 tests) passes against a production build

🤖 Generated with Claude Code

https://claude.ai/code/session_01EV5Pn6mAHVvqBZHjFKUguA


Generated by Claude Code

claude added 3 commits July 19, 2026 09:56
modulesToRouteFiles inferred the routes root as the longest common
directory prefix of the import.meta.glob keys. When every page lived
under one shared subdirectory (e.g. only ./pages/blog/**), that
subdirectory was treated as part of the routes root and stripped,
shifting all routes up one level.

The plugin now passes its known routes directory (globBase) through to
createFsRoutesEntries as a new `base` option, which is stripped
deterministically. Direct users of createFsRoutesEntries can pass
`base` themselves; the common-prefix heuristic remains as a fallback
when base is omitted or does not prefix every key.

Closes #139

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EV5Pn6mAHVvqBZHjFKUguA
Since base is now always known (the plugin passes its resolved routes
directory, and direct users know the directory they globbed), the
common-prefix heuristic is removed entirely. A base that does not
prefix every globbed key now fails the build with a clear error
instead of silently guessing the routes root.

The fs-routes module is experimental and not covered by semantic
versioning, so this breaking change lands in a minor release.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EV5Pn6mAHVvqBZHjFKUguA
@uhyo
uhyo merged commit a31528a into master Jul 19, 2026
2 checks passed
@uhyo
uhyo deleted the claude/issue-139-x4u5te branch July 19, 2026 10:08
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.

fs-routes: common-prefix stripping can misdetect the routes root and shift all routes

2 participants