The Complete SvelteKit Guide | Full Stack, Routing, Form Actions, Load, Hooks
이 글의 핵심
A complete guide to building full-stack web apps with SvelteKit: file-based routing, load functions, Form Actions, Hooks, and deployment—with practical examples. Focused on SvelteKit, Svelte, and full-stack development.
What this post covers
This is a complete guide to building full-stack web apps with SvelteKit. It walks through file-based routing, load functions, Form Actions, Hooks, and deployment—with practical examples.
From the field: While migrating a Next.js project to SvelteKit, we cut bundle size by about 60% and doubled initial load performance—here is what we learned.
Introduction: “Next.js feels too heavy”
Real-world scenarios
Scenario 1: getServerSideProps gets unwieldy
Data-fetching logic is split across layers. SvelteKit keeps it simple with load functions.
Scenario 2: The bundle is large
The React bundle is around 150KB. Svelte is about 20KB. Scenario 3: Forms are tedious
You end up maintaining separate API routes. SvelteKit simplifies this with Form Actions.
1. What is SvelteKit?
Core traits
SvelteKit is a full-stack framework built on Svelte. Main advantages:
- Small bundle: ~20KB (React is often ~150KB)
- Fast runtime: compile-time optimizations
- Minimal syntax: little boilerplate
- Full stack: SSR and APIs built in
- File-based routing: easy to navigate
2. Creating a project
Below is a short bash example. Run it locally to see how it behaves.
npm create svelte@latest my-app
cd my-app
npm install
npm run dev
3. File-based routing
Structure
This layout shows how routes map to files. Read it alongside the tree to see each piece’s role.
src/routes/
├── +page.svelte # /
├── about/
│ └── +page.svelte # /about
├── blog/
│ ├── +page.svelte # /blog
│ └── [slug]/
│ └── +page.svelte # /blog/:slug
└── api/
└── users/
└── +server.ts # /api/users
4. Load functions
+page.ts
This TypeScript example shows a typical load. It uses async/await for efficient data fetching—run it to verify the flow.
// src/routes/blog/+page.ts
export async function load({ fetch }) {
const response = await fetch('/api/posts');
const posts = await response.json();
return {
posts,
};
}
The Svelte page below consumes the data returned by load. Follow how data flows into the template.
<!-- src/routes/blog/+page.svelte -->
<script lang="ts">
export let data;
</script>
<h1>Blog</h1>
<ul>
{#each data.posts as post}
<li>
<a href="/blog/{post.slug}">{post.title}</a>
</li>
{/each}
</ul>
+page.server.ts
This server-only load imports what it needs, uses async/await, handles errors for stability, and branches with conditionals. Step through each part to see how it fits together.
// src/routes/blog/[slug]/+page.server.ts
import { error } from '@sveltejs/kit';
export async function load({ params }) {
const post = await db.post.findUnique({
where: { slug: params.slug },
});
if (!post) {
throw error(404, 'Post not found');
}
return { post };
}
5. Form Actions
+page.server.ts
This detailed TypeScript example defines Form Actions: imports, async work, validation-style failures, and a redirect on success. Read it line by line to see the flow.
// src/routes/login/+page.server.ts
import { fail, redirect } from '@sveltejs/kit';
export const actions = {
default: async ({ request, cookies }) => {
const data = await request.formData();
const email = data.get('email');
const password = data.get('password');
if (!email || !password) {
return fail(400, { email, missing: true });
}
const user = await authenticateUser(email, password);
if (!user) {
return fail(401, { email, incorrect: true });
}
cookies.set('session', user.sessionId, { path: '/' });
throw redirect(303, '/dashboard');
},
};
+page.svelte
This Svelte form uses progressive enhancement with enhance and surfaces server-returned errors. Each block handles a specific validation outcome.
<!-- src/routes/login/+page.svelte -->
<script lang="ts">
import { enhance } from '$app/forms';
export let form;
</script>
<form method="POST" use:enhance>
<input name="email" type="email" value={form?.email ?? ''} required />
<input name="password" type="password" required />
{#if form?.missing}
<p class="error">Email and password are required</p>
{/if}
{#if form?.incorrect}
<p class="error">Invalid credentials</p>
{/if}
<button type="submit">Login</button>
</form>
6. API routes
// src/routes/api/users/+server.ts
import { json } from '@sveltejs/kit';
export async function GET() {
const users = await db.user.findMany();
return json(users);
}
export async function POST({ request }) {
const data = await request.json();
const user = await db.user.create({
data: {
name: data.name,
email: data.email,
},
});
return json(user, { status: 201 });
}
7. Hooks
hooks.server.ts
This TypeScript hook imports Handle, runs async work per request, and branches on whether a session cookie exists. See how event.locals is populated before resolve.
// src/hooks.server.ts
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
const session = event.cookies.get('session');
if (session) {
event.locals.user = await getUserFromSession(session);
}
return resolve(event);
};
Usage
A server load can enforce auth using locals set in the hook: async flow, redirect when unauthenticated, return user data when allowed.
// src/routes/dashboard/+page.server.ts
import { redirect } from '@sveltejs/kit';
// Example run
export async function load({ locals }) {
if (!locals.user) {
throw redirect(303, '/login');
}
return {
user: locals.user,
};
}
8. Deployment
Vercel
npm install -D @sveltejs/adapter-vercel
Configure the Vercel adapter in svelte.config.js as shown below.
// svelte.config.js
import adapter from '@sveltejs/adapter-vercel';
export default {
kit: {
adapter: adapter(),
},
};
Cloudflare Pages
npm install -D @sveltejs/adapter-cloudflare
Node.js
npm install -D @sveltejs/adapter-node
Summary and checklist
Key takeaways
- SvelteKit: full-stack framework for Svelte
- Small bundle: ~20KB
loadfunctions: data fetching for pages- Form Actions: simpler form handling
- Hooks: cross-cutting request logic
- File-based routing: intuitive structure
Implementation checklist
- Create a SvelteKit project
- Implement routing
- Fetch data with
load - Add Form Actions
- Write API routes
- Configure Hooks
- Deploy
Related reading
- The Complete Svelte 5 Guide
- The Complete Remix Guide
- Next.js App Router Guide
Keywords in this post
SvelteKit, Svelte, Full Stack, SSR, Web Framework, JavaScript
Frequently asked questions (FAQ)
Q. SvelteKit vs Next.js—which should I pick?
A. SvelteKit tends to be lighter and faster. Next.js has the larger ecosystem. Prefer SvelteKit when raw performance matters; choose Next.js when ecosystem breadth is the priority.
Q. Do I need to know Svelte first?
A. Yes—SvelteKit is built on Svelte. That said, Svelte has a gentle learning curve.
Q. Is it production-ready?
A. Yes. SvelteKit 1.0 shipped and the framework is stable for real workloads.
Q. Does it support TypeScript?
A. Yes—first-class TypeScript support throughout.
Related Articles (Internal Links)
Other articles related to this topic.
Keywords Covered in This Article (Related Search Terms)
This article covers SvelteKit, Svelte, Full Stack, SSR, Web Framework, JavaScript.