/library / template-sveltekit-lucia
templateWeb app

SvelteKit + Drizzle + Lucia auth (full-stack with first-party session auth)

A SvelteKit full-stack app with Drizzle ORM, Lucia for session-based auth (no third-party), and Tailwind. Server actions + form-first interactions. Use when you want Svelte's DX and a backend you fully own.

use whenYou're tired of Next, want a smaller framework that ships less JS, and you don't want NextAuth/Clerk/Auth0 owning your sessions.

May 15, 20262,270 bytessveltekitsveltedrizzleluciaauth

[App Name] · SvelteKit + Lucia

Full-stack SvelteKit app. Server actions for mutations, Lucia for sessions, Drizzle for the DB. No third-party auth providers.

Source of truth

Vercel auto-deploys from main. Lucia stores sessions in Postgres (column on sessions table). Session cookie is httpOnly.

Tech stack

SvelteKit 2 + Svelte 5 (runes mode) + TypeScript. Drizzle ORM with Postgres. Lucia 4 for session-based auth (no JWTs, sessions live in your DB). Tailwind v4. Resend for transactional email (verification, password reset). Deployed to Vercel via @sveltejs/adapter-vercel.

Deploy

git push origin main. Vercel builds with the SvelteKit Vercel adapter. Postgres via Vercel Postgres or Neon.

File map

  • src/routes/ file-based routing
  • src/routes/(marketing)/ public: /, /pricing, /privacy
  • src/routes/(app)/ authed: /dashboard, /settings
  • src/routes/api/ route handlers (rare; prefer form actions)
  • src/lib/server/db/schema.ts Drizzle tables
  • src/lib/server/db/index.ts DB client
  • src/lib/server/auth.ts Lucia instance + session helpers
  • src/hooks.server.ts request hook attaching locals.user
  • drizzle.config.ts

.env keys

  • DATABASE_URL
  • RESEND_API_KEY
  • RESEND_FROM_EMAIL
  • PUBLIC_SITE_URL

Hard rules

  • Mutations via form actions (+page.server.ts actions), NOT API routes. Progressive enhancement matters.
  • All authed pages check locals.user in +page.server.ts load. NEVER trust the client.
  • Lucia sessions live in sessions table with an FK to users. Stale sessions cleaned via a cron.
  • Use Svelte 5 runes ($state, $derived, $effect). Don't mix in legacy $: reactive statements.
  • Form actions return either { form } or redirect(). Never return raw data the client can't use.
  • Password hashing with Lucia's recommended Argon2id, NOT bcrypt.

Recent significant changes

  • 2026-05-15: Scaffolded. Locked: Lucia over Auth.js (full control of session lifetime), Drizzle over Prisma (smaller, faster), Resend over SendGrid (DX).

Next session: start here

  1. Create Vercel project + Postgres.
  2. npm run db:push to apply Drizzle schema.
  3. Implement signup form action. Test the cookie flow with a real browser.
  4. Add a protected /dashboard page; confirm unauthed redirects to login.
  5. Set up Resend with verified domain for the magic-link / verification emails.

Get the next CLAUDE.md in your inbox.

One new template every week, plus occasional case studies.