jpskill.com
🛠️ 開発・MCP コミュニティ

web-meta-framework-sveltekit

SvelteKitは、ファイルベースのルーティングやデータ読み込み、フォーム処理、サーバー処理など、Webサイトに必要な機能をまとめて提供し、高速な表示やAPI作成を支援するSkill。

📜 元の英語説明(参考)

SvelteKit full-stack framework - file-based routing, load functions, form actions, server hooks, SSR/SSG, API routes, streaming, progressive enhancement

🇯🇵 日本人クリエイター向け解説

一言でいうと

SvelteKitは、ファイルベースのルーティングやデータ読み込み、フォーム処理、サーバー処理など、Webサイトに必要な機能をまとめて提供し、高速な表示やAPI作成を支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o web-meta-framework-sveltekit.zip https://jpskill.com/download/10296.zip && unzip -o web-meta-framework-sveltekit.zip && rm web-meta-framework-sveltekit.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10296.zip -OutFile "$d\web-meta-framework-sveltekit.zip"; Expand-Archive "$d\web-meta-framework-sveltekit.zip" -DestinationPath $d -Force; ri "$d\web-meta-framework-sveltekit.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して web-meta-framework-sveltekit.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → web-meta-framework-sveltekit フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

SvelteKit パターン

クイックガイド: SvelteKit は Svelte のためのフルスタックフレームワークです。サーバー側のデータには +page.server.ts のロード関数を、プログレッシブエンハンスメントを用いたミューテーションにはフォームアクションを、API ルートには +server.ts を使用します。データはロード関数から data プロパティを介してコンポーネントに流れます。クライアント側のプログレッシブエンハンスメントには、フォームで use:enhance を使用します。


<critical_requirements>

重要: この Skill を使用する前に

すべてのコードは CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case, 名前付きエクスポート, インポート順, import type, 名前付き定数)

(データベースアクセス、シークレット、または Cookie を必要とするデータには、必ずサーバーロード関数 (+page.server.ts) を使用してください)

(ミューテーションには必ずフォームアクションを使用してください — フォーム送信に API ルートを使用しないでください)

(バリデーションエラーには、@sveltejs/kitfail() を必ず使用してください — バリデーションでエラーをスローしないでください)

(サーバーですべての入力データを必ず検証してください — クライアント側の検証はセキュリティ上不十分です)

(型安全なロード関数とページプロパティには、必ず自動生成された $types を使用してください)

(プログレッシブエンハンスメントには、フォームで必ず use:enhance を使用してください — フォームは JavaScript なしで動作するはずです)

(try/catch で redirect() をキャッチしないでください — これは SvelteKit が処理する特別な例外をスローします)

</critical_requirements>


自動検出: SvelteKit, +page.svelte, +page.ts, +page.server.ts, +layout.svelte, +layout.ts, +layout.server.ts, +error.svelte, +server.ts, load function, form actions, use:enhance, hooks.server.ts, hooks.client.ts, hooks.ts, handle hook, handleFetch, handleError, handleValidationError, init hook, reroute, transport hook, $app/navigation, $app/forms, $app/state, PageLoad, PageServerLoad, LayoutLoad, LayoutServerLoad, RequestHandler, fail, redirect, error, .remote.ts

使用する場面:

  • ファイルベースルーティングによる SvelteKit アプリケーションの構築
  • サーバーまたはユニバーサルロード関数によるページのデータ読み込み
  • フォームアクションとプログレッシブエンハンスメントによるフォーム送信の処理
  • +server.ts ルートによる API エンドポイントの作成
  • 認証、ロギング、またはリクエストの変更のためのサーバーフックの実装
  • SSR、SSG、またはプリレンダリング戦略の設定

