Routing
Bosia uses file-based routing. Files in src/routes/ map directly to URLs.
Static Routes
Section titled “Static Routes”src/routes/+page.svelte → /src/routes/about/+page.svelte → /aboutsrc/routes/blog/+page.svelte → /blogEach +page.svelte file becomes a page at its directory’s path.
Dynamic Routes
Section titled “Dynamic Routes”Wrap a directory name in brackets to create a dynamic segment:
src/routes/blog/[slug]/+page.svelte → /blog/hello-world /blog/my-post /blog/anythingAccess the matched value via params:
export async function load({ params }: LoadEvent) { const post = await getPost(params.slug); return { post };}Catch-All Routes
Section titled “Catch-All Routes”Use [...rest] to match multiple path segments:
src/routes/all/[...catchall]/+page.svelte → /all/a /all/a/b/c /all/anything/hereparams.catchall contains the full matched sub-path (e.g. "a/b/c").
Route Groups
Section titled “Route Groups”Directories wrapped in parentheses are invisible in the URL but let you share layouts:
src/routes/(public)/+layout.svelte ← shared layoutsrc/routes/(public)/+page.svelte → /src/routes/(public)/about/+page.svelte → /about
src/routes/(admin)/+layout.svelte ← different layoutsrc/routes/(admin)/dashboard/+page.svelte → /dashboardThe (public) and (admin) groups never appear in the URL. They only control which +layout.svelte wraps the pages inside.
Route Priority
Section titled “Route Priority”When multiple routes could match a URL, Bosia resolves them in order:
- Exact matches — static routes like
/about - Dynamic segments —
[param]routes - Catch-all —
[...rest]routes
Layouts
Section titled “Layouts”+layout.svelte wraps all pages and child layouts in its directory:
<script lang="ts"> import "../app.css"; let { children, data } = $props();</script>
<nav> <a href="/">Home</a> <a href="/about">About</a></nav>
<main> {@render children()}</main>Layouts nest automatically — the root layout wraps group layouts, which wrap page layouts. Child content renders where {@render children()} appears.
Layout Data
Section titled “Layout Data”Pair a layout with +layout.server.ts to load data:
import type { LoadEvent } from "bosia";
export async function load({ locals }: LoadEvent) { return { appName: "My App", user: locals.user, };}All child pages and layouts can access this data via parent() in their own loaders.
Error Pages
Section titled “Error Pages”Create +error.svelte to handle errors thrown by loaders:
<script lang="ts"> let { error } = $props();</script>
<h1>{error.status}</h1><p>{error.message}</p>The error page receives the HttpError thrown by error() in a loader. Place it at the route level where you want to catch errors — it catches errors from all child routes.