Files
Nik RichersandNik Richers c7c6cca9ed chore(docs): align Next.js quickstart demo with monorepo catalog (#47144)
## I have read the CONTRIBUTING.md file.
YES

## What kind of change does this PR introduce?
Docs update, example maintenance

Closes DOCS-362.

## What is the current behavior?
- Linear item: Next JS checks (DOCS-362)
- `@supabase/ssr: "latest"` and unpinned `next` in
nextjs-user-management
- Duplicate `next.config.js` + `next.config.ts`
- Auth quickstart linked to non-existent
`/guides/auth/server-side/nextjs`

## What is the new behavior?
- Pinned `next@16.2.6`, `@supabase/ssr@0.10.2` per monorepo catalog
- Removed duplicate `next.config.js`
- Auth quickstart links to `creating-a-client?framework=nextjs`
- Audit skills moved to
[supabase/docs-agent-skills](https://github.com/supabase/docs-agent-skills):
[`audit-nextjs-docs`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/audit-nextjs-docs/SKILL.md),
[`audit-quickstarts`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/audit-quickstarts/SKILL.md)

## Additional context
- Verification (author): `npm install && npm run build` in
nextjs-user-management — **pass** (Next.js 16.2.6)
- Skill audit: no stale `middleware.ts` in Next docs paths; broken link
fixed; duplicate config removed

| Check | Result |
|-------|--------|
| Version matrix | Pass (pinned to catalog) |
| proxy.ts / no middleware refs | Pass |
| nextjs-user-management build | Pass |
| Auth quickstart link | Fixed |

### Test plan
- [ ] `cd examples/user-management/nextjs-user-management && npm install
&& npm run build`
- [ ] `cd apps/docs && pnpm codegen:examples && pnpm lint:mdx` on
changed MDX
- [ ] Framework quickstart — `create-next-app -e with-supabase` and
publishable key env vars
- [ ] Auth quickstart — "Learn more" resolves (no 404)
- [ ] Web app tutorial — code samples use `proxy.ts`
- [ ] Start nextjs-user-management locally with `.env.local` —
login/account flow
- [ ] Install audit skills from
[docs-agent-skills](https://github.com/supabase/docs-agent-skills) (`ln
-sf ~/GitHub/supabase/docs-agent-skills/.claude/skills/audit-nextjs-docs
~/.claude/skills/audit-nextjs-docs` and same for `audit-quickstarts`),
then run checklists in
[audit-nextjs-docs](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/audit-nextjs-docs/SKILL.md)
and
[audit-quickstarts](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/audit-quickstarts/SKILL.md)

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

## Summary by CodeRabbit

* **Documentation**
* Updated resource links in authentication quickstart guides for
improved navigation.

* **Chores**
* Updated dependencies in the Next.js user management example to latest
stable versions.
  * Removed unused configuration settings from the example application.

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

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
2026-06-26 07:34:45 -07:00
..

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. Allows downloading object with public key
-- See https://supabase.com/docs/guides/storage/security/access-control#policy-examples for more details.
create policy "Avatar images are publicly accessible." on storage.objects
  for select using (bucket_id = 'avatars' and storage.allow_any_operation(array['object.get_authenticated_info', 'object.get_authenticated']));

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