カバーする主要なパターン:

  • ファイルベースルーティング (+page.svelte, +layout.svelte, +error.svelte)
  • サーバーロード関数 (+page.server.ts, +layout.server.ts)
  • ユニバーサルロード関数 (+page.ts, +layout.ts)
  • バリデーションとプログレッシブエンハンスメントによるフォームアクション
  • サーバーフック (handle, handleFetch, handleError, handleValidationError, init), ユニバーサルルフック (reroute, transport)
  • API ルート (+server.ts) とストリーミングレスポンス
  • ページオプション (prerender, ssr, csr)
  • データの無効化とロード関数の再実行

使用しない場面:

  • Svelte 5 コンポーネントパターン (Runes, snippets, events) — web-framework-svelte を使用
  • SvelteKit ルーティングなしの純粋なクライアント側 Svelte
  • 一般的な React/Next.js パターン — 適切なフレームワーク Skill を使用

詳細なリソース:

  • 意思決定フレームワークとアンチパターンについては、reference.md を参照してください。

ルーティングとデータ:

  • examples/core.md - ファイルベースルーティング, +page.svelte, +layout.svelte, +error.svelte, 動的ルート
  • examples/load-functions.md - サーバーロード, ユニバーサルロード, ストリーミング, 親データ, 無効化

ミューテーションとフォーム:

  • examples/form-actions.md - フォームアクション, use:enhance, fail() によるバリデーション, リダイレクト

サーバー:

  • examples/hooks.md - handle, handleFetch, handleError, init, reroute, transport, sequence, 認証パターン
  • examples/api-routes.md - +server.ts API ルート, ストリーミング, コンテンツネゴシエーション

<philosophy>

哲学

SvelteKit は、ルーティング、サーバーサイドレンダリング、データローディング、およびフォーム処理を処理する Svelte 上に構築された フルスタックフレームワーク です。これは、ネイティブの Request/ResponseFormData、およびプログレッシブエンハンスメントを使用して、Web プラットフォームの標準を採用しています。

コア原則:

  1. ファイルベースルーティング — ディレクトリ構造が URL 構造を定義します。特別なファイル (+page.svelte, +layout.svelte など) が動作を定義します。
  2. サーバーファーストのデータローディング — ロード関数は、初期リクエストのためにサーバー上で実行され、レンダリング前にデータを提供します。
  3. プログレッシブエンハンスメント — フォームは JavaScript なしで動作します。use:enhance は、その上にクライアント側の動作を追加します。
  4. 関心の分離 — ロード関数はデータをフェッチし、フォームアクションはミューテーションを処理し、フックはクロス カッティングな関心を処理します。
  5. 型安全性 — 自動生成された $types は、型安全なロード関数、ページプロパティ、およびフォームデータを提供します。
  6. Web 標準RequestResponseURLHeadersFormData — 標準の Web API 上に構築されています。

SvelteKit のデータフロー:

Request → hooks.server.ts (handle) → +layout.server.ts (load) → +page.server.ts (load) → +page.svelte (render)
                                                                                         ← form actions (POST)

SvelteKit を使用する場面:

  • ルーティングを備えたフルスタック Web アプリケーション
  • SEO 要件のあるサーバーレンダリングされたページ
  • プログレッシブエンハンスメントを備えたフォームヘビーなアプリケーション
  • ページレンダリングと並行した API バックエンド
  • プリレンダリングによる静的サイト生成 (SSG)

使用しない場面:

  • ルーティングのないクライアントのみのシングルページアプリ (Svelte を直接使用)
  • 純粋な API サーバー (専用の API フレームワークを使用)
  • 他のフレームワークに埋め込まれたマイクロフロントエンド

</philosophy>


<patterns>

コアパターン

パターン 1: ファイルベースルーティング

SvelteKit は、src/routes/ のディレクトリが URL パスを定義し、特別なファイルが動作を定義する、ファイルシステムベースのルーティングを使用します。

ファイルの規約

ファイル 目的 実行場所
+page.svelte ページコンポーネント (UI) サーバー (SSR) + クライアント

