From svelte-ts-bun
Build SvelteKit 2 web applications using Svelte 5 runes mode, with colocated component/route tests under Bun and file-based routing. Use when creating new SvelteKit apps, adding routes/components, or extending an existing SvelteKit codebase that follows these conventions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/svelte-ts-bun:creating-sveltekit-web-appsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill guides the creation of SvelteKit web applications using the structural and stylistic conventions of a well-organized SvelteKit 2 project. It targets Svelte 5 runes mode, file-based routing, and colocated tests run under Bun.
This skill guides the creation of SvelteKit web applications using the structural and stylistic conventions of a well-organized SvelteKit 2 project. It targets Svelte 5 runes mode, file-based routing, and colocated tests run under Bun.
The skill is deployment-target agnostic. Every pattern here applies regardless of the adapter you use (Node, static, serverless, etc.). It says nothing about a specific hosting platform, database engine, or deployment configuration.
Use when:
+page.svelte + optional +page.server.ts)+server.ts)$lib/components/$lib/server/Do NOT use this skill for: configuring deployment targets, choosing a database engine, configuring a build pipeline, or anything else outside the application code itself.
Always start with the workflow checklist. Copy the appropriate checklist into a TODO list and track progress through each phase:
| Task | Workflow |
|---|---|
| Bootstrap a new app | New Project Workflow |
| Add a page route | New Page Route Workflow |
| Add an API route | New API Route Workflow |
| Add a component | New Component Workflow |
| Modify existing code | Modify Workflow |
The workflow includes validation loops at each phase. Do not skip validation steps.
Consult these when implementing specific phases of the workflow:
| Document | Use When |
|---|---|
| workflow.md | Choosing or following a phase-by-phase workflow with validation checkpoints |
| routing_patterns.md | Implementing pages, API endpoints, layouts, hooks, parameterized routes |
| component_patterns.md | Writing Svelte 5 runes-mode components — props, state, effects, derived values, callback props |
| data_loading.md | Writing load functions, request handlers, $lib/server modules, and auth-gated data flow |
| testing_patterns.md | Writing colocated tests for components, routes, hooks, and library modules under Bun |
| code_style.md | Following the ts-standard linting rules and file/identifier conventions used in this skill |
A SvelteKit app following these conventions has this top-level layout:
project-root/
├── src/
│ ├── app.css # Global CSS variables and base styles
│ ├── app.d.ts # App.Locals, App.Platform, App.Error types
│ ├── app.html # HTML shell, contains %sveltekit.head% and %sveltekit.body%
│ ├── hooks.server.ts # Server hooks (auth gating, locals population)
│ ├── hooks.server.test.ts # Tests for server hooks
│ ├── lib/
│ │ ├── index.ts # $lib barrel (often empty — paths use $lib/foo directly)
│ │ ├── components/ # Reusable Svelte components (.svelte + .test.ts)
│ │ ├── server/ # Server-only modules (cannot be imported by client code)
│ │ └── assets/ # Static assets imported into Svelte
│ ├── routes/
│ │ ├── +layout.svelte # Root layout
│ │ ├── +page.svelte # Root page
│ │ ├── +page.server.ts # Root page's load function
│ │ └── (route groups)/
│ └── tests/
│ ├── svelte-loader.ts # Bun preload — compiles .svelte on the fly + happy-dom setup
│ ├── use-native-fetch.ts # Restores native Response/Request for server-side tests
│ ├── mock-event.ts # mockRequestEvent, mockUser, expectHttpError helpers
│ ├── mock-db.ts # Generic database mock for SQL-style assertions
│ └── (shared test factories)
├── static/ # Files served verbatim at the site root
├── package.json
├── svelte.config.js # Adapter + runes mode enforcement
├── tsconfig.json # Extends .svelte-kit/tsconfig.json, adds strict mode
├── vite.config.ts # Vite plugins (sveltekit() at minimum)
└── bunfig.toml # [test] preload — points at src/tests/svelte-loader.ts
Foo.svelte has its tests at Foo.test.ts in the same directory. A route handler at +server.ts has tests at server.test.ts. A library module at auth.ts has tests at auth.test.ts.$lib/server/ is server-only. SvelteKit will refuse to bundle anything from $lib/server/ into client code. Put database code, secrets handling, and server-side notification logic there.event.locals. Populated by hooks.server.ts, consumed by load functions and request handlers. The hook is also where you decide whether a request continues, redirects, or returns 401.src/tests/. Don't recreate mockRequestEvent or MockDatabase in each test file — import them.Three configuration files set up the conventions this skill assumes. They should be created at project bootstrap and rarely changed after.
svelte.config.jsimport adapter from '@sveltejs/adapter-auto'
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
},
vitePlugin: {
// Enable runes mode for all project source; opt out for node_modules
dynamicCompileOptions: ({ filename }) =>
filename.includes('node_modules') ? undefined : { runes: true }
}
}
export default config
The runes: true setting is required — every component pattern in this skill assumes runes mode.
tsconfig.json{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"rewriteRelativeImportExtensions": true,
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
}
strict: true is required. The patterns rely on TypeScript catching null/undefined mistakes.
bunfig.toml[test]
preload = ["./src/tests/svelte-loader.ts"]
The preload file compiles .svelte files on the fly and registers happy-dom globally. See testing_patterns.md for its contents.
package.json scripts{
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test": "bun test --conditions browser",
"test:watch": "bun test --conditions browser --watch",
"lint": "ts-standard",
"format": "ts-standard --fix"
}
}
The --conditions browser flag is required so Bun resolves Svelte's browser entry points when running tests.
Most code in this skill is one of four things. Knowing which one you're writing tells you where the file goes, what it imports, and how it's tested:
| Concept | File pattern | Runs on | Tested with |
|---|---|---|---|
| Component | Foo.svelte | Browser (and SSR) | @testing-library/svelte + happy-dom |
| Page route | +page.svelte (+ optional +page.server.ts) | Both | Component test for .svelte, request-event test for .server.ts |
| API/server route | +server.ts | Server only | Request-event test with mockRequestEvent |
| Library module | $lib/foo.ts or $lib/server/foo.ts | Browser, server, or both | Plain unit test |
Each has a dedicated section in the reference documents.
After each implementation phase, run the validation loop:
bun run check && bun run lint && bun run test
Specifically:
| Step | Command | Catches |
|---|---|---|
| Type-check | bun run check | TypeScript errors, Svelte template errors, missing imports, runes-mode violations |
| Lint | bun run lint | Style violations (ts-standard) |
| Test | bun run test | Behavior regressions |
Fix all errors before proceeding to the next phase.
To run a single test file during iteration:
bun run test -- src/lib/components/Foo.test.ts
$lib/server/. Never put DB access or secrets in plain $lib/ — SvelteKit can't enforce the boundary outside $lib/server/.event.locals for auth state, not module globals. Hooks populate it; load functions and handlers consume it.error(400, …) before doing any work.bun run check before declaring something done — runes-mode mistakes are easy to make and are caught here.Before marking a feature complete, verify:
## Final Validation: [FEATURE]
### Structure
- [ ] Component lives in $lib/components/ if reusable, or inline if page-specific
- [ ] Server-only code lives in $lib/server/
- [ ] Tests are colocated next to source as `*.test.ts`
- [ ] Shared test factories used (no duplicated mockRequestEvent etc.)
### Code
- [ ] Svelte 5 runes ($state, $props, $effect, $derived) — no legacy reactive syntax
- [ ] No semicolons, single quotes, 2-space indent (ts-standard)
- [ ] All inputs validated at handler boundary
- [ ] Auth checks return 401 for missing user, 404 for not-found-or-not-yours
- [ ] Errors thrown via `error()`, JSON returned via `json()`
### Tests
- [ ] Component tests cover render, props, events, edge cases
- [ ] Route tests cover 401 (when applicable), 404, 400, success, and binding correctness
- [ ] Hook tests cover each branch of the auth/access gate
- [ ] No real network, no real DB — all external calls mocked
### Validation Passed
- [ ] `bun run check` passes (zero errors)
- [ ] `bun run lint` passes
- [ ] `bun run test` passes (no failures, no skips)
- [ ] Feature exercised in `bun run dev` for UI-affecting changes
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub dickdavis/personal-marketplace --plugin svelte-ts-bun