---
title: Routing
sort: 100
section-id: core-concepts
keywords: routing, file-based routing, dynamic routes, catch-all, nested routes, navigation
description: How Velox's file-based routing works, including dynamic segments, catch-all routes, and nested layouts
language: en
---
# Routing
Velox uses a file-based routing system. The file tree under the `routes/` directory maps one-to-one to the URL structure of your application. There is no router configuration file — the filesystem is the configuration.
## Basic Routes
Any `.velox` or `.tsx` file placed inside `routes/` becomes a page route:
| File | URL |
|------|-----|
| `routes/index.velox` | `/` |
| `routes/about.velox` | `/about` |
| `routes/blog/index.velox` | `/blog` |
| `routes/blog/my-post.velox` | `/blog/my-post` |
| `routes/shop/shoes/index.velox` | `/shop/shoes` |
## Dynamic Segments
Wrap a path segment in square brackets to make it dynamic:
```
routes/
└── blog/
└── [slug].velox → /blog/:slug
```
Inside the route, access the parameter via the `params` object in the server block:
```tsx
---
const { slug } = params;
const post = await db.posts.findBySlug(slug);
if (!post) {
throw new NotFound();
}
export const meta = { title: post.title };
---
{post.title}
```
### Multiple Dynamic Segments
You can nest multiple dynamic segments:
```
routes/
└── [category]/
└── [slug].velox → /:category/:slug
```
## Optional Dynamic Segments
Wrap a segment in double square brackets to make it optional:
```
routes/
└── blog/
└── [[page]].velox → /blog and /blog/:page
```
Inside the route, `params.page` will be `undefined` when the segment is not present.
## Catch-All Routes
Use the spread syntax `[...rest]` to match any number of path segments:
```
routes/
└── docs/
└── [...path].velox → /docs/ and /docs/a/b/c/d
```
`params.path` is an array of path segments: `['a', 'b', 'c', 'd']`.
### Optional Catch-All
`[[...rest]]` matches zero or more segments (i.e., the base path also matches):
```
routes/
└── [[...slug]].velox → / and /anything/at/all
```
## API Routes
Files with a `+server.ts` or `+server.js` suffix define API endpoints. They export HTTP method handlers named `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, or `OPTIONS`:
```typescript
// routes/api/users+server.ts
import { defineHandler } from 'velox/server';
import { db } from '$lib/db';
export const GET = defineHandler(async (req) => {
const users = await db.users.findMany();
return Response.json(users);
});
export const POST = defineHandler(async (req) => {
const body = await req.json();
const user = await db.users.create({ data: body });
return Response.json(user, { status: 201 });
});
```
## Route Groups
Wrap a directory name in parentheses to create a route group. Groups do not affect the URL — they are purely an organisational tool:
```
routes/
└── (marketing)/
├── index.velox → /
├── about.velox → /about
└── pricing.velox → /pricing
└── _layout.velox ← layout applied only to marketing routes
```
This is useful when you want different layouts for different sections of your site without adding URL segments.
## Special Files
### `_layout.velox`
A `_layout.velox` file wraps all sibling routes and nested route directories. Layouts receive a `` where child content is injected:
```tsx
// routes/blog/_layout.velox
---
import Sidebar from '../../components/Sidebar.tsx';
---