Routing
Routes are defined by the folder structure of src/routes. Each folder maps to a URL path, and each file within it handles a part of the request:
/routes
/+page.ts → /
/about/+page.ts → /about
/posts/[id]/+page.ts → /posts/123
/api/posts/+server.ts → /api/posts Special files
+page.ts— the page endpoint: the component to render, plus an optional clientloadfunction+page.server.ts— a server-onlyloadfunction and formactions+server.ts— a plain HTTP endpoint (no UI) — see API Endpoints_layout.tsand_layout.server.ts— wrap every route in the folder and the folders below it_error.ts— the page shown when a request in the folder fails_hook.server.ts— runs before and after every request below it — see Hooks
Pages
A +page.ts exports the component to render, imported from src/views (or wherever you keep your components):
// routes/posts/[id]/+page.ts
import component from "@/views/Post.torp";
import { type PageEndPoint } from "@torpor/build";
export default {
component,
} satisfies PageEndPoint;
Annotate the endpoint with its route path to get typed params in load functions and URL builders, e.g. PageEndPoint<"/posts/[id]">.
Dynamic segments
Use square brackets for dynamic segments: [id] matches a single path segment, and [...path] matches the rest of the path. The values are passed to load functions and actions as strings via event.params.
Type-safe URLs
Build URLs with route instead of string concatenation. Params are checked at compile time and missing or unknown params are errors:
import { route } from "@torpor/build/nav";
route("/posts/[id]", { id: 5 }); // "/posts/5"
route("/posts/[id]"); // compile error: missing 'id'
Routes in code
For small sites, routes can be added in code instead of using the standard file names. Each option maps to a file route type, and inline server code is kept out of the client bundle automatically:
import { Site, ok } from "@torpor/build";
const site = new Site();
site.addRoute("/", {
page: "./src/Counter.torp",
pageServer: { actions: { set: async ({ request }) => ok() } },
});
site.addRoute("/api/time", {
server: { get: async () => ok({ time: Date.now() }) },
});