(原文がここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

SvelteKit Patterns

Quick Guide: SvelteKit is the full-stack framework for Svelte. Use +page.server.ts load functions for server-side data, form actions for mutations with progressive enhancement, and +server.ts for API routes. Data flows from load functions to components via the data prop. Use use:enhance on forms for client-side progressive enhancement.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use server load functions (+page.server.ts) for data requiring database access, secrets, or cookies)

(You MUST use form actions for mutations — NOT API routes for form submissions)

(You MUST use fail() from @sveltejs/kit for validation errors — NEVER throw errors for validation)

(You MUST validate all input data on the server — client-side validation is NOT sufficient for security)

(You MUST use the auto-generated $types for type-safe load functions and page props)

(You MUST use use:enhance on forms for progressive enhancement — forms should work without JavaScript)

(You MUST NOT catch redirect() in try/catch — it throws a special exception SvelteKit handles)

</critical_requirements>


Auto-detection: SvelteKit, +page.svelte, +page.ts, +page.server.ts, +layout.svelte, +layout.ts, +layout.server.ts, +error.svelte, +server.ts, load function, form actions, use:enhance, hooks.server.ts, hooks.client.ts, hooks.ts, handle hook, handleFetch, handleError, handleValidationError, init hook, reroute, transport hook, $app/navigation, $app/forms, $app/state, PageLoad, PageServerLoad, LayoutLoad, LayoutServerLoad, RequestHandler, fail, redirect, error, .remote.ts

When to use:

  • Building SvelteKit applications with file-based routing
  • Loading data for pages with server or universal load functions
  • Handling form submissions with form actions and progressive enhancement
  • Creating API endpoints with +server.ts routes
  • Implementing server hooks for auth, logging, or request modification
  • Configuring SSR, SSG, or prerendering strategies

Key patterns covered:

  • File-based routing (+page.svelte, +layout.svelte, +error.svelte)
  • Server load functions (+page.server.ts, +layout.server.ts)
  • Universal load functions (+page.ts, +layout.ts)
  • Form actions with validation and progressive enhancement
  • Server hooks (handle, handleFetch, handleError, handleValidationError, init), universal hooks (reroute, transport)
  • API routes (+server.ts) and streaming responses
  • Page options (prerender, ssr, csr)
  • Data invalidation and rerunning load functions

When NOT to use:

  • Svelte 5 component patterns (Runes, snippets, events) — use web-framework-svelte
  • Pure client-side Svelte without SvelteKit routing
  • General React/Next.js patterns — use the appropriate framework skill

Detailed Resources:

  • For decision frameworks and anti-patterns, see reference.md

Routing & Data:

Mutations & Forms:

Server:


<philosophy>

Philosophy

SvelteKit is a full-stack framework built on Svelte that handles routing, server-side rendering, data loading, and form handling. It embraces web platform standards — using native Request/Response, FormData, and progressive enhancement.

Core principles:

  1. File-based routing — Directory structure defines URL structure. Special files (+page.svelte, +layout.svelte, etc.) define behavior.
  2. Server-first data loading — Load functions run on the server for initial requests, providing data before rendering.
  3. Progressive enhancement — Forms work without JavaScript. use:enhance adds client-side behavior on top.
  4. Separation of concerns — Load functions fetch data, form actions handle mutations, hooks handle cross-cutting concerns.
  5. Type safety — Auto-generated $types provide type-safe load functions, page props, and form data.
  6. Web standards — Built on Request, Response, URL, Headers, FormData — standard web APIs.

Data flow in SvelteKit:

Request → hooks.server.ts (handle) → +layout.server.ts (load) → +page.server.ts (load) → +page.svelte (render)
                                                                                         ← form actions (POST)

When to use SvelteKit:

  • Full-stack web applications with routing
  • Server-rendered pages with SEO requirements
  • Form-heavy applications with progressive enhancement
  • API backends alongside page rendering
  • Static site generation (SSG) with prerendering

