Skip to content
All essays
WebMarch 27, 202514 min

SvelteKit: The Complete Framework

Master SvelteKit for building modern web applications. Learn file-based routing, server-side rendering, and API routes.

Ü
Ümit Uz
Mobile & Full Stack Developer

SvelteKit is a full-stack web framework built on Svelte, providing server-side rendering, file-based routing, and excellent performance.

Why SvelteKit?

  • No virtual DOM - Compiled to vanilla JavaScript
  • Server-side rendering - Built-in SSR for SEO
  • File-based routing - Automatic route generation
  • API routes - Build full-stack applications
  • TypeScript support - First-class TypeScript
  • Great performance - Small bundle sizes

Getting Started

bash
npm create svelte@latest my-app
cd my-app
npm install
npm run dev

Directory Structure

my-app/
├── src/
│   ├── routes/         # File-based routing
│   ├── lib/            # Utility functions
│   └── app.html        # HTML template
├── static/             # Static assets
├── svelte.config.js    # Svelte configuration
└── vite.config.js      # Vite configuration

File-Based Routing

Basic Routes

svelte
<!-- src/routes/+page.svelte -->
<script>
  let name = 'World';
</script>

<h1>Hello {name}!</h1>

<!-- src/routes/about/+page.svelte -->
<h1>About Us</h1>
<p>This is the about page.</p>

Dynamic Routes

svelte
<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
  export let data;

  const { post } = data;
</script>

<h1>{post.title}</h1>
<div>{@html post.content}</div>

Layout Routes

svelte
<!-- src/routes/+layout.svelte -->
<script>
  import '../app.css';
</script>

<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
  <a href="/blog">Blog</a>
</nav>

<slot />

<footer>
  <p>© 2024 My App</p>
</footer>

Server-Side Data Loading

load Functions

javascript
// src/routes/+page.server.js
export async function load({ fetch }) {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  return {
    posts
  };
}

Universal load Functions

javascript
// src/routes/+page.js
export async function load({ fetch, page }) {
  const { limit = 10 } = page.params;

  const res = await fetch(`https://api.example.com/posts?limit=${limit}`);
  const posts = await res.json();

  return {
    posts
  };
}

Using Data in Components

svelte
<!-- src/routes/+page.svelte -->
<script>
  export let data;

  const { posts } = data;
</script>

{#each posts as post}
  <article>
    <h2>{post.title}</h2>
    <p>{post.excerpt}</p>
  </article>
{/each}

API Routes

GET Endpoint

javascript
// src/routes/api/posts/+server.js
export async function GET({ url }) {
  const limit = url.searchParams.get('limit') || 10;

  const posts = await db.posts.findMany({
    take: limit
  });

  return new Response(JSON.stringify(posts), {
    headers: {
      'Content-Type': 'application/json'
    }
  });
}

POST Endpoint

javascript
// src/routes/api/posts/+server.js
export async function POST({ request }) {
  const data = await request.json();

  const post = await db.posts.create({
    data: {
      title: data.title,
      content: data.content
    }
  });

  return new Response(JSON.stringify(post), {
    status: 201,
    headers: {
      'Content-Type': 'application/json'
    }
  });
}

Form Handling

Form Actions

svelte
<!-- src/routes/contact/+page.svelte -->
<script>
  export let form;

  let success = false;
</script>

{#if form?.success}
  <p>Message sent successfully!</p>
{/if}

{#if form?.error}
  <p>{form.error}</p>
{/if}

<form method="POST">
  <label>
    Name:
    <input type="text" name="name" required />
  </label>

  <label>
    Email:
    <input type="email" name="email" required />
  </label>

  <label>
    Message:
    <textarea name="message" required></textarea>
  </label>

  <button type="submit">Send</button>
</form>
javascript
// src/routes/contact/+page.server.js
export const actions = {
  default: async ({ request }) => {
    const data = await request.formData();
    const name = data.get('name');
    const email = data.get('email');
    const message = data.get('message');

    try {
      await sendEmail({ name, email, message });
      return { success: true };
    } catch (error) {
      return { error: 'Failed to send message' };
    }
  }
};

Error Handling

Error Pages

svelte
<!-- src/routes/error/+error.svelte -->
<script>
  export let status;
  export let error;
</script>

<h1>{status}</h1>
<p>{error.message}</p>

<a href="/">Go Home</a>

Configuration

svelte.config.js

javascript
import adapter from '@sveltejs/adapter-auto';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    adapter: adapter(),

    alias: {
      $lib: 'src/lib',
      $components: 'src/components'
    }
  }
};

export default config;

Stores

Writable Stores

javascript
// src/lib/stores/user.js
import { writable } from 'svelte/store';

export const user = writable(null);

export function login(userData) {
  user.set(userData);
}

export function logout() {
  user.set(null);
}

Using Stores

svelte
<script>
  import { user } from '$lib/stores/user';
</script>

{#if $user}
  <p>Welcome, {$user.name}!</p>
  <button on:click={logout}>Logout</button>
{:else}
  <button on:click={login}>Login</button>
{/if}

Deployment

Build for Production

bash
npm run build

Deploy to Vercel

bash
npm install -g vercel
vercel

SvelteKit provides a complete solution for building modern web applications with excellent performance and developer experience.

Related essays

Next essay
Svelte Stores: State Management Guide