
Sveltekit Structure
- 741 installs
- 92 repo stars
- Updated April 29, 2026
- spences10/svelte-skills-kit
sveltekit-structure is a SvelteKit agent skill that gives developers instant guidance on file conventions, routing, layouts, error boundaries, and SSR patterns in Cursor or Claude Code.
About
sveltekit-structure is a Svelte Skills Kit reference for SvelteKit project layout, routing, layouts, error handling, pending UI, and hydration inside AI coding agents. The skill documents file types including +page.svelte for pages, +layout.svelte for wrappers, +error.svelte for error boundaries, and +server.ts for API endpoints, with route examples such as src/routes/about/+page.svelte and dynamic src/routes/posts/[id]/+page.svelte paths. Developers reach for sveltekit-structure when scaffolding routes, nesting layouts, wiring svelte:boundary error UI, or clarifying SSR behavior during feature work. Guidance stays aligned to SvelteKit file naming so agents generate valid route trees instead of generic SPA patterns.
- Defines exact file types: +page.svelte, +layout.svelte, +error.svelte, +server.ts
- Explains route-to-file mapping including dynamic segments like [id]
- Details nested layout behavior that automatically wraps child routes
- Includes ready-to-use +layout.svelte component example with slots
- Links to four focused reference documents covering naming, patterns, and error handling
Sveltekit Structure by the numbers
- 741 all-time installs (skills.sh)
- +17 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #469 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Security screen: CRITICAL risk (skills.sh audit)
- Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/spences10/svelte-skills-kit --skill sveltekit-structureAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 741 |
|---|---|
| repo stars | ★ 92 |
| Security audit | 2 / 3 scanners passed |
| Last updated | April 29, 2026 |
| Repository | spences10/svelte-skills-kit ↗ |
How do SvelteKit routes and layout files work?
Get instant, accurate guidance on SvelteKit file conventions, routing, layouts, error boundaries, and SSR patterns while building with Cursor or Claude.
Who is it for?
Frontend developers building SvelteKit apps in Cursor or Claude Code who need accurate routing, layout, and SSR file-convention guidance.
Skip if: Teams using React, Next.js, or non-Svelte frameworks should skip sveltekit-structure because it only covers SvelteKit conventions.
When should I use this skill?
The user asks about SvelteKit routing, +page.svelte, +layout.svelte, +error.svelte, +server.ts, SSR, hydration, or svelte:boundary.
What you get
Correct SvelteKit route trees, layout hierarchies, error boundary files, API endpoints, and SSR-safe page structure.
- Valid SvelteKit route file tree
- Layout and error boundary files
- SSR-aware page and endpoint structure
Files
SvelteKit Structure
Quick Start
File types: +page.svelte (page) | +layout.svelte (wrapper) | +error.svelte (error boundary) | +server.ts (API endpoint)
Routes: src/routes/about/+page.svelte → /about | src/routes/posts/[id]/+page.svelte → /posts/123
Layouts: Apply to all child routes. +layout.svelte at any level wraps descendants.
Example
src/routes/
├── +layout.svelte # Root layout (all pages)
├── +page.svelte # Homepage /
├── about/+page.svelte # /about
└── dashboard/
├── +layout.svelte # Dashboard layout (dashboard pages only)
├── +page.svelte # /dashboard
└── settings/+page.svelte # /dashboard/settings<!-- +layout.svelte -->
<script>
let { children } = $props();
</script>
<nav><!-- Navigation --></nav>
<main>{@render children()}</main>
<footer><!-- Footer --></footer>Reference Files
- file-naming.md - File naming
conventions
- layout-patterns.md - Nested layouts
- error-handling.md - +error.svelte
placement
- svelte-boundary.md -
Component-level error/pending
- ssr-hydration.md - SSR and
browser-only code
Notes
- Layouts:
{@render children()}| Errors: +error.svelte _above_
failing route
- Groups:
(name)folders don't affect URL | Client-only: check
browser
- Last verified: 2025-01-11
<!-- PROGRESSIVE DISCLOSURE GUIDELINES:
- Keep this file ~50 lines total (max ~150 lines)
- Use 1-2 code blocks only (recommend 1)
- Keep description <200 chars for Level 1 efficiency
- Move detailed docs to references/ for Level 3 loading
- This is Level 2 - quick reference ONLY, not a manual
LLM WORKFLOW (when editing this file): 1. Write/edit SKILL.md 2. Format (if formatter available) 3. Run: npx skills add . --list 4. If the skill is not discovered, check SKILL.md frontmatter formatting 5. Validate again to confirm -->
Sveltekit Structure
SvelteKit structure guidance. Use for routing, layouts, error handling, and SSR. Covers file naming (+page vs +layout vs +server), nested layouts, error boundaries, and hydration.
Structure
SKILL.md- Main skill instructionsreferences/- Detailed documentation loaded as neededscripts/- Executable code for deterministic operationsassets/- Templates, images, or other resources
Usage
This skill is automatically discovered by compatible agents when relevant to the task.
Error Handling
Error Boundary Placement
Key rule: +error.svelte must be _above_ the failing route in the hierarchy.
src/routes/
├── +error.svelte # Catches errors in all routes below
├── +page.svelte # If this errors → uses +error.svelte above
└── admin/
├── +error.svelte # Catches errors in admin routes
└── +page.svelte # If this errors → uses admin/+error.svelteWrong:
src/routes/dashboard/
├── +layout.svelte # If this errors...
└── +error.svelte # This won't catch it (too low)Right:
src/routes/
├── +error.svelte # Catches dashboard layout errors
└── dashboard/
├── +layout.svelte
└── +error.svelte # Catches dashboard page errorsError Propagation
Errors bubble up to the nearest +error.svelte:
src/routes/
├── +error.svelte # Level 1 (root fallback)
└── blog/
├── +error.svelte # Level 2 (blog fallback)
└── [slug]/
├── +layout.server.ts # Error here → blog/+error.svelte
├── +page.server.ts # Error here → blog/+error.svelte
└── +page.svelte # Error here → blog/+error.svelteIf no error boundary exists at that level, it goes to the parent.
Basic Error Page
<!-- +error.svelte -->
<script>
import { page } from '$app/stores';
</script>
<h1>{$page.status}</h1><p>{$page.error.message}</p>Custom Error Data
// +page.server.ts
import { error } from '@sveltejs/kit';
export const load = async ({ params }) => {
const post = await getPost(params.id);
if (!post) {
throw error(404, {
message: 'Post not found',
postId: params.id,
});
}
return { post };
};<!-- +error.svelte -->
<script>
import { page } from '$app/stores';
</script>
<h1>{$page.status}</h1>
<p>{$page.error.message}</p>
{#if $page.error.postId}
<p>Could not find post with ID: {$page.error.postId}</p>
{/if}Status Code Specific Errors
<!-- +error.svelte -->
<script>
import { page } from '$app/stores';
</script>
{#if $page.status === 404}
<h1>Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<a href="/">Go home</a>
{:else if $page.status === 403}
<h1>Access Denied</h1>
<p>You don't have permission to view this page.</p>
{:else if $page.status === 401}
<h1>Unauthorized</h1>
<p>Please log in to continue.</p>
<a href="/login">Login</a>
{:else if $page.status >= 500}
<h1>Server Error</h1>
<p>Something went wrong on our end. Please try again later.</p>
{:else}
<h1>Error {$page.status}</h1>
<p>{$page.error.message}</p>
{/if}Common Status Codes
- 400 - Bad Request (malformed request)
- 401 - Unauthorized (not logged in)
- 403 - Forbidden (logged in but no permission)
- 404 - Not Found (resource doesn't exist)
- 500 - Internal Server Error (unhandled exception)
- 503 - Service Unavailable (server overloaded/down)
Error in Layout vs Page
Layout error:
// src/routes/dashboard/+layout.server.ts
export const load = async ({ locals }) => {
if (!locals.user) {
throw error(401, 'Not logged in'); // Caught by +error.svelte ABOVE dashboard
}
return { user: locals.user };
};Page error:
// src/routes/dashboard/settings/+page.server.ts
export const load = async () => {
throw error(404, 'Settings not found'); // Caught by nearest +error.svelte
};Expected Errors vs Unexpected Errors
Expected (use error()):
// User requests invalid resource
if (!post) throw error(404, 'Post not found');
// User lacks permission
if (post.authorId !== user.id) throw error(403, 'Not your post');Unexpected (let it bubble):
// Unhandled exceptions (DB connection fails, etc.)
// Will show generic 500 error
const posts = await db.query.posts.findMany(); // Might throwHandling Errors in handleError Hook
// src/hooks.server.ts
import type { HandleServerError } from '@sveltejs/kit';
export const handleError: HandleServerError = ({ error, event }) => {
// Log to error tracking service
console.error('Error:', error, 'Path:', event.url.pathname);
// Return user-friendly message (don't expose internals)
return {
message: 'An unexpected error occurred',
code: error?.code ?? 'UNKNOWN',
};
};Error in Load vs Error in Component
Load function error (recommended):
// +page.server.ts
export const load = async ({ params }) => {
const user = await getUser(params.id);
if (!user) throw error(404, 'User not found'); // Shows +error.svelte
return { user };
};Component error (not ideal):
<!-- +page.svelte - Don't do this -->
<script>
export let data;
// If data.user is undefined, component just shows nothing
// No error boundary triggered
</script>
<h1>{data.user.name}</h1> <!-- Might crash if user undefined -->Best practice: Validate and throw errors in load functions, not components.
Fallback Error Handling
Always have a root +error.svelte:
<!-- src/routes/+error.svelte -->
<script>
import { page } from '$app/stores';
import { dev } from '$app/environment';
</script>
<h1>Oops! Something went wrong</h1>
{#if dev}
<!-- Show details in dev mode -->
<pre>{JSON.stringify($page.error, null, 2)}</pre>
{:else}
<!-- Generic message in production -->
<p>We're sorry, but something unexpected happened.</p>
{/if}
<a href="/">Go home</a>Testing Error Boundaries
// +page.server.ts
export const load = async ({ url }) => {
// Test error page in dev
if (url.searchParams.has('test-error')) {
throw error(500, 'Test error');
}
return {};
};Visit http://localhost:5173/page?test-error to see error boundary.
Key Takeaways
1. ✅ Place +error.svelte ABOVE failing routes 2. ✅ Errors bubble up to nearest error boundary 3. ✅ Always have a root src/routes/+error.svelte 4. ✅ Throw errors in load functions, not components 5. ✅ Use specific status codes (401, 403, 404, 500) 6. ✅ Customize error pages per section (blog, admin, etc.) 7. ✅ Use handleError hook for logging/monitoring 8. ✅ Show detailed errors in dev, generic in production
File Naming Conventions
Core Files
| File | Purpose | Runs | Example |
|---|---|---|---|
+page.svelte | Page component | Client & Server (SSR) | /routes/about/+page.svelte → /about |
+page.ts | Universal load | Client & Server | Data for +page.svelte |
+page.server.ts | Server load & actions | Server only | DB queries, form actions |
+layout.svelte | Layout wrapper | Client & Server | Wraps child routes |
+layout.ts | Layout universal load | Client & Server | Data for +layout.svelte |
+layout.server.ts | Layout server load | Server only | Auth, user data |
+error.svelte | Error boundary | Client & Server | Shown when error thrown |
+server.ts | API endpoint | Server only | /routes/api/users/+server.ts → /api/users |
Route Parameters
| Pattern | Matches | Example |
|---|---|---|
[id] | Single param | /posts/[id]/+page.svelte → /posts/123 |
[slug] | Single param | /blog/[slug]/+page.svelte → /blog/hello-world |
[[optional]] | Optional param | /search/[[query]]/+page.svelte → /search or /search/svelte |
[...rest] | Rest params | /docs/[...path]/+page.svelte → /docs/a/b/c |
Route Groups
| Pattern | Purpose | URL |
|---|---|---|
(group) | Group routes (no URL impact) | /(app)/dashboard/+page.svelte → /dashboard |
(marketing) | Separate layouts | Different layout for marketing pages |
Special Files
hooks.server.ts- Server hooks (handle function, runs on every
request)
hooks.client.ts- Client hooks (runs in browser)app.html- HTML templateservice-worker.ts- Service workerparams/*.ts- Param validators
Common Patterns
src/routes/
├── +layout.svelte # Root layout
├── +layout.ts # Root data
├── +page.svelte # Homepage
├── +error.svelte # Root error boundary
│
├── (app)/ # App routes (grouped)
│ ├── +layout.svelte # App layout (auth required)
│ ├── dashboard/+page.svelte # /dashboard
│ └── settings/+page.svelte # /settings
│
├── (marketing)/ # Marketing routes (grouped)
│ ├── +layout.svelte # Marketing layout
│ ├── about/+page.svelte # /about
│ └── pricing/+page.svelte # /pricing
│
├── blog/
│ ├── +page.svelte # /blog (list)
│ └── [slug]/
│ ├── +page.svelte # /blog/post-title
│ └── +page.server.ts # Load post data
│
└── api/
└── posts/
└── +server.ts # API: GET/POST /api/postsLayout Patterns
Basic Layout
<!-- src/routes/+layout.svelte -->
<script>
let { children } = $props();
</script>
<header>Header</header>
<main>{@render children()}</main>
<footer>Footer</footer>Key points:
- Must declare
childrenin$props() - Use
{@render children()}to render nested content - Root layout wraps ALL pages
Nested Layouts
Layouts inherit from parent layouts:
src/routes/
├── +layout.svelte # Root layout (all pages)
└── dashboard/
├── +layout.svelte # Dashboard layout (dashboard pages only)
└── +page.svelte # Uses both layoutsResult: Root layout wraps dashboard layout wraps page.
Rendering order:
Root +layout.svelte
└─ Dashboard +layout.svelte
└─ +page.svelteExample: Nested Layout Pattern
<!-- src/routes/+layout.svelte -->
<script>
let { children } = $props();
</script>
<div class="app">
<nav>Global Nav</nav>
{@render children()}
</div><!-- src/routes/dashboard/+layout.svelte -->
<script>
let { children } = $props();
</script>
<div class="dashboard">
<aside>Dashboard Sidebar</aside>
<main>{@render children()}</main>
</div><!-- src/routes/dashboard/+page.svelte --><h1>Dashboard Home</h1>Rendered HTML structure:
<div class="app">
<nav>Global Nav</nav>
<div class="dashboard">
<aside>Dashboard Sidebar</aside>
<main>
<h1>Dashboard Home</h1>
</main>
</div>
</div>Layout Groups
Use (groups) to organize without affecting URLs:
src/routes/
├── (marketing)/
│ ├── +layout.svelte # Marketing layout
│ ├── about/+page.svelte # /about (uses marketing layout)
│ └── pricing/+page.svelte # /pricing (uses marketing layout)
│
└── (app)/
├── +layout.svelte # App layout
├── dashboard/+page.svelte # /dashboard (uses app layout)
└── settings/+page.svelte # /settings (uses app layout)Key points:
- Parentheses make groups invisible in URLs
/aboutroute, NOT/(marketing)/about- Different layouts for different sections
- Useful for authentication boundaries
Example: Marketing vs App Layouts
<!-- src/routes/(marketing)/+layout.svelte -->
<script>
let { children } = $props();
</script>
<header class="marketing-header">
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/login">Login</a>
</nav>
</header>
{@render children()}
<footer>© 2024 Company</footer><!-- src/routes/(app)/+layout.svelte -->
<script>
let { children, data } = $props();
</script>
<header class="app-header">
<nav>
<a href="/dashboard">Dashboard</a>
<a href="/settings">Settings</a>
<span>Welcome, {data.user.name}</span>
</nav>
</header>
{@render children()}Reset Layout
Use @ in filename to break layout inheritance:
NOT RECOMMENDED - This feature is deprecated in SvelteKit 2+.
Instead, use layout groups to create separate hierarchies:
src/routes/
├── +layout.svelte # Root layout (for most pages)
├── (app)/
│ └── +layout.svelte # App layout
└── (public)/
└── +layout.svelte # Public layout (completely separate)Layout with Data Loading
<!-- src/routes/+layout.server.ts -->
export const load = async ({ locals }) => {
// Available to all child routes
return {
user: locals.user,
};
};<!-- src/routes/+layout.svelte -->
<script>
let { children, data } = $props();
</script>
<header>
{#if data.user}
<span>Welcome, {data.user.name}</span>
{:else}
<a href="/login">Login</a>
{/if}
</header>
{@render children()}Conditional Layout Content
<!-- +layout.svelte -->
<script>
import { page } from '$app/stores';
let { children } = $props();
</script>
{#if !$page.url.pathname.startsWith('/admin')}
<header>Public Header</header>
{/if}
{@render children()}
{#if !$page.url.pathname.includes('/checkout')}
<footer>Footer</footer>
{/if}Better approach: Use layout groups instead of conditionals.
Protected Layouts
// src/routes/(app)/+layout.server.ts
import { redirect } from '@sveltejs/kit';
export const load = async ({ locals }) => {
if (!locals.user) {
throw redirect(303, '/login');
}
return {
user: locals.user,
};
};All routes under (app) group now require authentication.
Sharing Layout State
<!-- src/routes/+layout.svelte -->
<script>
import { setContext } from 'svelte';
let { children, data } = $props();
// Share state with all descendant components
setContext('user', data.user);
</script>
{@render children()}<!-- Any child component -->
<script>
import { getContext } from 'svelte';
const user = getContext('user');
</script>
<p>Hello, {user.name}</p>Layout Slot Props (Snippets)
<!-- src/routes/dashboard/+layout.svelte -->
<script>
let { children, header } = $props();
</script>
<div class="dashboard">
<aside>Sidebar</aside>
<div class="content">
{#if header}
<header>{@render header()}</header>
{/if}
<main>{@render children()}</main>
</div>
</div><!-- src/routes/dashboard/+page.svelte -->
{#snippet header()}
<h1>Custom Dashboard Header</h1>
{/snippet}
<p>Dashboard content</p>Common Patterns
Pattern 1: Auth Boundary
src/routes/
├── +layout.svelte # Root (no auth)
├── (public)/
│ ├── +layout.svelte # Public layout (landing pages)
│ ├── +page.svelte # /
│ └── about/+page.svelte # /about
└── (protected)/
├── +layout.server.ts # Check auth, redirect if not logged in
├── +layout.svelte # Protected layout (app UI)
├── dashboard/+page.svelte # /dashboard
└── settings/+page.svelte # /settingsPattern 2: Multi-tenant with Shared Root
src/routes/
├── +layout.svelte # Root layout (shared)
├── admin/
│ ├── +layout.svelte # Admin layout
│ └── users/+page.svelte # /admin/users
└── client/
├── +layout.svelte # Client layout
└── projects/+page.svelte # /client/projectsPattern 3: Progressive Enhancement
<!-- src/routes/+layout.svelte -->
<script>
import { page } from '$app/stores';
import { navigating } from '$app/stores';
let { children } = $props();
</script>
<div class="app">
{#if $navigating}
<div class="loading-bar"></div>
{/if}
{@render children()}
</div>
<style>
.loading-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: blue;
animation: loading 1s ease-in-out;
}
</style>Layout Best Practices
1. ✅ Keep root layout minimal (shared across ALL pages) 2. ✅ Use layout groups for separate sections 3. ✅ Load shared data in layout's load function 4. ✅ Use context for sharing state with descendants 5. ✅ Avoid too many nested layouts (max 2-3 levels) 6. ✅ Don't put auth logic in root layout (use groups) 7. ✅ Remember: layouts share data DOWN, not UP 8. ❌ Avoid conditionals in layouts (use groups instead)
Debugging Layouts
<!-- src/routes/+layout.svelte -->
<script>
import { page } from '$app/stores';
let { children } = $props();
$effect(() => {
console.log('Current route:', $page.url.pathname);
console.log('Layout data:', $page.data);
});
</script>
{@render children()}Key Takeaways
- Layouts wrap all child routes
- Nested layouts create hierarchy (root → section → page)
- Groups
(name)organize without affecting URLs - Load data in
+layout.server.tsto share with children - Use context to share reactive state
- Keep layouts simple and focused
SSR & Hydration
The Problem
SvelteKit runs on server (SSR) then hydrates in browser. Code using browser APIs (window, document, localStorage) fails on server.
Solution: Check for Browser
import { browser } from '$app/environment';
// In load function
export const load = async () => {
const theme = browser ? localStorage.getItem('theme') : 'light';
return { theme };
};<!-- In component -->
<script>
import { browser } from '$app/environment';
import { onMount } from 'svelte';
let data = $state(null);
// Option 1: Use browser check
if (browser) {
data = localStorage.getItem('data');
}
// Option 2: Use onMount (only runs in browser)
onMount(() => {
data = localStorage.getItem('data');
});
// Option 3: Use $effect with browser check
$effect(() => {
if (browser) {
data = localStorage.getItem('data');
}
});
</script>Common Mistakes
❌ Using window Without Check
// WRONG - fails on server
export const load = async () => {
const width = window.innerWidth; // ERROR on server
return { width };
};
// RIGHT
import { browser } from '$app/environment';
export const load = async () => {
const width = browser ? window.innerWidth : 1024;
return { width };
};❌ Accessing DOM in Load
// WRONG
export const load = async () => {
const el = document.getElementById('root'); // ERROR on server
};
// RIGHT - Do DOM stuff in onMount
export const load = async () => {
return {};
};
// Then in component:
onMount(() => {
const el = document.getElementById('root');
});Disable SSR (Not Recommended)
// +page.ts
export const ssr = false; // Disables SSR for this pageOnly use when absolutely necessary (e.g., heavy Canvas/WebGL).
svelte:boundary Component
Available in Svelte 5.3+
Two Purposes
1. Error boundaries - catch rendering errors 2. Pending UI - show loading state while await resolves
Basic Error Boundary
<svelte:boundary onerror={(e, reset) => console.error(e)}>
<RiskyComponent />
{#snippet failed(error, reset)}
<p>Error: {error.message}</p>
<button onclick={reset}>Try again</button>
{/snippet}
</svelte:boundary>Pending UI (Loading States)
⚠️ Known Bug:<svelte:boundary>+{@const await}causes
infinite navigation loops during client-side page transitions when
pages share async queries. See
sveltejs/svelte#17717.
Use {#await} blocks until this is fixed.With experimental.async: true (Svelte 5.36+), {@const await} is possible but not safe for pages with shared queries or navigation:
<!-- ⚠️ Causes navigation loops - use {#await} instead -->
<svelte:boundary>
{#snippet pending()}
<LoadingSpinner />
{/snippet}
{@const data = await loadData()}
<DataView {data} />
</svelte:boundary>Safe alternative:
{#await loadData()}
<LoadingSpinner />
{:then data}
<DataView {data} />
{:catch error}
<p>Error: {error.message}</p>
{/await}Combined Error + Pending
Use svelte:boundary for error catching only, with {#await} for async data:
<svelte:boundary onerror={logError}>
{#snippet failed(error, reset)}
<p>Failed to load user</p>
<button onclick={reset}>Retry</button>
{/snippet}
{#await fetchUser()}
<p>Loading user...</p>
{:then user}
<UserProfile {user} />
{:catch error}
<p>Error: {error.message}</p>
{/await}
</svelte:boundary>What Gets Caught
Caught:
- Errors during rendering
- Errors in
$effect
NOT Caught:
- Event handler errors (
onclick, etc.) - Errors after
setTimeout - Async errors outside boundary's await
vs +error.svelte
| Feature | svelte:boundary | +error.svelte |
|---|---|---|
| Scope | Component subtree | Route segment |
| Reset | Built-in reset function | Navigate away |
| Pending | Yes (pending snippet) | No |
| Use case | Component-level | Page-level |
Error Tracking Integration
<svelte:boundary
onerror={(error, reset) => {
// Send to Sentry, LogRocket, etc.
errorTracker.captureException(error);
}}
>
<App />
{#snippet failed(error, reset)}
<ErrorFallback {error} {reset} />
{/snippet}
</svelte:boundary>Nested Boundaries
Inner boundary catches first:
<svelte:boundary>
<!-- Outer fallback -->
{#snippet failed(e)}
<p>Outer caught: {e.message}</p>
{/snippet}
<svelte:boundary>
<!-- Inner fallback -->
{#snippet failed(e)}
<p>Inner caught: {e.message}</p>
{/snippet}
<ComponentThatMightFail />
</svelte:boundary>
</svelte:boundary>Key Points
- Use
svelte:boundaryfor component-level error isolation - Use
+error.sveltefor route-level error pages pendingsnippet shows only on initial load (not on refresh - no flicker)failedsnippet replaces content on errorresetfunction lets users retry- Errors in event handlers are NOT caught
- Requires
experimental.async: truein svelte.config.js for{@const await} - ⚠️ Bug:
{@const await}+ navigation causes infinite loops (#17717) — use{#await}instead
Related skills
FAQ
Which SvelteKit files does sveltekit-structure cover?
sveltekit-structure covers +page.svelte pages, +layout.svelte wrappers, +error.svelte error boundaries, and +server.ts API endpoints, including nested routes and layout inheritance across child paths.
When should I load sveltekit-structure?
Load sveltekit-structure when building or debugging SvelteKit routing, layouts, error handling, pending UI, SSR, hydration, or svelte:boundary patterns inside Cursor or Claude Code.
Is Sveltekit Structure safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.