---
title: Routing
description: How Statue handles routing for markdown content
icon: map
---
# Routing
Statue extends SvelteKit's routing to automatically create pages from markdown files. This guide covers Statue-specific routing behavior.
> **Contribute to Statue!** Built a useful component, theme, or template? Share it with the community—it only takes a single command. **[Learn how →](https://github.com/accretional/statue/blob/main/CONTRIBUTING.md)**
> **New to SvelteKit routing?** Read the [SvelteKit Routing docs](https://svelte.dev/docs/kit/routing) first for the basics.
---
## Two Types of Routes
### 1. Content Routes (Automatic)
Markdown files in `content/` become pages automatically:
```
content/blog/my-post.md → /blog/my-post
content/docs/guide.md → /docs/guide
content/about.md → /about
```
Statue handles this automatically - no route files needed.
### 2. Custom Routes (Manual)
Standard SvelteKit routes in `src/routes/`:
```
src/routes/pricing/+page.svelte → /pricing
src/routes/contact/+page.svelte → /contact
```
Full control over the page. **[Learn more →](https://svelte.dev/docs/kit/routing)**
---
## How Content Routing Works
Statue uses two special catch-all routes to handle markdown content:
### `[...slug]/+page.svelte`
Renders individual markdown pages.
**Matches:**
- `/blog/hello-world` → `content/blog/hello-world.md`
- `/docs/guide` → `content/docs/guide.md`
- `/about` → `content/about.md`
**How it works:**
1. User visits `/blog/hello-world`
2. SvelteKit matches the `[...slug]` route
3. `+page.server.js` looks up `content/blog/hello-world.md`
4. Markdown is parsed and rendered
### `[directory]/+page.svelte`
Lists all content in a directory.
**Matches:**
- `/blog` → Lists all files in `content/blog/`
- `/docs` → Lists all files in `content/docs/`
**How it works:**
1. User visits `/blog`
2. SvelteKit matches the `[directory]` route
3. `+page.server.js` finds all `*.md` files in `content/blog/`
4. Renders as a list of posts
---
## Route Priority
When routes conflict, SvelteKit follows this priority:
1. **Static routes** (e.g., `src/routes/about/+page.svelte`)
2. **Dynamic routes** (e.g., `src/routes/[directory]/+page.svelte`)
3. **Catch-all routes** (e.g., `src/routes/[...slug]/+page.svelte`)
### Example Conflict
If you have both:
- `src/routes/about/+page.svelte` (custom Svelte page)
- `content/about.md` (markdown content)
The Svelte page wins - the markdown won't be shown.
**Fix:** Either remove the Svelte file or rename the markdown file.
---
## Customizing Content Pages
You can customize how markdown content is displayed by editing Statue's route templates.
### Content Pages Template
**File:** `src/routes/[...slug]/+page.svelte`
**What you must include:**
```svelte
```
**Typical customization:**
```svelte
```
**Available in `data.content`:**
- `metadata.title` - From frontmatter
- `metadata.description` - From frontmatter
- `metadata.date` - From frontmatter
- `content` - Rendered HTML
### Directory Pages Template
**File:** `src/routes/[directory]/+page.svelte`
**What you must include:**
```svelte
```
**Typical customization:**
```svelte
```
**Available in `data`:**
- `currentDirectory` - Info about this directory
- `directoryContent` - Array of content items
- `subDirectories` - Subdirectories in this directory
**Don't modify `+page.server.js` files unless you know what you're doing** - they contain the logic that loads markdown content.
---
## URL Structure
### Content → URL Mapping
```
content/blog/hello.md → /blog/hello
content/docs/guides/intro.md → /docs/guides/intro
content/projects/2024/project.md → /projects/2024/project
```
The folder structure becomes the URL structure.
### Best Practices
**Use descriptive URLs:**
```
✅ /blog/getting-started-with-statue
❌ /blog/post1
```
**Use hyphens, not underscores:**
```
✅ my-blog-post.md
❌ my_blog_post.md
```
**Keep it simple:**
```
✅ /docs/routing
❌ /documentation/advanced-concepts/routing-system
```
---
## Creating Custom Routes
When creating custom pages for your Statue site, follow these patterns:
### Required: Enable Prerendering
**In every `+page.server.js`, you must include:**
```javascript
export const prerender = true;
```
**Why:** Statue generates static sites. Without this, SvelteKit won't generate the HTML files at build time.
### Typical Data Loading Pattern
**For custom pages that need data, use this pattern:**
```javascript
// src/routes/pricing/+page.server.js
export const prerender = true;
export function load() {
// Load your data here
const plans = [
{ name: 'Free', price: 0 },
{ name: 'Pro', price: 29 }
];
return { plans };
}
```
**Why:** The `load` function runs at build time and passes data to your page component.
### Page Component
```svelte
Pricing
{#each data.plans as plan}
{plan.name}: ${plan.price}/mo
{/each}
```
**Want to do something different?** Check [SvelteKit's routing docs](https://svelte.dev/docs/kit/routing) for other patterns, but note that Statue requires static prerendering to work.
---
## Common Issues
### 404 on existing markdown file
**Check:**
1. File is in `content/` directory?
2. Has `.md` extension?
3. Restarted dev server? (`npm run dev`)
### Custom route not working
See [SvelteKit routing docs](https://svelte.dev/docs/kit/routing) for route setup.
### Changes not appearing
Clear SvelteKit cache:
```bash
rm -rf .svelte-kit build
npm run dev
```
---
## Learn More
### Statue Docs
- **[Statue.dev](https://statue.dev)** - Official documentation
- **[Get Started](./get-started.md)** - Overview
- **[Site Config](./site-config.md)** - Configuration
- **[Components](./components.md)** - Build pages
### SvelteKit Docs
- **[Routing](https://svelte.dev/docs/kit/routing)** - File-based routing basics
- **[Loading Data](https://svelte.dev/docs/kit/load)** - Server data loading
- **[Advanced Routing](https://svelte.dev/docs/kit/advanced-routing)** - Layouts, groups, matchers