원클릭으로
sveltekit-latest
Quick-reference for SvelteKit + Svelte 5 development (Feb 2026)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Quick-reference for SvelteKit + Svelte 5 development (Feb 2026)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Orchestrate development work through sub-agents using td for state. Use when given a td task ID, text idea, markdown plan, or td epic to execute through plan-implement-review loops.
Set up and run autonomous overnight coding loops that process td epic tasks one at a time. Includes the loop runner, Rich TUI cockpit dashboard, and prompt template. Use when automating multi-day feature development across many tasks with td for state management.
Start a td review session and do a detailed review of open reviews. Fix obvious bugs immediately, create tasks for bigger issues, ensure test coverage, and use parallel subagents for independent reviews. Use when you want to review and triage pending td reviews.
Task management for AI agents across context windows. Use when agents need to track work, log progress, hand off state, and maintain context across sessions. Includes workflows for single-issue focus, multi-issue work sessions, and structured handoffs. Essential for AI-assisted development where context windows reset between sessions.
Create and maintain DESIGN.md files — a design system specification optimized for AI consumption. Use when creating a project's design system file, extracting tokens from existing CSS/code, auditing design consistency, or onboarding an agent to a project's visual language.
Write naturally and avoid AI-detectable patterns. Use when (1) generating any written content, (2) reviewing/editing text for AI-like patterns, (3) user asks to make writing sound more human/natural, or (4) improving text that sounds robotic or generic. Covers vocabulary, structure, tone, and formatting tells that signal AI authorship.
| name | sveltekit-latest |
| description | Quick-reference for SvelteKit + Svelte 5 development (Feb 2026) |
| version | 1.0.0 |
| tags | ["svelte","sveltekit","frontend","typescript","runes"] |
| Package | Version | Notes |
|---|---|---|
| Svelte | ~5.50.x | Svelte 5 is the current stable. Svelte 4 is legacy. |
| SvelteKit | ~2.50.x | SvelteKit 2 is current stable. SvelteKit 1 is legacy. |
| sv (CLI) | latest | Replaces create-svelte. Use npx sv for all scaffolding. |
# Current recommended command (npm create svelte@latest is DEPRECATED)
npx sv create my-app
cd my-app
npm install
npm run dev
| Flag | Purpose |
|---|---|
--template minimal|demo|library | Project template |
--types ts|jsdoc|--no-types | TypeScript config |
--add [add-ons...] | Install add-ons (see below) |
--no-add-ons | Skip interactive add-on prompt |
--install npm|pnpm|yarn|bun|deno | Package manager |
drizzle, eslint, better-auth, tailwindcss, prettier, vitest, playwright, storybook, mdsvex, paraglide, sveltekit-adapter, mcp, devtools-json
TypeScript is built-in. Select "ts" when prompted by npx sv create, or pass --types ts. No extra configuration needed.
<script lang="ts"> in .svelte filesnpm run dev or npx svelte-kit syncverbatimModuleSyntax: true, isolatedModules: true, noEmit: true.svelte.ts files for reactive modules (replaces .ts when you need runes)Runes replace Svelte 4's implicit reactivity (let, $:) with explicit, portable primitives.
<script>
let count = $state(0); // primitive
let todos = $state([]); // deep reactive proxy (arrays/objects)
</script>
<button onclick={() => count++}>{count}</button>
done = $state(false); inside class bodieslet items = $state.raw([1, 2, 3]);
// items.push(4) -- NO EFFECT (not reactive)
items = [...items, 4]; // works (reassignment)
Use for large collections you never mutate in place. Better performance.
let data = $state({ count: 0 });
console.log($state.snapshot(data)); // plain object, no proxy
Use when passing state to external libraries or structuredClone.
let count = $state(0);
const doubled = $derived(count * 2);
const filtered = $derived.by(() => {
return items.filter(item => item.active);
});
$derived(expr) is equivalent to $derived.by(() => expr).
$effect(() => {
// Runs on mount and whenever dependencies change
// Dependencies are auto-tracked
console.log(`count is ${count}`);
// Optional cleanup (returned function runs before re-execution)
return () => { /* cleanup */ };
});
$effect.pre(() => {
// Runs before DOM is updated. Rare use case.
});
Rule of thumb: $derived for values, $effect for actions/side effects.
<script>
// Replaces "export let"
let { name, count = 0, class: klass, ...rest } = $props();
</script>
<script>
let { value = $bindable('default') } = $props();
</script>
Parent can then use bind:value={something}.
$inspect(count); // logs to console whenever count changes (dev only, stripped in prod)
Slots are deprecated. Use snippets and {@render} instead.
<!-- Parent -->
<Card>
<p>This becomes the children snippet</p>
</Card>
<!-- Card.svelte -->
<script>
let { children } = $props();
</script>
<div class="card">
{@render children?.()}
</div>
<!-- Parent -->
<Card>
{#snippet header()}
<h2>Title</h2>
{/snippet}
{#snippet footer()}
<p>Footer</p>
{/snippet}
<p>Default children content</p>
</Card>
<!-- Card.svelte -->
<script>
let { header, footer, children } = $props();
</script>
<div class="card">
{@render header?.()}
{@render children?.()}
{@render footer?.()}
</div>
<!-- Parent -->
<List items={users}>
{#snippet item(user)}
<span>{user.name}</span>
{/snippet}
</List>
<!-- List.svelte -->
<script>
let { items, item } = $props();
</script>
{#each items as entry}
{@render item(entry)}
{/each}
<!-- Svelte 4 -->
<button on:click={handler}>Click</button>
<input on:input={handler} />
<!-- Svelte 5 -->
<button onclick={handler}>Click</button>
<input oninput={handler} />
<!-- Svelte 4 child -->
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
</script>
<button on:click={() => dispatch('submit', data)}>Submit</button>
<!-- Svelte 5 child -->
<script>
let { onsubmit } = $props();
</script>
<button onclick={() => onsubmit(data)}>Submit</button>
Replace on:click|preventDefault with explicit calls:
<button onclick={(e) => { e.preventDefault(); handler(e); }}>Click</button>
// Svelte 4
const app = new App({ target: document.getElementById('app') });
// Svelte 5
import { mount, unmount } from 'svelte';
const app = mount(App, { target: document.getElementById('app') });
// later: unmount(app);
// counter.svelte.ts
let count = $state(0);
// Cannot export reassignable $state directly. Two patterns:
// Pattern 1: Export object (mutate properties)
export const counter = $state({ count: 0 });
export function increment() { counter.count++; }
// Pattern 2: Export getter functions
export function getCount() { return count; }
export function increment() { count++; }
SSR caveat: Module-scoped
$stateis a singleton shared across SSR requests. Always reset at render start. See "SSR Behavior for Module-Scoped State" below.
| Context | SSR | CSR |
|---|---|---|
Top-level <script> code | YES | YES |
$state initialization | YES | YES |
$derived / $derived.by | Compiled as IIFE (computed once at module init) | Reactive (recomputes on dependency change) |
$effect / $effect.pre | NO | YES |
onMount | NO | YES |
| Template expressions | YES | YES |
$derived.by(() => ...) compiles to const x = (() => ...)() during SSR -- an immediately-invoked function that runs once at module initialization, not reactively. If module-scoped $state is set after the derived is initialized, the derived will NOT reflect the updated values.
Broken pattern:
// store.svelte.ts
let page = $state('');
const snapshot = $derived.by(() => ({ page })); // Frozen at init during SSR!
function setPage(p) { page = p; }
Working pattern:
// store.svelte.ts
let page = $state('');
function buildSnapshot() { return { page }; } // Fresh read every call
export const store = {
get snapshot() { return buildSnapshot(); }, // Works in both SSR and CSR
setPage(p) { page = p; },
};
During CSR, reading $state variables inside a getter called from a template still triggers Svelte 5's fine-grained reactivity tracking.
To populate state during SSR, call setters at the top level of <script> blocks (not in $effect or onMount). Use $effect for client-side reactive updates:
<script>
import { page } from '$app/stores';
import { myStore } from '$lib/stores/my.svelte';
let { data } = $props();
// SSR + CSR: runs on every render
myStore.setPage(data.title);
// CSR only: reactive updates on navigation
$effect(() => {
myStore.setPage(data.title);
});
</script>
When you need $derived values for SSR baseline code, DON'T read the $derived at top level. Instead, compute the value directly from the source:
<!-- BAD: warns because $derived is read outside reactive context -->
<script>
let isAdmin = $derived(data.user?.role === 'admin');
if (isAdmin) { store.setAuth({...}); } // Warning!
</script>
<!-- GOOD: compute from source directly -->
<script>
let isAdmin = $derived(data.user?.role === 'admin');
// SSR baseline: use source data, not $derived
if (data.user?.role === 'admin') { store.setAuth({...}); }
// $effect for CSR reactivity uses $derived normally
$effect(() => { if (isAdmin) { store.setAuth({...}); } });
</script>
Module-scoped $state is shared across all SSR requests (it's a singleton). SvelteKit SSR is synchronous per-request, so call reset() at the top of the root layout to prevent cross-request pollution:
<!-- +layout.svelte (root) -->
<script>
import { myStore } from '$lib/stores/my.svelte';
myStore.reset(); // Clear state before each render
</script>
error() and redirect() no longer need to be thrown -- just call themcookies.set/delete/serialize require explicit path parametervitePreprocess from @sveltejs/vite-plugin-svelte (not from SvelteKit)resolvePath replaced by resolveRoute from $app/pathspaths.relative config# Migrate Svelte 4 -> Svelte 5
npx sv migrate svelte-5
# Migrate SvelteKit 1 -> SvelteKit 2
npx sv migrate sveltekit-2
src/
lib/ # Shared code, importable as $lib/
routes/ # File-based routing
+page.svelte # Page component
+page.ts # Page load function (universal)
+page.server.ts # Server-only load / form actions
+layout.svelte # Layout component
+layout.ts # Layout load function
+layout.server.ts # Server-only layout load
+error.svelte # Error page
+server.ts # API endpoint (GET, POST, etc.)
app.html # HTML template
app.d.ts # Auto-generated types
svelte.config.js # SvelteKit configuration
vite.config.ts # Vite configuration
<!-- +page.svelte -->
<form method="POST" action="?/create">
<input name="title" />
<button>Create</button>
</form>
// +page.server.ts
import type { Actions } from './$types';
export const actions = {
create: async ({ request }) => {
const data = await request.formData();
const title = data.get('title');
// handle creation
}
} satisfies Actions;
// +page.ts (runs on server AND client)
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ fetch }) => {
const res = await fetch('/api/data');
return { items: await res.json() };
};
// +page.server.ts (runs ONLY on server)
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ locals }) => {
return { user: locals.user };
};