When NOT to use:

  • Client-only single-page apps without routing (use Svelte directly)
  • Pure API servers (use a dedicated API framework)
  • Micro-frontends embedded in other frameworks

</philosophy>


<patterns>

Core Patterns

Pattern 1: File-Based Routing

SvelteKit uses filesystem-based routing where directories in src/routes/ define URL paths and special files define behavior.

File Conventions

File Purpose Runs On
+page.svelte Page component (UI) Server (SSR) + Client
+page.ts Universal load function Server + Client
+page.server.ts Server load function + form actions Server only
+layout.svelte Shared layout wrapper Server (SSR) + Client
+layout.ts Universal layout load Server + Client
+layout.server.ts Server layout load Server only
+error.svelte Error boundary Server (SSR) + Client
+server.ts API route (GET, POST, etc.) Server only

Route Structure

src/routes/
├── +layout.svelte          # Root layout
├── +page.svelte            # Home page (/)
├── +error.svelte           # Root error boundary
├── about/
│   └── +page.svelte        # /about
├── blog/
│   ├── +page.svelte        # /blog (list)
│   ├── +page.server.ts     # Load blog posts
│   └── [slug]/
│       ├── +page.svelte    # /blog/:slug (detail)
│       └── +page.server.ts # Load single post
├── dashboard/
│   ├── +layout.svelte      # Dashboard layout (sidebar)
│   ├── +layout.server.ts   # Auth check for all dashboard pages
│   ├── +page.svelte        # /dashboard
│   └── settings/
│       └── +page.svelte    # /dashboard/settings
├── (marketing)/             # Route group (no URL segment)
│   ├── +layout.svelte      # Marketing-specific layout
│   ├── pricing/
│   │   └── +page.svelte    # /pricing
│   └── features/
│       └── +page.svelte    # /features
└── api/
    └── health/
        └── +server.ts      # GET /api/health

Why this works: File conventions eliminate routing configuration, layouts nest automatically, route groups organize without affecting URLs


Pattern 2: Server Load Functions

Server load functions (+page.server.ts) run only on the server. Use for database access, secrets, and cookie-based auth.

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

const POSTS_PER_PAGE = 10;

export const load: PageServerLoad = async ({ url, locals }) => {
  // Access query params
  const page = Number(url.searchParams.get("page") ?? "1");

  // Access server-only data (locals set in hooks)
  if (!locals.user) {
    error(401, "Not authenticated");
  }

  // Fetch from database (server-only)
  const offset = (page - 1) * POSTS_PER_PAGE;
  const [posts, total] = await Promise.all([
    db.post.findMany({
      take: POSTS_PER_PAGE,
      skip: offset,
      orderBy: { createdAt: "desc" },
    }),
    db.post.count(),
  ]);

  return {
    posts,
    pagination: {
      page,
      totalPages: Math.ceil(total / POSTS_PER_PAGE),
    },
  };
};
<!-- src/routes/blog/+page.svelte -->
<script lang="ts">
  import type { PageProps } from './$types';

  let { data }: PageProps = $props();
</script>

<h1>Blog</h1>

