ConfigsApr 11, 2026·1 min read

SvelteKit — Streamlined Full-Stack Framework for Svelte

SvelteKit is the official full-stack framework for Svelte. File-based routing, SSR/SSG/CSR, server actions, and type-safe data loading — built on top of Vite for blazing-fast development.

AI
AI Open Source · Community
Quick Use

Use it first, then decide how deep to go

This block should tell both the user and the agent what to copy, install, and apply first.

# Create a new SvelteKit app
npm create svelte@latest my-app
cd my-app
npm install
npm run dev
Intro

SvelteKit is the official full-stack framework for Svelte, the compiler-based UI framework that rivals React and Vue. It provides file-based routing, server-side rendering, static site generation, server actions, and adapters for every major hosting platform — all built on top of Vite for blazing-fast development experience.

With 20.4K+ GitHub stars and MIT license, SvelteKit has become the go-to choice for developers who want the elegance of Svelte with a complete application framework. It consistently ranks among the most loved frameworks in developer surveys.

What SvelteKit Does

  • File-Based Routing: Routes defined by file structure in src/routes
  • SSR/SSG/CSR: Server-side rendering, static generation, or client-only rendering
  • Server Actions: Form submissions handled on the server with progressive enhancement
  • Load Functions: Type-safe server data loading for pages
  • Layouts: Nested layouts with shared data
  • API Routes: RESTful endpoints as file-based routes
  • Adapters: Deploy to Vercel, Netlify, Cloudflare, Node, static hosting
  • Hot Module Replacement: Instant updates via Vite
  • TypeScript: First-class TypeScript support
  • Link Prefetching: Automatic prefetching on hover

Project Structure

my-app/
├── src/
│   ├── routes/                 ← File-based routing
│   │   ├── +page.svelte       ← Home page
│   │   ├── +layout.svelte     ← Root layout
│   │   ├── about/
│   │   │   └── +page.svelte
│   │   └── blog/
│   │       ├── +page.svelte   ← Blog list
│   │       ├── +page.server.ts ← Server data loader
│   │       └── [slug]/
│   │           ├── +page.svelte
│   │           └── +page.server.ts
│   ├── lib/                   ← Shared utilities
│   │   ├── components/
│   │   └── db.ts
│   ├── app.html
│   └── hooks.server.ts        ← Server hooks (auth, etc.)
├── svelte.config.js
└── vite.config.js

Basic Components

Simple Page

<!-- src/routes/+page.svelte -->
<script lang="ts">
  let count = 0;

  function increment() {
    count++;
  }
</script>

<h1>Welcome to SvelteKit!</h1>
<button on:click={increment}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

<style>
  h1 {
    color: #ff3e00;
  }
</style>

Reactive Statements

<script lang="ts">
  let firstName = 'John';
  let lastName = 'Doe';

  // Reactive computed value
  $: fullName = `${firstName} ${lastName}`;

  // Reactive statement - runs on dependency change
  $: console.log(`Name changed to: ${fullName}`);

  // Can have conditions
  $: if (fullName.length > 20) {
    console.warn('Name is very long!');
  }
</script>

<input bind:value={firstName} />
<input bind:value={lastName} />
<p>Hello, {fullName}!</p>

Data Loading

Server Load Function

// src/routes/blog/+page.server.ts
import type { PageServerLoad } from './$types';
import { db } from '$lib/db';

export const load: PageServerLoad = async () => {
  const posts = await db.post.findMany({
    orderBy: { createdAt: 'desc' },
    take: 10,
  });

  return { posts };
};
<!-- src/routes/blog/+page.svelte -->
<script lang="ts">
  import type { PageData } from './$types';

  export let data: PageData;
  // data.posts is fully typed!
</script>

