From dac575629518b89d169531b659bbfd72cd642f78 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Thu, 16 Jul 2026 15:29:00 +0300 Subject: [PATCH] docs(auth): add server-side package disambiguation guide (#47966) Adds a docs guide, "Choosing a server-side package", that explains when to use `supabase-js`, `@supabase/ssr`, or `@supabase/server` when working with Supabase from JavaScript on the server. It includes a decision table and a short code example for each, with one rule up front: cookie-based sessions in SSR frameworks use `@supabase/ssr`, per-request header auth in Edge Functions and other backend runtimes uses `@supabase/server`, and `supabase-js` is the base client both wrap. The guide is surfaced from the Auth overview page and the sidebar, and is cross-linked from the `supabase-js` and `@supabase/server` reference introductions so it is reachable from where developers start. It also states that the packages coexist and are not replacements for each other, and keeps combining `@supabase/server` with `@supabase/ssr` as an advanced section. ## Summary by CodeRabbit - **New Features** - Added a guide explaining how to choose between Supabase server-side JavaScript packages. - Added the guide to Auth navigation and the getting-started content listings. - Added links to the new guidance throughout relevant JavaScript and server documentation. - **Documentation** - Clarified when to use cookie-based sessions versus header-based authentication. - Added package comparisons, usage examples, advanced guidance, and related next steps. - Updated spelling support for framework names used in the documentation. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../NavigationMenu.constants.ts | 4 + .../guides/auth/choosing-a-server-package.mdx | 95 +++++++++++++++++++ apps/docs/data/content-listings/auth.data.ts | 5 + .../docs/docs/ref/javascript/introduction.mdx | 2 + apps/docs/docs/ref/server/introduction.mdx | 2 + .../javascript/v2/partials/introduction.mdx | 2 + .../server/v1/partials/introduction.mdx | 6 ++ supa-mdx-lint/Rule003Spelling.toml | 2 + 8 files changed, 118 insertions(+) create mode 100644 apps/docs/content/guides/auth/choosing-a-server-package.mdx diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index dbcfb17e112..ccbb06a95dd 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -740,6 +740,10 @@ export const auth: NavMenuConstant = { name: 'Flows (How-tos)', enabled: authFlowsEnabled, items: [ + { + name: 'Which package to use', + url: '/guides/auth/choosing-a-server-package', + }, { name: 'Server-Side Rendering', url: '/guides/auth/server-side', diff --git a/apps/docs/content/guides/auth/choosing-a-server-package.mdx b/apps/docs/content/guides/auth/choosing-a-server-package.mdx new file mode 100644 index 00000000000..199d6357eb2 --- /dev/null +++ b/apps/docs/content/guides/auth/choosing-a-server-package.mdx @@ -0,0 +1,95 @@ +--- +title: 'Which package to use' +subtitle: 'When to use supabase-js, @supabase/ssr, or @supabase/server on the server.' +--- + +When you use Supabase from JavaScript on the server, there are three packages to choose from. They are not alternatives to each other — `@supabase/ssr` and `@supabase/server` both build on top of `supabase-js` and solve different problems. This guide helps you pick the right one. + + + +These are JavaScript packages, not separate language SDKs. If you're looking for the client library for another language (Python, Swift, Kotlin, etc.), see the [client library references](/docs/reference). + + + +## Which package to use + +The quickest way to decide is by **how the user's identity reaches your code**: + +- The session lives in **cookies** (an SSR framework like Next.js or SvelteKit) → use **`@supabase/ssr`**. +- Auth arrives **per request in headers** (`Authorization: Bearer `) → use **`@supabase/server`**. +- You want the base client, or you're handling auth yourself → use **`@supabase/supabase-js`** directly. + +| Package | Use it when | Runs in | Auth model | +| ----------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------- | +| `@supabase/supabase-js` | You want the base client, or you manage auth yourself | Browser and server | You wire up auth | +| `@supabase/ssr` | User sessions are stored in **cookies** | SSR frameworks (Next.js, SvelteKit, TanStack Start) | Cookie-based sessions, with refresh-token rotation | +| `@supabase/server` | Auth arrives **per request in headers** | Edge Functions, Workers, Vercel, Bun, and framework APIs (Hono, H3, Elysia, NestJS) | Stateless Bearer JWT + `apikey` | + +## `@supabase/supabase-js` + +The isomorphic base client. `@supabase/ssr` and `@supabase/server` both wrap it — reach for `supabase-js` directly when you don't need either wrapper's auth handling. + +```ts +import { createClient } from '@supabase/supabase-js' + +const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_PUBLISHABLE_KEY!) +``` + +## `@supabase/ssr` + +For SSR frameworks that store the user's session in cookies. It reads and writes session cookies and handles refresh-token rotation, so the same user and session are available on both the client and the server. + +```ts +import { createServerClient } from '@supabase/ssr' + +const supabase = createServerClient( + process.env.SUPABASE_URL!, + process.env.SUPABASE_PUBLISHABLE_KEY!, + { + cookies: { + getAll() { + // return the request's cookies + }, + setAll(cookiesToSet) { + // write cookies back on the response + }, + }, + } +) +``` + +See the [server-side rendering guide](/guides/auth/server-side) for framework-specific setup. + +## `@supabase/server` + +For stateless, header-based auth in backend runtimes — Edge Functions, Workers, and framework APIs. You declare who may call an endpoint and receive a ready-to-use context (a caller-scoped client that respects RLS, plus an admin client). It verifies JWTs and resolves the new API keys (`SUPABASE_PUBLISHABLE_KEYS` / `SUPABASE_SECRET_KEYS`) for you. + +```ts +import { withSupabase } from '@supabase/server' + +export default { + fetch: withSupabase({ auth: 'user' }, async (req, ctx) => { + // ctx.supabase is scoped to the caller and respects RLS + const { data } = await ctx.supabase.from('todos').select() + return Response.json(data) + }), +} +``` + +See the [`@supabase/server` reference](/docs/reference/server) for the full API. + + + +`@supabase/ssr` and `@supabase/server` coexist and are not replacements for each other, and `@supabase/ssr` is not deprecated. Pick based on where your code runs and how auth reaches it, using the table above. + + + +## Advanced: Combining `@supabase/server` and `@supabase/ssr` + +In a cookie-based framework you can compose the two — let `@supabase/ssr` own the cookie session lifecycle and hand the resolved token to `@supabase/server`'s primitives. This requires more setup, and deeper first-party integration is on the roadmap. See the [`@supabase/server` SSR frameworks guide](https://github.com/supabase/server/blob/main/docs/ssr-frameworks.md). + +## Next steps + +- [Server-side rendering](/guides/auth/server-side) — set up `@supabase/ssr` for your framework. +- [`@supabase/server` reference](/docs/reference/server) — API for header-based server auth. +- [`supabase-js` reference](/docs/reference/javascript) — the base JavaScript client. diff --git a/apps/docs/data/content-listings/auth.data.ts b/apps/docs/data/content-listings/auth.data.ts index e70d1cd5836..1374ac25b32 100644 --- a/apps/docs/data/content-listings/auth.data.ts +++ b/apps/docs/data/content-listings/auth.data.ts @@ -16,6 +16,11 @@ export const authGetStarted: ContentListingGroup = { href: '/guides/auth/server-side', description: 'Create a Supabase client for SSR frameworks like Next.js and SvelteKit.', }, + { + title: 'Which package to use', + href: '/guides/auth/choosing-a-server-package', + description: 'supabase-js vs @supabase/ssr vs @supabase/server — which to use on the server.', + }, { title: 'Row Level Security', href: '/guides/database/postgres/row-level-security', diff --git a/apps/docs/docs/ref/javascript/introduction.mdx b/apps/docs/docs/ref/javascript/introduction.mdx index 38419887755..b0ed783aa6a 100644 --- a/apps/docs/docs/ref/javascript/introduction.mdx +++ b/apps/docs/docs/ref/javascript/introduction.mdx @@ -7,3 +7,5 @@ hideTitle: true This reference documents every object and method available in Supabase's isomorphic JavaScript library, `supabase-js`. You can use `supabase-js` to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files. To convert SQL queries to `supabase-js` calls, use the [SQL to REST API translator](/docs/guides/api/sql-to-rest). + +Using `supabase-js` on the server? See [which package to use](/docs/guides/auth/choosing-a-server-package) to decide between `supabase-js`, `@supabase/ssr`, and `@supabase/server`. diff --git a/apps/docs/docs/ref/server/introduction.mdx b/apps/docs/docs/ref/server/introduction.mdx index eaacb0c51dd..5c9e884b186 100644 --- a/apps/docs/docs/ref/server/introduction.mdx +++ b/apps/docs/docs/ref/server/introduction.mdx @@ -6,3 +6,5 @@ title: Introduction `@supabase/server` is a framework-agnostic library for authenticating requests in server-side JavaScript environments. It verifies JWTs, resolves Supabase API keys, and creates pre-configured Supabase clients — exposing everything through a single `SupabaseContext` that is identical regardless of which adapter or primitive produced it. Adapters for Hono, H3, Elysia, and NestJS are included. You can also compose the lower-level primitives directly for custom frameworks or edge runtimes. + +Not sure this is the right package? See [which package to use](/docs/guides/auth/choosing-a-server-package) — for cookie-based sessions in SSR frameworks, use [`@supabase/ssr`](/docs/guides/auth/server-side) instead. diff --git a/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx b/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx index ff2524c82f9..2de91f081eb 100644 --- a/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx +++ b/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx @@ -6,3 +6,5 @@ title: Introduction This reference documents every object and method available in Supabase's isomorphic JavaScript library, `supabase-js`. You can use `supabase-js` to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files. To convert SQL queries to `supabase-js` calls, use the [SQL to REST API translator](/docs/guides/api/sql-to-rest). + +Using `supabase-js` on the server? See [which package to use](/docs/guides/auth/choosing-a-server-package) to decide between `supabase-js`, `@supabase/ssr`, and `@supabase/server`. diff --git a/apps/docs/spec/reference/server/v1/partials/introduction.mdx b/apps/docs/spec/reference/server/v1/partials/introduction.mdx index eaacb0c51dd..146ee752b22 100644 --- a/apps/docs/spec/reference/server/v1/partials/introduction.mdx +++ b/apps/docs/spec/reference/server/v1/partials/introduction.mdx @@ -6,3 +6,9 @@ title: Introduction `@supabase/server` is a framework-agnostic library for authenticating requests in server-side JavaScript environments. It verifies JWTs, resolves Supabase API keys, and creates pre-configured Supabase clients — exposing everything through a single `SupabaseContext` that is identical regardless of which adapter or primitive produced it. Adapters for Hono, H3, Elysia, and NestJS are included. You can also compose the lower-level primitives directly for custom frameworks or edge runtimes. + + + +See [which package to use](/docs/guides/auth/choosing-a-server-package) — for cookie-based sessions in SSR frameworks, use [`@supabase/ssr`](/docs/guides/auth/server-side) instead. + + diff --git a/supa-mdx-lint/Rule003Spelling.toml b/supa-mdx-lint/Rule003Spelling.toml index 6161711d68d..5ff03ca7c62 100644 --- a/supa-mdx-lint/Rule003Spelling.toml +++ b/supa-mdx-lint/Rule003Spelling.toml @@ -223,6 +223,7 @@ allow_list = [ "dotenvx", "Drizzle", "ElevenLabs", + "Elysia", "[Ee]nablement", "EnterpriseDB", "Entra", @@ -306,6 +307,7 @@ allow_list = [ "MySQL", "[Nn]amespaces?", "[Nn]ano", + "NestJS", "Netlify", "Next.js", "[Nn]ginx",