{#each data.posts as post}
  <article>
    <h2><a href="/blog/{post.slug}">{post.title}</a></h2>
    <p>{post.excerpt}</p>
  </article>
{/each}

<nav>
  {#if data.pagination.page > 1}
    <a href="?page={data.pagination.page - 1}">Previous</a>
  {/if}
  {#if data.pagination.page < data.pagination.totalPages}
    <a href="?page={data.pagination.page + 1}">Next</a>
  {/if}
</nav>

Why good: Server-only code (database access), type-safe with auto-generated $types, named constant for pagination, parallel data fetching with Promise.all


Pattern 3: Universal Load Functions

Universal load functions (+page.ts) run on both server and client. Use for external APIs that don't need secrets.

// src/routes/weather/+page.ts
import { error } from "@sveltejs/kit";
import type { PageLoad } from "./$types";

export const load: PageLoad = async ({ fetch, params }) => {
  // SvelteKit's fetch: works on server and client, inherits cookies
  const response = await fetch(`https://api.weather.com/forecast?city=london`);

  if (!response.ok) {
    error(response.status, "Failed to load weather data");
  }

  const forecast = await response.json();

  return { forecast };
};

Why good: fetch from SvelteKit works on both server (SSR) and client (navigation), auto-deduplicates on the client, inherits cookies for authenticated APIs

When to use: External public APIs, data that doesn't require server secrets

When not to use: Database access, private environment variables, cookie manipulation — use +page.server.ts


Pattern 4: Layout Load Functions

Layout load functions provide data to all child pages in the route segment.

// src/routes/dashboard/+layout.server.ts
import { redirect } from "@sveltejs/kit";
import type { LayoutServerLoad } from "./$types";

export const load: LayoutServerLoad = async ({ cookies, locals }) => {
  // Auth check for all dashboard routes
  if (!locals.user) {
    redirect(303, "/login");
  }

  // Data available to all dashboard pages
  const notifications = await db.notification.findMany({
    where: { userId: locals.user.id, read: false },
  });

  return {
    user: locals.user,
    notifications,
  };
};
<!-- src/routes/dashboard/+layout.svelte -->
<script lang="ts">
  import type { LayoutProps } from './$types';

  let { data, children }: LayoutProps = $props();
</script>

<div class="dashboard">
  <aside class="sidebar">
    <nav>
      <a href="/dashboard">Overview</a>
      <a href="/dashboard/settings">Settings</a>
    </nav>
    <p>Welcome, {data.user.name}</p>
    <span class="badge">{data.notifications.length} unread</span>
  </aside>

  <main>
    {@render children()}
  </main>
</div>

Why good: Auth check runs for all dashboard child pages, layout data cascades to children, redirect throws for unauthenticated users, Svelte 5 {@render children()} for layout slot


Pattern 5: Form Actions

Form actions handle POST requests in +page.server.ts. They enable progressive enhancement — forms work without JavaScript.

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

const MIN_PASSWORD_LENGTH = 8;

export const load: PageServerLoad = async ({ locals }) => {
  if (locals.user) {
    redirect(303, "/dashboard");
  }
};

export const actions: Actions = {
  login: async ({ request, cookies }) => {
    const data = await request.formData();
    const email = data.get("email")?.toString() ?? "";
    const password = data.get("password")?.toString() ?? "";

    // Validation
    if (!email) {
      return fail(400, { email, missing: true, message: "Email is required" });
    }

    if (password.length < MIN_PASSWORD_LENGTH) {
      return fail(400, {
        email,
        invalid: true,
        message: `Password must be at least ${MIN_PASSWORD_LENGTH} characters`,
      });
    }

    // Authentication (defer to your auth solution)
    const user = await authenticateUser(email, password);

    if (!user) {
      return fail(400, {
        email,
        invalid: true,
        message: "Invalid credentials",
      });
    }

    // Set session cookie
    cookies.set("session", user.sessionId, {
      path: "/",
      httpOnly: true,
      sameSite: "lax",
      secure: true,
      maxAge: 60 * 60 * 24 * 30, // 30 days
    });

    redirect(303, "/dashboard");
  },

  register: async ({ request }) => {
    // Named action for registration
    const data = await request.formData();
    // ... registration logic
  },
};
<!-- src/routes/login/+page.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  import type { PageProps } from './$types';

  let { form }: PageProps = $props();
</script>

<h1>Login</h1>

{#if form?.message}
  <p class="error" role="alert">{form.message}</p>
{/if}

<form method="POST" action="?/login" use:enhance>
  <label>
    Email
    <input
      type="email"
      name="email"
      value={form?.email ?? ''}
      required
    />
  </label>

  <label>
    Password
    <input
      type="password"
      name="password"
      required
    />
  </label>

  <button type="submit">Log in</button>
  <button type="submit" formaction="?/register">Register</button>
</form>

Why good: fail() returns validation errors without clearing form data, form prop shows returned data, use:enhance for client-side enhancement, action="?/login" targets named action, redirect after successful auth, named constant for password length


Pattern 6: Error Handling

SvelteKit uses +error.svelte components as error boundaries and the error() helper for controlled errors.

<!-- src/routes/+error.svelte -->
<script lang="ts">
  import { page } from '$app/state';
</script>

<div class="error-page">
  <h1>{page.status}</h1>

  {#if page.status === 404}
    <p>Page not found</p>
    <a href="/">Go home</a>
  {:else if page.status === 401}
    <p>You need to log in to access this page.</p>
    <a href="/login">Log in</a>
  {:else}
    <p>{page.error?.message ?? 'Something went wrong'}</p>
  {/if}
</div>
// In a load function
import { error } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";

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

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

  return { post };
};

Why good: error() throws a controlled error that renders +error.svelte, page from $app/state provides status and error info (Svelte 5 pattern), error boundary walks up the tree to find nearest +error.svelte


Pattern 7: Streaming with Load Functions

Return unawaited promises from load functions to stream data — fast data renders immediately, slow data streams in.

// src/routes/dashboard/+page.server.ts
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async ({ locals }) => {
  // Fast query - awaited (blocks render until ready)
  const user = await db.user.findUnique({
    where: { id: locals.user.id },
  });

  // Slow queries - NOT awaited (streamed after initial render)
  const analyticsPromise = fetchAnalytics(locals.user.id);
  const recommendationsPromise = fetchRecommendations(locals.user.id);

  return {
    user,
    analytics: analyticsPromise, // Streams when ready
    recommendations: recommendationsPromise, // Streams when ready
  };
};
<!-- src/routes/dashboard/+page.svelte -->
<script lang="ts">
  import type { PageProps } from './$types';

  let { data }: PageProps = $props();
</script>

<h1>Welcome, {data.user.name}</h1>

{#await data.analytics}
  <div class="skeleton">Loading analytics...</div>
{:then analytics}
  <div class="analytics">
    <p>Views: {analytics.views}</p>
    <p>Revenue: ${analytics.revenue}</p>
  </div>
{:catch error}
  <p class="error">Failed to load analytics: {error.message}</p>
{/await}

{#await data.recommendations}
  <div class="skeleton">Loading recommendations...</div>
{:then recommendations}
  <ul>
    {#each recommendations as rec}
      <li>{rec.title}</li>
    {/each}
  </ul>
{:catch error}
  <p class="error">Failed to load recommendations</p>
{/await}

Why good: User sees fast data immediately, slow data streams in progressively, each section handles loading and error states independently, {#await} blocks handle all three states


Pattern 8: Dynamic Routes

Use bracket notation for dynamic route segments.

Single Parameter

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

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

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

  return { post };
};

Rest Parameters

// src/routes/docs/[...path]/+page.server.ts
// Matches /docs/a, /docs/a/b, /docs/a/b/c
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async ({ params }) => {
  // params.path is "a/b/c" for /docs/a/b/c
  const segments = params.path.split("/");
  const doc = await loadDocument(segments);

  return { doc, breadcrumbs: segments };
};

Optional Parameters

// src/routes/[[lang]]/about/+page.svelte
// Matches /about and /en/about, /fr/about, etc.

Pattern 9: Page Options

Control rendering behavior per-page or per-layout.

// src/routes/blog/+page.ts
// Prerender blog listing at build time
export const prerender = true;

// src/routes/dashboard/+page.ts
// Disable SSR for client-only dashboard
export const ssr = false;

// src/routes/marketing/+layout.ts
// Prerender all marketing pages
export const prerender = true;

// src/routes/api/realtime/+server.ts
// Force dynamic rendering (no caching)
export const prerender = false;
Option Values Effect
prerender true, false, 'auto' Generate static HTML at build time
ssr true, false Enable/disable server-side rendering
csr true, false Enable/disable client-side rendering (hydration)

When to use:

  • prerender = true — Static content (blog posts, marketing pages)
  • ssr = false — Client-only pages with browser APIs (dashboards with charts)
  • csr = false — Zero JavaScript pages (legal text, documentation)

</patterns>


<integration>

Integration Guide

SvelteKit is the full-stack framework. It builds on Svelte for routing, data loading, and server-side concerns.

Svelte component integration:

  • All Svelte 5 patterns (Runes, snippets, events) work in SvelteKit pages and layouts
  • Page components receive data prop from load functions via $props()
  • Use PageProps, LayoutProps from auto-generated $types

Data fetching integration:

  • Server load functions fetch data before rendering (no waterfalls)
  • Layout load data cascades to all child pages
  • invalidate() and invalidateAll() for programmatic data refresh

Form handling integration:

  • Form actions handle POST requests with progressive enhancement
  • use:enhance adds client-side behavior (no page reload)
  • fail() returns validation errors to the form prop

Auth integration:

  • hooks.server.ts handle hook for session verification
  • event.locals for passing auth data to load functions and actions
  • Layout server load for protecting route groups

Deployment:

  • adapter-auto — Auto-detects deployment platform
  • adapter-node — Node.js server
  • adapter-static — Static site generation
  • adapter-vercel, adapter-netlify, adapter-cloudflare — Platform-specific

</integration>


<red_flags>

RED FLAGS

High Priority Issues:

  • Using API routes for form submissions -- Use form actions for mutations; API routes are for external clients
  • Throwing errors for validation -- Use fail() to return errors without clearing form state
  • Catching redirect() in try/catch -- redirect() throws a special exception; don't catch it
  • Missing auth checks in form actions -- Actions are public POST endpoints; always verify locals.user
  • Using +page.ts for database access -- Universal loads run on the client; use +page.server.ts

Medium Priority Issues:

  • Missing use:enhance on forms -- Forms reload the full page without it
  • Not using $types for load function typing -- Lose automatic type inference
  • Fetching data in components instead of load functions -- Creates client-side waterfalls
  • Using goto() instead of <a> links -- Lose prefetching and progressive enhancement

Gotchas & Edge Cases:

  • redirect() inside try/catch -- Redirect throws internally; wrap only the mutation in try/catch, not the redirect
  • Using page from $app/stores instead of $app/state -- $app/state is the Svelte 5 pattern (SvelteKit 2.12+)
  • Not returning from fail() -- fail() doesn't exit the function; you must return fail(...)
  • Using default action with named actions -- A page with named actions cannot also have a default action
  • Server load must return serializable data -- No classes, functions, or component instances (unless you define a transport hook)
  • event.locals is request-scoped -- Safe for per-request data (auth), not for global state
  • Remote functions (.remote.ts) are experimental -- Enable via kit.experimental.remoteFunctions in config; API may change

See reference.md for the full red flags list and decision frameworks.

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use server load functions (+page.server.ts) for data requiring database access, secrets, or cookies)

(You MUST use form actions for mutations — NOT API routes for form submissions)

(You MUST use fail() from @sveltejs/kit for validation errors — NEVER throw errors for validation)

(You MUST validate all input data on the server — client-side validation is NOT sufficient for security)

(You MUST use the auto-generated $types for type-safe load functions and page props)

(You MUST use use:enhance on forms for progressive enhancement — forms should work without JavaScript)

(You MUST NOT catch redirect() in try/catch — it throws a special exception SvelteKit handles)

Failure to follow these rules will break data loading, create security vulnerabilities, lose progressive enhancement, or cause redirect failures.

</critical_reminders>