[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-e877a545-1ed5-4807-a9cb-4f9a33dbad1d":3,"$ft3C5EGbvj6eaiCqDirodVq66m-YNP82fAH6JLSSrMXo":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"e877a545-1ed5-4807-a9cb-4f9a33dbad1d","sveltekit","使用SvelteKit构建全栈Web应用——基于文件的路由、SSR、SSG、API路由和表单操作在一个框架中。","cat_coding_frontend","mod_coding","sickn33,coding","---\nname: sveltekit\ndescription: \"Build full-stack web applications with SvelteKit — file-based routing, SSR, SSG, API routes, and form actions in one framework.\"\ncategory: frontend\nrisk: safe\nsource: community\ndate_added: \"2026-03-18\"\nauthor: suhaibjanjua\ntags: [svelte, sveltekit, fullstack, ssr, ssg, typescript]\ntools: [claude, cursor, gemini]\n---\n\n# SvelteKit Full-Stack Development\n\n## Overview\n\nSvelteKit is the official full-stack framework built on top of Svelte. It provides file-based routing, server-side rendering (SSR), static site generation (SSG), API routes, and progressive form actions — all with Svelte's compile-time reactivity model that ships zero runtime overhead to the browser. Use this skill when building fast, modern web apps where both DX and performance matter.\n\n## When to Use This Skill\n\n- Use when building a new full-stack web application with Svelte\n- Use when you need SSR or SSG with fine-grained control per route\n- Use when migrating a SPA to a framework with server capabilities\n- Use when working on a project that needs file-based routing and collocated API endpoints\n- Use when the user asks about `+page.svelte`, `+layout.svelte`, `load` functions, or form actions\n\n## How It Works\n\n### Step 1: Project Setup\n\n```bash\nnpm create svelte@latest my-app\ncd my-app\nnpm install\nnpm run dev\n```\n\nChoose **Skeleton project** + **TypeScript** + **ESLint\u002FPrettier** when prompted.\n\nDirectory structure after scaffolding:\n\n```\nsrc\u002F\n  routes\u002F\n    +page.svelte        ← Root page component\n    +layout.svelte      ← Root layout (wraps all pages)\n    +error.svelte       ← Error boundary\n  lib\u002F\n    server\u002F             ← Server-only code (never bundled to client)\n    components\u002F         ← Shared components\n  app.html              ← HTML shell\nstatic\u002F                 ← Static assets\n```\n\n### Step 2: File-Based Routing\n\nEvery `+page.svelte` file in `src\u002Froutes\u002F` maps directly to a URL:\n\n```\nsrc\u002Froutes\u002F+page.svelte          → \u002F\nsrc\u002Froutes\u002Fabout\u002F+page.svelte    → \u002Fabout\nsrc\u002Froutes\u002Fblog\u002F[slug]\u002F+page.svelte  → \u002Fblog\u002F:slug\nsrc\u002Froutes\u002Fshop\u002F[...path]\u002F+page.svelte → \u002Fshop\u002F* (catch-all)\n```\n\n**Route groups** (no URL segment): wrap in `(group)\u002F` folder.\n**Private routes** (not accessible as URLs): prefix with `_` or `(group)`.\n\n### Step 3: Loading Data with `load` Functions\n\nUse a `+page.ts` (universal) or `+page.server.ts` (server-only) file alongside the page:\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fblog\u002F[slug]\u002F+page.server.ts\nimport { error } from '@sveltejs\u002Fkit';\nimport type { PageServerLoad } from '.\u002F$types';\n\nexport const load: PageServerLoad = async ({ params, fetch }) => {\n  const post = await fetch(`\u002Fapi\u002Fposts\u002F${params.slug}`).then(r => r.json());\n\n  if (!post) {\n    error(404, 'Post not found');\n  }\n\n  return { post };\n};\n```\n\n```svelte\n\u003C!-- src\u002Froutes\u002Fblog\u002F[slug]\u002F+page.svelte -->\n\u003Cscript lang=\"ts\">\n  import type { PageData } from '.\u002F$types';\n  export let data: PageData;\n\u003C\u002Fscript>\n\n\u003Ch1>{data.post.title}\u003C\u002Fh1>\n\u003Carticle>{@html data.post.content}\u003C\u002Farticle>\n```\n\n### Step 4: API Routes (Server Endpoints)\n\nCreate `+server.ts` files for REST-style endpoints:\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fapi\u002Fposts\u002F+server.ts\nimport { json } from '@sveltejs\u002Fkit';\nimport type { RequestHandler } from '.\u002F$types';\n\nexport const GET: RequestHandler = async ({ url }) => {\n  const limit = Number(url.searchParams.get('limit') ?? 10);\n  const posts = await db.post.findMany({ take: limit });\n  return json(posts);\n};\n\nexport const POST: RequestHandler = async ({ request }) => {\n  const body = await request.json();\n  const post = await db.post.create({ data: body });\n  return json(post, { status: 201 });\n};\n```\n\n### Step 5: Form Actions\n\nForm actions are the SvelteKit-native way to handle mutations — no client-side fetch required:\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fcontact\u002F+page.server.ts\nimport { fail, redirect } from '@sveltejs\u002Fkit';\nimport type { Actions } from '.\u002F$types';\n\nexport const actions: Actions = {\n  default: async ({ request }) => {\n    const data = await request.formData();\n    const email = data.get('email');\n\n    if (!email) {\n      return fail(400, { email, missing: true });\n    }\n\n    await sendEmail(String(email));\n    redirect(303, '\u002Fthank-you');\n  }\n};\n```\n\n```svelte\n\u003C!-- src\u002Froutes\u002Fcontact\u002F+page.svelte -->\n\u003Cscript lang=\"ts\">\n  import { enhance } from '$app\u002Fforms';\n  import type { ActionData } from '.\u002F$types';\n  export let form: ActionData;\n\u003C\u002Fscript>\n\n\u003Cform method=\"POST\" use:enhance>\n  \u003Cinput name=\"email\" type=\"email\" \u002F>\n  {#if form?.missing}\u003Cp class=\"error\">Email is required\u003C\u002Fp>{\u002Fif}\n  \u003Cbutton type=\"submit\">Subscribe\u003C\u002Fbutton>\n\u003C\u002Fform>\n```\n\n### Step 6: Layouts and Nested Routes\n\n```svelte\n\u003C!-- src\u002Froutes\u002F+layout.svelte -->\n\u003Cscript lang=\"ts\">\n  import type { LayoutData } from '.\u002F$types';\n  export let data: LayoutData;\n\u003C\u002Fscript>\n\n\u003Cnav>\n  \u003Ca href=\"\u002F\">Home\u003C\u002Fa>\n  \u003Ca href=\"\u002Fblog\">Blog\u003C\u002Fa>\n  {#if data.user}\n    \u003Ca href=\"\u002Fdashboard\">Dashboard\u003C\u002Fa>\n  {\u002Fif}\n\u003C\u002Fnav>\n\n\u003Cslot \u002F>  \u003C!-- child page renders here -->\n```\n\n```typescript\n\u002F\u002F src\u002Froutes\u002F+layout.server.ts\nimport type { LayoutServerLoad } from '.\u002F$types';\n\nexport const load: LayoutServerLoad = async ({ locals }) => {\n  return { user: locals.user ?? null };\n};\n```\n\n### Step 7: Rendering Modes\n\nControl per-route rendering with page options:\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fdocs\u002F+page.ts\nexport const prerender = true;   \u002F\u002F Static — generated at build time\nexport const ssr = true;         \u002F\u002F Default — rendered on server per request\nexport const csr = false;        \u002F\u002F Disable client-side hydration entirely\n```\n\n## Examples\n\n### Example 1: Protected Dashboard Route\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fdashboard\u002F+layout.server.ts\nimport { redirect } from '@sveltejs\u002Fkit';\nimport type { LayoutServerLoad } from '.\u002F$types';\n\nexport const load: LayoutServerLoad = async ({ locals }) => {\n  if (!locals.user) {\n    redirect(303, '\u002Flogin');\n  }\n  return { user: locals.user };\n};\n```\n\n### Example 2: Hooks — Session Middleware\n\n```typescript\n\u002F\u002F src\u002Fhooks.server.ts\nimport type { Handle } from '@sveltejs\u002Fkit';\nimport { verifyToken } from '$lib\u002Fserver\u002Fauth';\n\nexport const handle: Handle = async ({ event, resolve }) => {\n  const token = event.cookies.get('session');\n  if (token) {\n    event.locals.user = await verifyToken(token);\n  }\n  return resolve(event);\n};\n```\n\n### Example 3: Preloading and Invalidation\n\n```svelte\n\u003Cscript lang=\"ts\">\n  import { invalidateAll } from '$app\u002Fnavigation';\n\n  async function refresh() {\n    await invalidateAll(); \u002F\u002F re-runs all load functions on the page\n  }\n\u003C\u002Fscript>\n\n\u003Cbutton on:click={refresh}>Refresh\u003C\u002Fbutton>\n```\n\n## Best Practices\n\n- ✅ Use `+page.server.ts` for database\u002Fauth logic — it never ships to the client\n- ✅ Use `$lib\u002Fserver\u002F` for shared server-only modules (DB client, auth helpers)\n- ✅ Use form actions for mutations instead of client-side `fetch` — works without JS\n- ✅ Type all `load` return values with generated `$types` (`PageData`, `LayoutData`)\n- ✅ Use `event.locals` in hooks to pass server-side context to load functions\n- ❌ Don't import server-only code in `+page.svelte` or `+layout.svelte` directly\n- ❌ Don't store sensitive state in stores — use `locals` on the server\n- ❌ Don't skip `use:enhance` on forms — without it, forms lose progressive enhancement\n\n## Security & Safety Notes\n\n- All code in `+page.server.ts`, `+server.ts`, and `$lib\u002Fserver\u002F` runs exclusively on the server — safe for DB queries, secrets, and session validation.\n- Always validate and sanitize form data before database writes.\n- Use `error(403)` or `redirect(303)` from `@sveltejs\u002Fkit` rather than returning raw error objects.\n- Set `httpOnly: true` and `secure: true` on all auth cookies.\n- CSRF protection is built-in for form actions — do not disable `checkOrigin` in production.\n\n## Common Pitfalls\n\n- **Problem:** `Cannot use import statement in a module` in `+page.server.ts`\n  **Solution:** The file must be `.ts` or `.js`, not `.svelte`. Server files and Svelte components are separate.\n\n- **Problem:** Store value is `undefined` on first SSR render\n  **Solution:** Populate the store from the `load` function return value (`data` prop), not from client-side `onMount`.\n\n- **Problem:** Form action does not redirect after submit\n  **Solution:** Use `redirect(303, '\u002Fpath')` from `@sveltejs\u002Fkit`, not a plain `return`. 303 is required for POST redirects.\n\n- **Problem:** `locals.user` is undefined inside a `+page.server.ts` load function\n  **Solution:** Set `event.locals.user` in `src\u002Fhooks.server.ts` before the `resolve()` call.\n\n## Related Skills\n\n- `@nextjs-app-router-patterns` — When you prefer React over Svelte for SSR\u002FSSG\n- `@trpc-fullstack` — Add end-to-end type safety to SvelteKit API routes\n- `@auth-implementation-patterns` — Authentication patterns usable with SvelteKit hooks\n- `@tailwind-patterns` — Styling SvelteKit apps with Tailwind CSS\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,169,507,"2026-05-16 13:42:36",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"前端开发","frontend","mdi-language-html5","HTML\u002FCSS\u002FJavaScript\u002F框架相关",1,96,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"d13ae9ae-dc29-4204-b6f6-a13fb29a94c4","1.0.0","sveltekit.zip",3760,"uploads\u002Fskills\u002Fe877a545-1ed5-4807-a9cb-4f9a33dbad1d\u002Fsveltekit.zip","16754ec65606a2b35e297be6af33d4574bcb1636a75b48ecec59b39bb2860099","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":9187}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]