Connect
Supabase
Create the project, paste three keys, enable Google and magic links, and add the profiles table the kit already queries.
Launch Kit uses Supabase for auth and Postgres. Sessions are cookies via @supabase/ssr. Middleware refreshes them. You do not replace libs/supabase.
Keys
Create a project at supabase.com. In Project Settings → API:
| Credential | Env var | Used by |
|---|---|---|
| Project URL | NEXT_PUBLIC_SUPABASE_URL | Browser, server, middleware |
anon public key | NEXT_PUBLIC_SUPABASE_ANON_KEY | Same, with the user session |
service_role secret key | SUPABASE_SERVICE_ROLE_KEY | Stripe webhook only. Bypasses RLS |
Auth providers
In Authentication → Providers:
- Enable Email. Magic links use
signInWithOtpfrom/signin. - Enable Google. Add the Google client ID and secret from Google Cloud.
Redirect URL the kit already uses:
http://localhost:3000/api/auth/callbackAdd the production URL when you deploy: https://your-domain.com/api/auth/callback. Also add both origins under Authentication → URL Configuration.
Profiles table
Checkout, the billing portal, and the webhook all read a profiles table. It is not created for you. Run this in the SQL editor:
create table public.profiles (
id uuid primary key references auth.users (id) on delete cascade,
email text,
customer_id text,
price_id text,
has_access boolean not null default false,
created_at timestamptz not null default now()
);
alter table public.profiles enable row level security;
create policy "Users can read 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);
create function public.handle_new_user()
returns trigger
language plpgsql
security definer
set search_path = public
as $$
begin
insert into public.profiles (id, email)
values (new.id, new.email);
return new;
end;
$$;
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();| Column | Who writes it | Why |
|---|---|---|
id | Auth trigger | Matches auth.users.id |
email | Auth trigger | Guest checkout lookup |
customer_id | Stripe webhook | Billing portal and subscription events |
price_id | Stripe webhook | Invoice / plan match |
has_access | Stripe webhook | Paid access flag. Gate your product on this |
The webhook can also create an auth user for guest checkout. The trigger still inserts the profile row.
What the kit already does
- Server:
await createClient()from@/libs/supabase/server - Browser:
createClient()from@/libs/supabase/client /dashboardredirects guests toconfig.auth.loginUrl/api/auth/callbackexchanges the code and sends the user toconfig.auth.callbackUrl
Protect another route by copying app/dashboard/layout.tsx. See Authentication.