SvelteKit didn’t win the framework wars; it doesn’t need to. By 2026 it’s a mature, beloved alternative for teams that prefer simpler abstractions. This post is the working set.

Svelte 5 runes

<script>
  let count = $state(0);
  let doubled = $derived(count * 2);
  
  $effect(() => {
    console.log("count is", count);
  });
</script>

<button onclick={() => count++}>{count}  {doubled}</button>

Explicit reactivity primitives: $state, $derived, $effect. Better than the old $: magic. Cleaner TS.

Routes

src/routes/
├── +layout.svelte
├── +page.svelte           → /
├── about/
│   └── +page.svelte       → /about
├── posts/
│   ├── +page.svelte       → /posts
│   └── [slug]/
│       ├── +page.svelte   → /posts/<slug>
│       └── +page.server.ts

File-system routing. +page.svelte, +page.server.ts (server-side load), +page.ts (universal load).

Load functions

// +page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params, locals }) => {
    const post = await db.post.findUnique({ where: { slug: params.slug } });
    if (!post) throw error(404);
    return { post };
};
<!-- +page.svelte -->
<script lang="ts">
  let { data } = $props();
</script>

<h1>{data.post.title}</h1>

Server runs load; data passed as props to the page. Type-safe end-to-end.

Form actions

// +page.server.ts
export const actions = {
    create: async ({ request, locals }) => {
        const form = await request.formData();
        const title = form.get('title');
        await db.post.create({ data: { title } });
        return { success: true };
    },
};
<form method="POST" action="?/create">
  <input name="title" />
  <button>Create</button>
</form>

Forms work without JS; enhance with use:enhance for SPA-like UX. Similar to Remix’s pattern.

Hooks

// hooks.server.ts
export const handle: Handle = async ({ event, resolve }) => {
    event.locals.user = await getUserFromCookie(event);
    return resolve(event);
};

Auth, logging, headers — middleware-style. Available throughout server-side via locals.

Adapters

// svelte.config.js
import adapter from '@sveltejs/adapter-node';      // Node server
// or '@sveltejs/adapter-cloudflare'               // CF Workers
// or '@sveltejs/adapter-vercel'
// or '@sveltejs/adapter-static'                   // SSG

export default { kit: { adapter: adapter() } };

Same code; different deploy targets. Excellent flexibility — Vercel, Cloudflare Workers, Node, static export, AWS Lambda.

Performance

  • Bundle size: typically 30-40% smaller than React equivalents.
  • Runtime: Svelte’s compiled output is lean.
  • HMR: very fast.
  • First paint: small JS payload helps.

For latency-sensitive / mobile-heavy apps: SvelteKit’s bundle savings are real.

TypeScript

<script lang="ts">
  import type { User } from '$lib/types';
  
  let { user, onUpdate }: { user: User; onUpdate: (u: User) => void } = $props();
</script>

Solid TS support. Generated $types per route. Less magic than Next.js.

Stores (legacy)

Pre-runes Svelte had stores. Still supported; less needed in Svelte 5:

import { writable } from 'svelte/store';
export const count = writable(0);

Most state in Svelte 5: just runes in shared modules.

Comparison to Next.js

SvelteKitNext.js
Component modelSvelteReact
Server / client+page.server.ts / +page.tsRSC / Client Components
MutationsForm actionsServer Actions
File routingFoldersFolders
Bundle sizeSmallerLarger
EcosystemSmallerBigger
HostingMany adaptersVercel-best
Learning curveLowerHigher (RSC)
HiringHarderEasier

For pure DX: SvelteKit. For ecosystem / hiring: Next.js.

Real-world patterns

Auth

// hooks.server.ts
export const handle: Handle = async ({ event, resolve }) => {
    const session = event.cookies.get('session');
    if (session) {
        event.locals.user = await verifySession(session);
    }
    return resolve(event);
};

// +page.server.ts (protected)
export const load: PageServerLoad = async ({ locals }) => {
    if (!locals.user) throw redirect(302, '/login');
    return {};
};

Data fetching

// Universal load (runs server + client)
// +page.ts
export const load: PageLoad = async ({ fetch }) => {
    const res = await fetch('/api/posts');
    return { posts: await res.json() };
};

// Server-only load
// +page.server.ts
export const load: PageServerLoad = async () => {
    return { posts: await db.post.findMany() };
};

+page.ts runs both sides; safe data only. +page.server.ts runs server-only; can use secrets, DB.

API routes

// +server.ts
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async ({ params }) => {
    const post = await db.post.findUnique({ where: { id: params.id } });
    return new Response(JSON.stringify(post));
};

Tied to file-system routes. REST endpoints next to pages.

Deployment patterns

  • Vercel: 1-click; great DX.
  • Cloudflare Workers + KV: edge; cheap; AWS-free.
  • Self-host Node: standard server.
  • Static (adapter-static): SSG for blog/docs.

When to pick SvelteKit

  • Small/medium team without React experience.
  • Performance-critical (bundle size, perceived speed).
  • Wanting less framework magic.
  • DX-driven decisions.

When to pick Next.js

  • Big team with React experience.
  • Need component library ecosystem.
  • Hiring market matters.
  • Vercel-first deployment.

Both are valid in 2026.

Common mistakes

1. Stores when runes work

Old habits. Rewrite to runes for Svelte 5.

2. Universal +page.ts for sensitive data

Runs on client too; secrets leak. Use +page.server.ts.

3. Adapter mismatch

adapter-node deployed on Cloudflare Workers fails. Match adapter to target.

4. Form action without progressive enhancement

use:enhance is the difference between full reload and SPA UX.

5. Missing $types

Skipping types; lose end-to-end safety. Run svelte-kit sync to generate them.

What I’d ship today

For a new SvelteKit app:

  • Svelte 5 runes universally.
  • +page.server.ts for protected pages.
  • Form actions with use:enhance for UX.
  • adapter-node or adapter-cloudflare based on hosting.
  • Drizzle / Prisma for DB.
  • Zod for validation.
  • Vitest for tests.

Read this next

If you want my SvelteKit + Drizzle + Lucia auth starter, it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .