[{"data":1,"prerenderedAt":192},["ShallowReactive",2],{"blog-blueprints/sveltekit-supabase":3},{"id":4,"title":5,"body":6,"category":172,"date":173,"dateModified":173,"description":174,"draft":175,"extension":176,"faq":177,"featured":175,"headerVariant":178,"image":177,"keywords":177,"meta":179,"navigation":180,"ogDescription":181,"ogTitle":177,"path":182,"readTime":183,"schemaOrg":184,"schemaType":185,"seo":186,"sitemap":187,"stem":188,"tags":189,"twitterCard":190,"__hash__":191},"blog/blog/blueprints/sveltekit-supabase.md","SvelteKit + Supabase Security Blueprint",{"type":7,"value":8,"toc":161},"minimark",[9,20,23,29,34,49,53,62,66,75,79,84,87,90,93,96,99,113,149],[10,11,12],"blueprint-summary",{},[13,14,15,19],"p",{},[16,17,18],"strong",{},"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.",[21,22],"blueprint-meta",{},[24,25,26],"tldr",{},[13,27,28],{},"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.",[30,31,33],"h2",{"id":32},"server-hooks-setup-sveltekit-supabase","Server Hooks Setup SvelteKit Supabase",[35,36,38],"code-block",{"label":37},"src/hooks.server.ts",[39,40,45],"pre",{"className":41,"code":43,"language":44},[42],"language-text","import { createServerClient } from '@supabase/ssr'\nimport type { Handle } from '@sveltejs/kit'\n\nexport const handle: Handle = async ({ event, resolve }) => {\n  event.locals.supabase = createServerClient(\n    PUBLIC_SUPABASE_URL,\n    PUBLIC_SUPABASE_ANON_KEY,\n    {\n      cookies: {\n        get: (key) => event.cookies.get(key),\n        set: (key, value, options) => {\n          event.cookies.set(key, value, { ...options, path: '/' })\n        },\n        remove: (key, options) => {\n          event.cookies.delete(key, { ...options, path: '/' })\n        },\n      },\n    }\n  )\n\n  event.locals.getSession = async () => {\n    const { data: { session } } = await event.locals.supabase.auth.getSession()\n    return session\n  }\n\n  return resolve(event)\n}\n","text",[46,47,43],"code",{"__ignoreMap":48},"",[30,50,52],{"id":51},"protected-load-functions-sveltekit","Protected Load Functions SvelteKit",[35,54,56],{"label":55},"src/routes/dashboard/+page.server.ts",[39,57,60],{"className":58,"code":59,"language":44},[42],"import { redirect } from '@sveltejs/kit'\n\nexport async function load({ locals }) {\n  const { data: { user } } = await locals.supabase.auth.getUser()\n\n  if (!user) {\n    throw redirect(303, '/login')\n  }\n\n  const { data: posts } = await locals.supabase\n    .from('posts')\n    .select('*')\n    .eq('author_id', user.id)\n\n  return { posts, user }\n}\n",[46,61,59],{"__ignoreMap":48},[30,63,65],{"id":64},"secure-form-actions-sveltekit","Secure Form Actions SvelteKit",[35,67,69],{"label":68},"Form actions with auth",[39,70,73],{"className":71,"code":72,"language":44},[42],"export const actions = {\n  create: async ({ locals, request }) => {\n    const { data: { user } } = await locals.supabase.auth.getUser()\n\n    if (!user) {\n      return fail(401, { error: 'Unauthorized' })\n    }\n\n    const formData = await request.formData()\n\n    await locals.supabase.from('posts').insert({\n      title: formData.get('title'),\n      author_id: user.id  // Use verified user ID\n    })\n\n    return { success: true }\n  }\n}\n",[46,74,72],{"__ignoreMap":48},[30,76,78],{"id":77},"security-checklist","Security Checklist",[80,81,83],"h4",{"id":82},"pre-launch-checklist","Pre-Launch Checklist",[13,85,86],{},"RLS enabled on all tables",[13,88,89],{},"Auth verified in all load functions",[13,91,92],{},"Auth verified in all form actions",[13,94,95],{},"Hooks properly configured",[13,97,98],{},"Environment variables set",[100,101,102,108],"related-articles",{},[103,104],"related-card",{"description":105,"href":106,"title":107},"Alternative framework","/blog/blueprints/nextjs-supabase-vercel","Next.js + Supabase",[103,109],{"description":110,"href":111,"title":112},"Deep dive","/blog/guides/supabase","Supabase Security Guide",[114,115,116,121,124],"stack-comparison",{},[117,118,120],"h3",{"id":119},"alternative-stacks","Alternative Stacks",[13,122,123],{},"Consider these related blueprints:",[125,126,127,135,142],"ul",{},[128,129,130,134],"li",{},[131,132,133],"a",{"href":106},"Next.js + Supabase + Vercel"," - Next.js alternative",[128,136,137,141],{},[131,138,140],{"href":139},"/blog/blueprints/remix-supabase","Remix + Supabase"," - Remix alternative",[128,143,144,148],{},[131,145,147],{"href":146},"/blog/blueprints/nuxt-supabase","Nuxt + Supabase"," - Vue/Nuxt alternative",[150,151,154,158],"cta-box",{"href":152,"label":153},"/","Start Free Scan",[30,155,157],{"id":156},"building-with-this-stack","Building with this stack?",[13,159,160],{},"Scan for RLS and auth issues.",{"title":48,"searchDepth":162,"depth":162,"links":163},2,[164,165,166,167,171],{"id":32,"depth":162,"text":33},{"id":51,"depth":162,"text":52},{"id":64,"depth":162,"text":65},{"id":77,"depth":162,"text":78,"children":168},[169],{"id":119,"depth":170,"text":120},3,{"id":156,"depth":162,"text":157},"blueprints","2026-02-11","Security guide for SvelteKit + Supabase stack. Configure RLS, handle auth with hooks, protect server routes and form actions, and secure your SvelteKit app.",false,"md",null,"purple",{},true,"Complete security configuration for SvelteKit apps with Supabase.","/blog/blueprints/sveltekit-supabase","10 min read","[object Object]","Article",{"title":5,"description":174},{"loc":182},"blog/blueprints/sveltekit-supabase",[],"summary_large_image","MM1jiu-8jG6x180UqI9iOAcfDHMm3Jz4YEc0cmv1o2o",1775843932088]