AuthTemplate

A Next.js + Supabase starting point with email/password sign-up, login, sessions, and protected routes already wired up โ€” so you can skip the auth boilerplate and get straight to building. Follow the steps below to connect your own Supabase project and deploy it.

What's included

Everything not marked "delete when ready" is the actual template โ€” keep it. Click a file or folder with a ๐Ÿ’ก for details.

src/
app/

Onboarding content only โ€” the landing page you're looking at right now, this file-tree section, the setup guide below, and the /dashboard example. It's a route group: the parentheses keep it out of the URL, so deleting the whole folder won't break any other route. Delete it once you've replaced the home page with your own. ยท delete when ready

Every auth route and its shared UI, all in one place โ€” not to be confused with lib/auth/ further down, which holds the actual signUp/signIn/signOut logic this folder calls into.

lib/

Forgot password?

Don't have an account? Sign up

Setup guide

Prerequisites

01

Install Node.js

Version 20.19 or newer (22 or 24 LTS recommended).

nodejs.org
Terminal
node -v
02

Install Docker Desktop and make sure it's running

Supabase's local stack (Postgres, auth, storage) runs inside Docker containers on your machine.

New to Docker? It packages a program with everything it needs into a self-contained "container," like a lightweight virtual machine. You don't need to learn it โ€” just:

  • Install Docker Desktop
  • Open it once so it's running (look for its icon in your menu bar/taskbar)
  • Leave it running in the background โ€” nothing else in this guide asks you to touch it directly
Get Docker
Terminal
docker info

Get the code

03

Use this template

Click "Use this template" on GitHub to get your own copy, then clone it.

github.com/rl3020/AuthTemplate
Terminal
git clone <your-repo-url>

Local setup

04

Install dependencies and start local Supabase

npm install pulls down (see package.json for the full list):

  • Next.js and React โ€” the framework
  • The Supabase client libraries
  • The Supabase CLI itself โ€” a project dependency, not a global install, so every supabase command here runs through npx
package.json
Terminal
npm install
npx supabase start
05

Set up your env file and run the app

  • cp copies .env.example to .env.local โ€” paste in the Publishable key that supabase start just printed
  • npm run dev starts the Next.js dev server, which reads that file and talks to your local Supabase stack, not a production one
Terminal
cp .env.example .env.local
npm run dev

Create a Supabase project

06

Create the project

Note the Project URL and Publishable key (Project Settings โ†’ API), and the database password (Project Settings โ†’ Database).

supabase.com/dashboard

Generate an access token

07

Create a personal access token

Scope it to this project โ€” it's used by GitHub Actions to push migrations.

Account โ†’ Access Tokens

Wire up GitHub Actions

08

Add three repository secrets

The migration workflow below needs these to authenticate as you and reach your database โ€” without them it fails with no way to connect.

  • Add them at: your GitHub repo โ†’ Settings โ†’ Secrets and variables โ†’ Actions (your repo, not this template's)
  • Names must match exactly โ€” see the panel
GitHub docs: creating repository secrets
GitHub Secrets
SUPABASE_ACCESS_TOKEN
SUPABASE_PROJECT_REF
SUPABASE_DB_PASSWORD

Your first migration is already here

09

This template ships one migration โ€” you don't need to create it

It's what created the profiles table you saw in "What's included": Row Level Security enabled, plus policies so each user can only read/update their own row.

supabase/migrations/20260830005405_init.sql
create table public.profiles (
id uuid primary key references auth.users(id) on delete cascade,
display_name text
);
alter table public.profiles enable row level security;
create policy "Users can view their own profile"
on public.profiles for select
using (auth.uid() = id);
create policy "Users can update their own profile"
on public.profiles for update
using (auth.uid() = id);
10

It goes live the first time the workflow runs

The GitHub Action above applies every file in supabase/migrations/ with supabase db push whenever main gets a commit touching that folder. This one was already committed before you added the secrets, so:

  • Re-run the workflow now from your repo's Actions tab, or
  • Just wait โ€” your next real migration will bring this one along too, since db push applies everything not yet applied, not just what changed
GitHub docs: re-running a workflow
11

Adding your own migration later looks like this

Example: your next migration
npx supabase migration new add_posts_table
npx supabase db reset
git add supabase/migrations
git commit -m "Add posts table"
git push

Deploy to Vercel

12

Import the repo

vercel.com/new
13

Add environment variables

  • NEXT_PUBLIC_SUPABASE_URL โ€” your hosted project's API URL
  • NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY โ€” the public key from Project Settings โ†’ API (safe to expose client-side โ€” it's not a secret)
  • NEXT_PUBLIC_SITE_URL โ€” your production domain, used to build the confirmation email link. You won't know this until after the first deploy โ€” add it and redeploy once you do
Vercel Env Vars
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
NEXT_PUBLIC_SITE_URL
14

Add your deployed URL to Supabase

Authentication โ†’ URL Configuration โ†’ Redirect URLs โ€” otherwise the confirmation email link gets rejected.

15

Configure a real SMTP provider before you launch

Supabase's built-in mailer works out of the box, but it's rate-limited project-wide โ€” a couple of emails per hour, not per user. Fine for testing, too low for real signups.

Fix โ€” you're still using Supabase Auth, just supplying your own outbound email server:

  • Authentication โ†’ Emails โ†’ SMTP Settings โ€” point it at your own provider (Resend, SendGrid, Postmark all have free tiers)
  • Authentication โ†’ Rate Limits โ€” raise the limit yourself once you're on your own SMTP
Supabase SMTP docs