Copy-paste Claude Code prompts for SvelteKit 2 — +page.server.ts loaders, form actions, hooks, and Svelte 5 runes. Plus Drizzle and Lucia patterns.
SvelteKit's file-based routing and explicit server/client boundaries give Claude Code a lot of structure to work with. Pin the Svelte version and the data-fetching policy, and Claude generates routes that match your patterns.
Build a new route /projects that:
- Loads the current user's projects via a +page.server.ts load function
- Uses Drizzle (db client at $lib/server/db) — read $lib/server/db/projects.ts first
- Supports cursor pagination: ?cursor= with page size 20
- Renders the list in +page.svelte using Svelte 5 runes ($props for the data)
- Each row links to /projects/[id]
Constraints:
- +page.server.ts: declare PageServerLoad type, use locals.user (set in
hooks.server.ts — read it first). Redirect to /login if no user.
- DON'T expose the DB query in +page.ts (must be server-only).
- Loading state in the UI uses $effect + a 'loading' rune — read existing
patterns in routes/dashboard/+page.svelte.
- Empty state component already exists at $lib/components/EmptyState.svelte —
reuse it.
Add a 'createProject' form action to /projects/new.
Requirements:
- +page.server.ts exports actions = { default: ... }
- Validate with zod schema in $lib/schemas/project.ts (read schemas/auth.ts as the
pattern — same naming, same error-shape)
- On invalid input: return fail(400, { errors, values }) — preserve user values
for the client to re-render
- On success: throw redirect(303, `/projects/${id}`)
- +page.svelte uses use:enhance with a custom handler that shows toast on
success and inline field errors on fail
- Errors typed: use the $page.form.errors with field names matching schema keys
Test: a Playwright spec in tests/projects-new.spec.ts that submits invalid
then valid data, checks inline errors then redirect.
Convert the existing /dashboard, /settings, /projects routes into a layout
group (authed) that:
- Has src/routes/(authed)/+layout.server.ts redirecting to /login if no
locals.user
- Shares a Sidebar component (already at $lib/components/Sidebar.svelte)
via the layout
- Lazy-loads heavy components inside the layout using await import on click
for /settings/billing (Stripe pricing table is heavy)
Constraints:
- Don't change URL paths — only directory structure
- Keep the existing tests green; update import paths in test files if needed
- Move only the routes I named — don't sweep other routes into the group
## Stack
SvelteKit 2 (Node adapter), Svelte 5 runes, TypeScript strict, Drizzle ORM,
Lucia for auth, Tailwind v4.
## Conventions
- Server data: +page.server.ts. Client-only fetch: +page.ts.
- Mutations: form actions, never custom POST endpoints unless an external
client (mobile app) needs JSON.
- Components in $lib/components, server utils in $lib/server.
- Zod schemas in $lib/schemas — one schema reused by both action and client.
- E2E: Playwright. Unit: Vitest + @testing-library/svelte.
Related: testing prompts, refactoring prompts.