Skip to content

feat: move file-system routing from SolidStart into router-neutral packages#572

Draft
brenelz wants to merge 2 commits into
solidjs:mainfrom
brenelz:fs-routes
Draft

feat: move file-system routing from SolidStart into router-neutral packages#572
brenelz wants to merge 2 commits into
solidjs:mainfrom
brenelz:fs-routes

Conversation

@brenelz

@brenelz brenelz commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Implements the architecture refined by @ryansolid in #571shapes vs machinery, shared analysis / per-consumer emission — building on the pnpm workspace layout from #570 (this branch includes that PR's commit; the new work is the top commit).

What's in here

@solidjs/file-routes (new, router-neutral)

The machinery, ported from SolidStart's config/fs-routes:

  • Bundler-agnostic coreBaseFileSystemRouter scans a directory into a flat, neutral route manifest (paths in a neutral pattern language, module refs with export picks). No Vite imports in the core.
  • Pluggable conventionPageFileSystemRouter is exactly the convention Start has proven ([id], [[opt]], [...rest], (group), index, route export, md/mdx), overridable via toPath/toRoute or a custom router.
  • Export analysis behind its own seam (analyze.ts, oxc-parser) — the compiler-shaped slice, kept separable so a compiler that already reports exports can provide it instead.
  • Server conventions intentionally excludedGET/POST export handling stays in Start, which can extend PageFileSystemRouter.

@solidjs/file-routes/vite (delivery adapter)

  • Serves the manifest as the solid:file-routes virtual module: $-prefixed refs become code-split dynamic imports, $$-prefixed refs become static imports, each tree-shaken to the picked exports (?pick).
  • Watcher-driven HMR (add/change/remove routes without a restart).
  • routers: { client, ssr, ... } option keyed by Vite environment, so Start can compose it with different conventions per environment.

@solidjs/router/fs (emission adapter, new subpath export)

  • createFileRoutes(manifest) — nests the flat manifest by path prefix, strips (group) segments, merges route configs, emits lazy RouteDefinitions tagged info.filesystem.
  • <FileRoutes /> — the runtime component for <Router> children.
  • @solidjs/router does not depend on @solidjs/file-routes; the adapter only consumes the virtual module, so Start's bring-your-own-router story is preserved.

examples/file-routes

A plain Vite + Solid Router SPA (no Start) exercising the whole path — nested layout, index routes, params with typed route config + preload + createAsync, catch-all 404. Wired into the workspace so the root build doubles as an end-to-end check.

// vite.config.ts
plugins: [solid({ extensions: [".jsx", ".tsx"] }), fileRoutes()]
<Router root={Layout}>
  <FileRoutes />
</Router>

Notes for reviewers

  • Ported fixes: single-extension globs were treated as literal brace patterns by picomatch (*.{tsx}); the watcher used to invalidate the virtual module during the initial scan — routes are now pre-built before the reloader attaches.
  • solid({ extensions: [".jsx", ".tsx"] }) is required because vite-plugin-solid's dev filter tests the raw id, which the ?pick query defeats — same reason Start passes extensions. Could be fixed upstream in vite-plugin-solid.
  • The virtual module id is the neutral solid:file-routes (Start currently uses solid-start:routes); <FileRoutes> here is the SPA/client variant — Start keeps its per-request SSR variant and composes the rest.
  • Follow-up on the Start side: delete its fs-routes/ internals and rebase SolidStartServerFileRouter + config wiring onto @solidjs/file-routes.

Verification

  • 33 new @solidjs/file-routes tests (incl. ported solid-start specs for export analysis + tree-shaking) and 264 router tests (incl. new emission-adapter unit tests and a mounted <Router><FileRoutes/></Router> rendering test) — all passing.
  • arethetypeswrong green (esm-only profile) for both packages including the new subpaths.
  • Example verified live: dev server, client navigation, preload, HMR route add, and production build producing per-route chunks with route configs shaken out of component chunks.

🤖 Generated with Claude Code

birkskyum and others added 2 commits July 19, 2026 23:17
…ckages

Implements the architecture from discussion solidjs#571 (shared analysis,
per-consumer emission), building on the workspace layout from solidjs#570:

- @solidjs/file-routes: router-neutral core — bundler-agnostic scanning
  (BaseFileSystemRouter), the SolidStart-proven filename convention as a
  pluggable default (PageFileSystemRouter), route-module export analysis
  behind its own seam (oxc-parser), and a neutral route manifest as the
  emission seam. Server conventions (GET/POST exports) stay in Start.
- @solidjs/file-routes/vite: the Vite delivery adapter — serves the
  manifest as the solid:file-routes virtual module (lazy $-refs become
  code-split dynamic imports, eager $$-refs become static imports,
  tree-shaken per export via ?pick), with watcher-driven HMR and
  per-Vite-environment routers so Start can compose it.
- @solidjs/router/fs: Solid Router's emission adapter — createFileRoutes
  nests the flat manifest, strips (group) segments and merges route
  configs into lazy RouteDefinitions, and ships <FileRoutes />.
- examples/file-routes: a plain Vite + Solid Router SPA exercising the
  whole path (nested layout, params, preload, catch-all); wired into the
  workspace so the root build doubles as an end-to-end check.

Fixes found while porting: single-extension globs were treated as
literal brace patterns, and the watcher invalidated the virtual module
during the initial scan (routes are now pre-built before the reloader
attaches).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d1f2a86

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@solidjs/file-routes Minor
@solidjs/router Minor
example-file-routes Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@brenelz
brenelz marked this pull request as draft July 22, 2026 01:50
@brenelz
brenelz changed the base branch from main to next July 22, 2026 01:57
@brenelz
brenelz changed the base branch from next to main July 22, 2026 01:58
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.

2 participants