install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/svelte-server-hooks" ~/.claude/skills/intense-visions-harness-engineering-svelte-server-hooks-92ebdc && rm -rf "$T"
manifest:
agents/skills/codex/svelte-server-hooks/SKILL.mdsource content
Svelte Server Hooks
Intercept every request, populate locals, modify responses, and handle errors using SvelteKit's hooks.server.ts
When to Use
- You need to validate session cookies and attach a user object to every request
- You want to add CORS headers, rate limiting, or logging across all routes
- You need to modify outgoing responses (add security headers, compress, cache)
- You are composing multiple
functions usinghandlesequence - You want to capture and report unhandled server errors
Instructions
handle — the main request hook:
- Export a
function fromhandle
. It intercepts every request and must callsrc/hooks.server.ts
to continue:resolve(event)
// src/hooks.server.ts import type { Handle } from '@sveltejs/kit'; export const handle: Handle = async ({ event, resolve }) => { // Runs before load functions and routes const response = await resolve(event); // Runs after return response; };
- Attach per-request data to
— accessible in all load functions and actions:event.locals
export const handle: Handle = async ({ event, resolve }) => { const sessionId = event.cookies.get('session_id'); if (sessionId) { event.locals.user = await db.session.findUser(sessionId); } return resolve(event); };
// src/app.d.ts — declare the locals shape declare global { namespace App { interface Locals { user: User | null; } } } export {};
- Short-circuit a request (bypass routing) by returning a response directly:
export const handle: Handle = async ({ event, resolve }) => { if (event.url.pathname.startsWith('/api') && !event.locals.user) { return new Response('Unauthorized', { status: 401 }); } return resolve(event); };
- Modify the resolved response to add security headers:
export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event); response.headers.set('X-Frame-Options', 'DENY'); response.headers.set('X-Content-Type-Options', 'nosniff'); response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin'); return response; };
- Use
to modify HTML output (inject scripts, replace placeholders):transformPageChunk
const response = await resolve(event, { transformPageChunk: ({ html }) => html.replace('%theme%', event.locals.theme ?? 'light'), });
sequence — composing multiple handle functions:
- Use
fromsequence
to chain multiple handle functions cleanly:@sveltejs/kit/hooks
import { sequence } from '@sveltejs/kit/hooks'; import { auth } from './hooks/auth'; import { logging } from './hooks/logging'; import { security } from './hooks/security'; export const handle = sequence(auth, logging, security);
Each function in the sequence calls
resolve(event) to pass to the next.
handleFetch — modifying server-side fetch calls:
- Intercept
calls made inside load functions (only on the server during SSR):fetch
import type { HandleFetch } from '@sveltejs/kit'; export const handleFetch: HandleFetch = async ({ request, fetch }) => { // Rewrite internal API calls to avoid the network round-trip if (request.url.startsWith('https://myapp.com/api/')) { const url = request.url.replace('https://myapp.com', 'http://localhost:3000'); return fetch(new Request(url, request)); } return fetch(request); };
handleError — unhandled server errors:
- Capture and report unexpected errors. The return value shapes what
contains:$page.error
import type { HandleServerError } from '@sveltejs/kit'; export const handleError: HandleServerError = async ({ error, event, status, message }) => { const errorId = crypto.randomUUID(); // Log to your error tracking service await reportError({ error, errorId, url: event.url.pathname }); // Return safe error info (never expose internals) return { message: 'An unexpected error occurred', errorId, }; };
Client hooks (hooks.client.ts):
- Export
fromhandleError
to capture client-side errors:src/hooks.client.ts
// src/hooks.client.ts import type { HandleClientError } from '@sveltejs/kit'; export const handleError: HandleClientError = ({ error, event }) => { Sentry.captureException(error); return { message: 'Something went wrong' }; };
Details
Execution order:
Request → handle (hooks.server.ts) → layout load (+layout.server.ts) → page load (+page.server.ts) → page renders ← response ← response ← handle (can modify) Response
locals type safety:
Always declare your
App.Locals interface in src/app.d.ts. TypeScript will then infer the correct types when you access event.locals in load functions and actions.
Auth pattern:
// hooks/auth.ts import type { Handle } from '@sveltejs/kit'; export const auth: Handle = async ({ event, resolve }) => { const token = event.cookies.get('auth_token'); event.locals.user = token ? await verifyToken(token) : null; return resolve(event); }; // Any load function: export const load: PageServerLoad = ({ locals }) => { if (!locals.user) redirect(303, '/login'); return { user: locals.user }; };
CORS for API routes:
export const handle: Handle = async ({ event, resolve }) => { if (event.request.method === 'OPTIONS') { return new Response(null, { status: 204, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }, }); } const response = await resolve(event); response.headers.set('Access-Control-Allow-Origin', '*'); return response; };
handleFetch use cases:
- Replace public API URLs with internal service URLs during SSR (avoid DNS round-trip)
- Inject auth headers into all server-side fetch calls
- Mock API calls in test environments
Source
https://kit.svelte.dev/docs/hooks
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.