<h1>Blog Posts</h1>
<ul>
  {#each data.posts as post}
    <li>
      <a href="/blog/{post.slug}">{post.title}</a>
    </li>
  {/each}
</ul>

Dynamic Route

// src/routes/blog/[slug]/+page.server.ts
import type { PageServerLoad } from './$types';
import { error } from '@sveltejs/kit';

export const load: PageServerLoad = async ({ params }) => {
  const post = await db.post.findUnique({
    where: { slug: params.slug },
  });

  if (!post) {
    throw error(404, 'Post not found');
  }

  return { post };
};

Server Actions (Forms)

// src/routes/login/+page.server.ts
import type { Actions } from './$types';
import { fail, redirect } from '@sveltejs/kit';

export const actions: Actions = {
  default: async ({ request, cookies }) => {
    const data = await request.formData();
    const email = data.get('email');
    const password = data.get('password');

    if (!email || !password) {
      return fail(400, { email, missing: true });
    }

    const user = await authenticate(email, password);
    if (!user) {
      return fail(401, { email, incorrect: true });
    }

    cookies.set('session', user.sessionId, { path: '/' });
    throw redirect(303, '/dashboard');
  },
};
<!-- src/routes/login/+page.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  import type { ActionData } from './$types';

  export let form: ActionData;
</script>

<!-- Works without JavaScript! Progressive enhancement -->
<form method="POST" use:enhance>
  <input name="email" value={form?.email ?? ''} />
  {#if form?.missing}<p>Email required</p>{/if}

  <input name="password" type="password" />
  {#if form?.incorrect}<p>Invalid credentials</p>{/if}

  <button>Log in</button>
</form>

API Routes

// src/routes/api/users/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async ({ url }) => {
  const limit = Number(url.searchParams.get('limit') ?? '10');
  const users = await db.user.findMany({ take: limit });
  return json(users);
};

export const POST: RequestHandler = async ({ request }) => {
  const body = await request.json();
  const user = await db.user.create({ data: body });
  return json(user, { status: 201 });
};

Layouts

<!-- src/routes/+layout.svelte -->
<script>
  import '../app.css';
  import Header from '$lib/components/Header.svelte';
</script>

<Header />

<main>
  <slot /> <!-- Child pages render here -->
</main>

<footer>© 2024 My Site</footer>
<!-- src/routes/blog/+layout.svelte - nested layout -->
<div class="blog-layout">
  <aside>Blog sidebar</aside>
  <article>
    <slot />
  </article>
</div>

Deployment Adapters

// svelte.config.js - choose adapter
import adapter from '@sveltejs/adapter-auto';
// Or specific:
// import adapter from '@sveltejs/adapter-vercel';
// import adapter from '@sveltejs/adapter-netlify';
// import adapter from '@sveltejs/adapter-cloudflare';
// import adapter from '@sveltejs/adapter-node';
// import adapter from '@sveltejs/adapter-static';

export default {
  kit: {
    adapter: adapter(),
  },
};

Why Svelte?

Compiler-Based

Unlike React (virtual DOM) or Solid (signals), Svelte is a compiler. Components are compiled to highly optimized vanilla JavaScript at build time — no runtime framework needed.

Your Component (5KB)
  → Svelte Compiler
  → Optimized JS (2KB, no framework)

Svelte 5 (Runes)

<script>
  // New reactive primitives in Svelte 5
  let count = $state(0);
  let doubled = $derived(count * 2);

  $effect(() => {
    console.log('count changed:', count);
  });
</script>

<button onclick={() => count++}>
  {count} (doubled: {doubled})
</button>

SvelteKit vs Alternatives

Feature SvelteKit Next.js Nuxt Remix
Framework Svelte (compiler) React Vue React
Bundle size Smallest Medium Medium Medium
Routing File-based File-based (App Router) File-based File-based
Server actions Yes Yes Server handlers Yes
SSR/SSG/CSR All three All three All three Server-focused
Dev speed (Vite) Yes Turbopack Vite Vite
Learning curve Easy Medium Easy Medium
Deployment All major Vercel optimized All major All major

常见问题

Q: Svelte 和 React 哪个更好? A: Svelte 更简洁(更少的样板代码)、性能更好(编译后无运行时)、包体积更小。React 生态更大、人才更多、大型应用模式更成熟。对于新项目,Svelte 开发体验更好;对于企业级,React 更稳妥。

Q: Svelte 5 的 runes 是什么? A: Svelte 5 引入的新反应式原语($state、$derived、$effect),替换之前的 let + $: 语法。新 API 更明确,适合大型项目,与旧语法保持兼容。

Q: 适合什么项目? A: 任何 Web 项目:内容网站(SSG)、SaaS 应用(SSR)、管理后台(CSR)。SvelteKit 灵活性高,可以在同一应用中混合不同渲染模式。特别适合性能敏感和开发者体验优先的项目。

来源与致谢

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets