Files
supabase/examples/user-management/nextjs-user-management/README.md
Chris Chinchilla 8b01d388b9 docs: Remove leftover auth-ui components (#45931)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated authentication guide for Kotlin Compose Multiplatform with
revised dependency configuration.
* Enhanced user-management example README with improved project
structure, deployment steps, and resources.

* **Chores**
* Refactored example applications to use custom authentication forms
instead of pre-built Auth UI components.
* Removed unused authentication UI dependencies from multiple example
projects.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45931)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cemal Kılıç <cemalkilic@users.noreply.github.com>
2026-05-14 15:42:09 +00:00

9.7 KiB

Supabase Next.js Auth & User Management Starter

This example sets you up for a very common situation: users can sign up or sign in and then update their account with public profile information, including a profile image.

This demonstrates how to use:

Technologies used

Project structure

  • app/login/ — login and signup form. The form posts to Server Actions in app/login/actions.ts that call supabase.auth.signInWithPassword() and supabase.auth.signUp().
  • app/account/ — protected profile page. Uses a Supabase server client to check the session and renders an account form with avatar upload.
  • app/auth/confirm/route.ts — handles the email confirmation callback by verifying the OTP token and redirecting.
  • app/auth/signout/route.ts — server route that signs the user out.
  • lib/supabase/client.ts — browser client (createBrowserClient).
  • lib/supabase/server.ts — server client (createServerClient) wired up to Next.js cookies.
  • supabase/migrations/ — database schema for the profiles table, RLS policies, the handle_new_user trigger, and the avatars storage bucket.
  • supabase/config.toml — local Supabase configuration used by npx supabase start.

Instant deploy

The Vercel deployment will guide you through creating a Supabase account and project. After installation of the Supabase integration, all relevant environment variables will be set up so that the project is usable immediately after deployment 🚀.

Deploy with Vercel

Run locally

1. Install dependencies

Requires Node.js 20+ and npx (bundled with npm).

npm install

2. Start a local Supabase stack

The example includes a supabase/ directory with the schema and config needed to run a local stack via the Supabase CLI.

npx supabase start

This boots Postgres, Auth, Storage, and Supabase Studio locally and runs the migrations in supabase/migrations/. When it finishes, it prints your local API URL and keys.

3. Configure environment variables

Copy the development env template:

cp .env.example .env.local

The defaults in .env.example already match the local stack (API URL http://127.0.0.1:54321 and the demo publishable key). Update them if your local ports differ.

4. Start the dev server

npm run dev

Open http://localhost:3000 to use the app.

Using a remote Supabase project

1. Create a project

Sign up at https://supabase.com/dashboard and create a new project. Wait for your database to start.

2. Get the URL and publishable key

Go to the Project Settings (the cog icon), open the API tab, and find your Project URL and publishable key.

The publishable key is your client-side API key. It allows "anonymous access" to your database until the user logs in. Once they log in, the user's own JWT is used, which enables Row Level Security to scope data per user. Read more below.

Note: The secret (service role) key has full access to your data and bypasses all security policies. Keep it in server environments only — never expose it to the client or browser.

Copy the production env template and fill it in with your project URL, publishable key, and the URL(s) you want to allow as redirect targets:

cp .env.production.example .env.production

Link your local checkout to the remote project:

SUPABASE_ENV=production npx supabase@latest link --project-ref <your-project-ref>

Push the supabase/config.toml settings (Auth site URL, redirect URLs, etc.):

SUPABASE_ENV=production npx supabase@latest config push

Push the database schema in supabase/migrations/:

SUPABASE_ENV=production npx supabase@latest db push

Vercel Preview with Branching

Supabase integrates seamlessly with Vercel's preview branches, giving each branch a dedicated Supabase project. This setup allows testing database migrations or service configurations safely before applying them to production.

Steps

  1. Ensure the Vercel project is linked to a Git repository.

  2. Configure the "Preview" environment variables in Vercel:

    • NEXT_PUBLIC_SUPABASE_URL
    • NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
  3. Create a new branch, make changes (e.g., update max_frequency), and push the branch to Git.

    • Open a pull request to trigger the Vercel + Supabase integration.
    • Upon successful deployment, the preview environment reflects the changes.

Preview Checks

Postgres Row Level Security

This project uses high-level authorization via Postgres' Row Level Security. When you start a Postgres database on Supabase, we populate it with an auth schema and some helper functions. When a user logs in, they are issued a JWT with the role authenticated and their UUID. We can use these details to provide fine-grained control over what each user can and cannot do.

The schema and policies that this example uses (see supabase/migrations/20221017024722_init.sql):

-- Create a table for public profiles
create table profiles (
  id uuid references auth.users not null primary key,
  updated_at timestamp with time zone,
  username text unique,
  full_name text,
  avatar_url text,
  website text,

  constraint username_length check (char_length(username) >= 3)
);
-- Set up Row Level Security (RLS)
-- See https://supabase.com/docs/guides/auth/row-level-security for more details.
alter table profiles
  enable row level security;

create policy "Public profiles are viewable by everyone." on profiles
  for select using (true);

create policy "Users can insert their own profile." on profiles
  for insert with check ((select auth.uid()) = id);

create policy "Users can update own profile." on profiles
  for update using ((select auth.uid()) = id);

-- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth.
-- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details.
create function public.handle_new_user()
returns trigger as $$
begin
  insert into public.profiles (id, full_name, avatar_url)
  values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url');
  return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
  after insert on auth.users
  for each row execute procedure public.handle_new_user();

-- Set up Storage!
insert into storage.buckets (id, name)
  values ('avatars', 'avatars');

-- Set up access controls for storage.
-- See https://supabase.com/docs/guides/storage#policy-examples for more details.
create policy "Avatar images are publicly accessible." on storage.objects
  for select using (bucket_id = 'avatars');

create policy "Anyone can upload an avatar." on storage.objects
  for insert with check (bucket_id = 'avatars');

create policy "Anyone can update their own avatar." on storage.objects
  for update using ( auth.uid() = owner ) with check (bucket_id = 'avatars');

More Supabase examples & resources

Examples

These official examples are maintained by the Supabase team:

Other resources

Authors

Supabase is open source. We'd love for you to follow along and get involved at https://github.com/supabase/supabase