Files
crumbs-original/.agents/skills/sveltekit-structure/references/ssr-hydration.md
T
Frederic CabassutandClaude Opus 4.6 02e6b57764 chore: add agent skills for Svelte 5, SvelteKit, TypeScript, and Drizzle
Install project-level skills via skills.sh CLI:
- svelte5-best-practices (runes, snippets, events, migration)
- sveltekit-structure (routing, layouts, error boundaries)
- sveltekit-data-flow (load functions, form actions, serialization)
- typescript-best-practices (type-first development, discriminated unions)
- drizzle-migrations (SQLite schema, query patterns)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 14:11:36 +01:00

1.8 KiB

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');
});
// +page.ts
export const ssr = false; // Disables SSR for this page

Only use when absolutely necessary (e.g., heavy Canvas/WebGL).