set-up-supabase-auth
Sets up Supabase authentication (email magic link, password or Google OAuth) in a Next.js app with server-side sessions, protected routes and row level security. Use when the user wants login, sign in, sign up, user accounts, auth, or to protect pages and data per user.
Version 1.1 · Updated 2026-10-31
Install in Claude Code, Cursor or Codex (optional)
Only for AI coding tools that read skill folders. Run one line in a terminal, in your project folder. It downloads this skill's text files from TheSkillVault and nothing else; you can read them first with “View raw SKILL.md”.
Claude Code (all your projects)
curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/set-up-supabase-auth/raw' -o ~/'.claude/skills/set-up-supabase-auth/SKILL.md'Cursor (this project)
curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/set-up-supabase-auth/raw' -o '.cursor/skills/set-up-supabase-auth/SKILL.md'Codex and other Agent Skills tools (this project)
curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/set-up-supabase-auth/raw' -o '.agents/skills/set-up-supabase-auth/SKILL.md'
Or connect the whole library over MCP
Add TheSkillVault to Cursor or add this to your app's MCP settings (read-only; help):
{
"mcpServers": {
"theskillvault": {
"url": "https://theskillvault.ai/mcp"
}
}
}Set up Supabase auth
Supabase Auth handles sign-up, sign-in and sessions for you. In Next.js the session lives in cookies, so the server and the browser both need their own Supabase client. This skill wires that up and protects pages and data per user.
When to use
- Adding login or sign-up to a Next.js App Router project backed by Supabase.
- Adding Google or another OAuth provider, or email magic links.
- Making pages or data visible only to the signed-in user.
Steps
npm i @supabase/supabase-js @supabase/ssr; addNEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_ANON_KEY(the publishable key) to.env.local.- Create two clients:
createBrowserClientfor client components andcreateServerClient(with Nextcookies()) for server components, route handlers and server actions. - Add
middleware.ts(calledproxy.tsin Next.js 16) that refreshes the session on each request and redirects signed-out users away from/app/*. - Enable providers in the Supabase dashboard (Email, Google). Set the Site URL and redirect URLs for localhost and production.
- Add an
/auth/callbackroute that callsexchangeCodeForSession(code). - Turn on row level security for every table and add policies such as
using ((select auth.uid()) = user_id). For full schema, policy and index guidance, usedesign-supabase-postgres-schema. - On the server, trust
supabase.auth.getUser()orgetClaims()(they verify the token), notgetSession(). - Test with two accounts: sign up, sign out, sign in again, and confirm each user sees only their own data.
Gotchas
- RLS on with no policies means every query returns zero rows. That is the usual "it worked yesterday" bug.
- Magic links fail if the redirect URL is not allow-listed.
- Session refresh in middleware must return the response with the updated cookies, or users get signed out at random.
Safety
- Never ship the
service_roleor secret key to the browser or prefix it withNEXT_PUBLIC_. It bypasses RLS. - Keep
.env.localout of git. Never paste keys or user passwords into chat or logs. - Do not store passwords yourself. Supabase Auth hashes them for you.
Works with other stacks
The same steps work with Remix, SvelteKit or Nuxt, since @supabase/ssr supports any cookie-based server framework. If you use Clerk, Auth.js or Firebase Auth instead, the shape is equivalent: server-side session check, protected routes, per-user data rules.
Done when
- Sign-up, sign-in and sign-out work on localhost and production URLs.
- Signed-out visitors are redirected away from protected pages.
- RLS is on, and a second test user cannot see the first user's data.
Example prompt
"Add Google login with Supabase and make the dashboard only visible to signed-in users."
Licence: CC BY 4.0. Attribution when you reuse it: From TheSkillVault, https://theskillvault.ai, CC BY 4.0