Routing
Choose a manual route table or flat files. Both produce the same route objects.
Compatibility
Manual paths
Static segments match exactly; :id captures one non-empty segment; a terminal * captures the remaining path. One trailing slash is ignored. Query strings do not select routes. First match wins.
const routes = [
defineRoute("/tasks/search", search),
defineRoute("/tasks/:id", detail),
defineRoute("/files/*", files),
];Flat files
The Vite plugin discovers immediate route folders or flat module files. Dots create URL segments, $id creates a parameter, and a terminal $ creates a splat. _index is an index route. Leading underscore segments are pathless; trailing underscores are removed. These are URL conventions, not nested component layouts.
src/routes/_index/route.ts → /
src/routes/tasks._index/route.ts → /tasks
src/routes/tasks.search/route.ts → /tasks/search
src/routes/tasks.$id/route.ts → /tasks/:id
src/routes/files.$/route.ts → /files/*Enable the plugin
Install Vite 8 or newer. Import the generated route table from the virtual module. Re-export server handlers from separate files so server implementation code can be excluded from browser builds.
import { defineConfig } from "vite";
import { fileRouter } from "@kasperrt/smolter/react/vite";
export default defineConfig({
plugins: [fileRouter({ directory: "src/routes" })],
});
// main.ts
import routes from "virtual:smolter/routes";Limits
File routing does not support arbitrary directory nesting, optional segments, parentheses, bracket escapes, or nested layout rendering. Duplicate or ambiguous parameter patterns return an error. Manual ordering remains your responsibility; file discovery sorts static routes ahead of dynamic routes.