To secure a SvelteKit + Supabase stack, you need to: (1) configure hooks.server.ts for Supabase client and session handling, (2) verify auth using getUser() in all +page.server.ts load functions, (3) verify auth in all form actions before mutations, (4) enable RLS as defense-in-depth, and (5) pass the Supabase client through locals. This blueprint covers SvelteKit's hooks system with Supabase SSR patterns.
TL;DR
SvelteKit's hooks system pairs perfectly with Supabase auth. Key tasks: use hooks.server.ts for session handling, verify auth in all +page.server.ts load functions and form actions, enable RLS as defense-in-depth, and use locals for passing the Supabase client.
Server Hooks Setup SvelteKit Supabase
import { createServerClient } from '@supabase/ssr'
import type { Handle } from '@sveltejs/kit'
export const handle: Handle = async ({ event, resolve }) => {
event.locals.supabase = createServerClient(
PUBLIC_SUPABASE_URL,
PUBLIC_SUPABASE_ANON_KEY,
{
cookies: {
get: (key) => event.cookies.get(key),
set: (key, value, options) => {
event.cookies.set(key, value, { ...options, path: '/' })
},
remove: (key, options) => {
event.cookies.delete(key, { ...options, path: '/' })
},
},
}
)
event.locals.getSession = async () => {
const { data: { session } } = await event.locals.supabase.auth.getSession()
return session
}
return resolve(event)
}
Protected Load Functions SvelteKit
import { redirect } from '@sveltejs/kit'
export async function load({ locals }) {
const { data: { user } } = await locals.supabase.auth.getUser()
if (!user) {
throw redirect(303, '/login')
}
const { data: posts } = await locals.supabase
.from('posts')
.select('*')
.eq('author_id', user.id)
return { posts, user }
}
Secure Form Actions SvelteKit
export const actions = {
create: async ({ locals, request }) => {
const { data: { user } } = await locals.supabase.auth.getUser()
if (!user) {
return fail(401, { error: 'Unauthorized' })
}
const formData = await request.formData()
await locals.supabase.from('posts').insert({
title: formData.get('title'),
author_id: user.id // Use verified user ID
})
return { success: true }
}
}
Security Checklist
Pre-Launch Checklist
RLS enabled on all tables
Auth verified in all load functions
Auth verified in all form actions
Hooks properly configured
Environment variables set
Alternative Stacks
Consider these related blueprints:
- Next.js + Supabase + Vercel - Next.js alternative
- Remix + Supabase - Remix alternative
- Nuxt + Supabase - Vue/Nuxt alternative