SvelteKit Routing and SSR

File-based Routing

SvelteKit uses a file-based routing system where files in the src/routes directory automatically become routes in your application.

Basic Route Structure

src/routes/
├── +page.svelte         # Home page (/)
├── about/
│   └── +page.svelte     # About page (/about)
├── blog/
│   ├── +page.svelte     # Blog index (/blog)
│   └── [slug]/          # Dynamic route
│       └── +page.svelte # Individual blog post (/blog/:slug)
        

Each +page.svelte file represents a page component that will be rendered for that route.

Dynamic Routes

SvelteKit supports dynamic route parameters using square brackets in the folder name.

Dynamic Route Examples

  • /users/[id] matches /users/123, /users/456, etc.
  • /products/[category]/[id] matches /products/books/svelte-book
  • /[...catchAll] matches any route and captures the rest of the path

Route Parameter Access

Access route parameters in the +page.svelte component via the $page.params store:

<script>
  import { page } from '$app/stores';
</script>

<h1>User ID: {$page.params.id}</h1>
        

Page Options

Control how pages are rendered using additional files:

SvelteKit Special Files

  • +page.svelte: The page component
  • +page.ts: Load data for the page
  • +page.server.ts: Load data server-side only
  • +layout.svelte: Layout component for the route and its children
  • +layout.ts: Load data for the layout
  • +error.svelte: Custom error page

Data Loading

SvelteKit provides a powerful data loading system through load functions.

Load Function Examples

Client and Server Data Loading

// +page.ts
export async function load({ params, fetch }) {
  const response = await fetch(`/api/posts/${params.slug}`);
  const post = await response.json();
  
  return { post };
}
        

Server-Only Data Loading

// +page.server.ts
export async function load({ params, locals }) {
  // Access server-only resources like databases
  const post = await db.getPost(params.slug);
  
  // Access server-only data like session info
  const user = locals.user;
  
  return { post, user };
}
        

In your +page.svelte component, you can access this data as props:

<script>
  export let data; // Contains the data returned by load functions
</script>

<h1>{data.post.title}</h1>
<p>Written by {data.user.name}</p>
        

Layouts

Layouts in SvelteKit allow you to share UI elements across multiple pages.

Layout Hierarchy

src/routes/
├── +layout.svelte     # Root layout (applies to all routes)
├── +page.svelte       # Home page
├── dashboard/
│   ├── +layout.svelte # Dashboard layout (nested)
│   ├── +page.svelte   # Dashboard index
│   └── settings/
│       └── +page.svelte # Settings page (gets both layouts)
        

Layout Components

<script>
  import Header from '$lib/Header.svelte';
  import Footer from '$lib/Footer.svelte';
  
  // You can access layout data
  export let data;
</script>

<Header user={data.user} />

<main>
  <slot></slot> <!-- Page content goes here -->
</main>

<Footer />
        

Server-Side Rendering (SSR)

SvelteKit provides several rendering options to optimize for performance and SEO.

Rendering Options

  • SSR (Server-Side Rendering): Pages are rendered on the server for each request, providing the best SEO and initial load experience.
  • CSR (Client-Side Rendering): Pages are rendered in the browser, useful for private pages that don't need SEO.
  • SSG (Static Site Generation): Pages are pre-rendered at build time, providing the fastest possible loading experience.
  • Hybrid Rendering: Mix and match approaches for different routes.

Configure Rendering in +page.ts

// SSR (default)
export const ssr = true;

// CSR (disable SSR)
export const ssr = false;

// SSG (prerender at build time)
export const prerender = true;

// For dynamic routes that should be prerendered
export const entries = () => [
  { slug: 'hello-world' },
  { slug: 'getting-started' }
];
        

Next Steps

Now that you understand SvelteKit routing and server-side rendering, check out: