# @supabase/ssr

> Use the Supabase JavaScript library in popular server-side rendering (SSR) frameworks.

Latest version **0.12.7** (published 2026-09-08) · MIT license · 0 weekly downloads

## Install

```sh
npm install @supabase/ssr
pnpm add @supabase/ssr
yarn add @supabase/ssr
bun add @supabase/ssr
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.12.7 |
| Published | 2026-09-08 |
| First published | 2023-09-06 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 324.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 207 |
| Author | Supabase, Inc. |
| Keywords | Supabase, SSR, Server-Side, Rendering, Next, Next.js, NextJS, Remix, Svelte, SvelteKit, Postgres |

## Links

- npm: https://www.npmjs.com/package/@supabase/ssr
- Repository: https://github.com/supabase/ssr
- Homepage: https://github.com/supabase/ssr#readme
- Issues: https://github.com/supabase/ssr/issues
- npm.io page: https://npm.io/package/@supabase/ssr

## Dependencies (1)

- [cookie](https://npm.io/package/cookie.md) ^1.0.2

## Alternatives

- [@sindresorhus/slugify](https://npm.io/package/@sindresorhus/slugify.md) — 3.7M weekly downloads
- [solid-js](https://npm.io/package/solid-js.md) — 2.7M weekly downloads
- [expo-glass-effect](https://npm.io/package/expo-glass-effect.md) — 2.5M weekly downloads
- [nanoassert](https://npm.io/package/nanoassert.md) — 780.8K weekly downloads
- [@ffmpeg/ffmpeg](https://npm.io/package/@ffmpeg/ffmpeg.md) — 529.5K weekly downloads

## Recent versions

- 0.12.7 (latest) — 2026-09-08
- 0.12.7-rc.162 (rc) — 2026-09-08
- 0.4.1 (patched) — 2024-07-05
- 0.12.6 — 2026-09-04
- 0.12.6-rc.158 — 2026-09-04
- 0.12.5 — 2026-08-24
- 0.12.5-rc.154 — 2026-08-24
- 0.12.4 — 2026-07-28
- 0.12.4-rc.146 — 2026-07-28
- 0.12.3 — 2026-07-14
- 0.12.3-rc.135 — 2026-07-14
- 0.12.2 — 2026-07-14
- 0.12.2-rc.133 — 2026-07-14
- 0.12.2-rc.132 — 2026-07-13
- 0.12.1 — 2026-07-13
- … 82 more at https://npm.io/package/@supabase/ssr/versions

## README

# Supabase clients for use in SSR frameworks

> **Package Consolidation Notice**: This package replaces the deprecated `@supabase/auth-helpers-*` packages. All framework-specific auth-helpers packages have been consolidated into `@supabase/ssr` for better maintenance and consistency.

## Overview

This package provides a framework-agnostic way to use the [Supabase JavaScript library](https://supabase.com/docs/reference/javascript/introduction) in server-side rendering (SSR) frameworks.

## Installation

```bash
npm i @supabase/ssr
# or
pnpm add @supabase/ssr
# or
yarn add @supabase/ssr
# or
bun add @supabase/ssr
```

## Deprecated Packages

The following packages have been deprecated and consolidated into `@supabase/ssr`:

- `@supabase/auth-helpers-nextjs` → Use `@supabase/ssr`
- `@supabase/auth-helpers-react` → Use `@supabase/ssr`
- `@supabase/auth-helpers-remix` → Use `@supabase/ssr`
- `@supabase/auth-helpers-sveltekit` → Use `@supabase/ssr`

If you're currently using any of these packages, please update your dependencies to use `@supabase/ssr` directly.

## Documentation

Please refer to the [official server-side rendering guides](https://supabase.com/docs/guides/auth/server-side) for the latest best practices on using this package in your SSR framework of choice.

## Known patterns and limitations

For guidance on choosing between `getSession()`, `getUser()`, and `getClaims()`,
see the [official server-side rendering guides](https://supabase.com/docs/guides/auth/server-side).

### The `auth.storage` option is ignored

`createBrowserClient` and `createServerClient` always store the session in
cookies — this is the entire point of the package, since it lets a
server-rendered request read the same session the browser wrote. Passing
`auth.storage` has no effect; a one-time console warning is logged if you do. (`auth.userStorage` is different and is still respected when `cookies.encode` is set to `"tokens-only"`.) If you
don't need server-side access to the session, use `@supabase/supabase-js`'s
`createClient` directly with your own `storage` (e.g. `localStorage`) —
there's no reason to use `@supabase/ssr` in that case.

### Concurrent requests with the same expired session

Supabase refresh tokens are single-use. If two requests arrive simultaneously
with the same expired session cookie (e.g. from two browser tabs opening at
the same time), both will attempt a token refresh. The second request's
refresh will fail because the token was already consumed by the first. The
second request will receive `session: null` until the browser syncs the
updated cookie from the first response.

The **middleware pattern** mitigates this for the common case: middleware runs
once per navigation and refreshes the session before the page renders, so
subsequent requests within the same navigation see a valid token. For parallel
requests (e.g. parallel `fetch()` calls from the client), handle `null`
sessions gracefully and retry or re-authenticate as needed.

### React Router middleware

[React Router middleware](https://reactrouter.com/how-to/middleware) is stable
and is a good place to create a server Supabase client, refresh the session once
per request, and write updated auth cookies back onto the response.

```ts
// app/context.ts
import { createContext } from "react-router";
import type { SupabaseClient } from "@supabase/supabase-js";

export const supabaseContext = createContext<SupabaseClient | null>(null);
```

```ts
// app/middleware/supabase.ts
import {
  createServerClient,
  parseCookieHeader,
  serializeCookieHeader,
} from "@supabase/ssr";
import type { CookieOptions } from "@supabase/ssr";
import type { MiddlewareFunction } from "react-router";
import { supabaseContext } from "~/context";

type PendingCookie = {
  name: string;
  value: string;
  options: CookieOptions;
};

/**
 * Framework-mode server middleware: refresh the session before loaders/actions
 * run, then attach any Set-Cookie / cache headers to the Response.
 */
export const supabaseMiddleware: MiddlewareFunction<Response> = async (
  { request, context },
  next,
) => {
  const pendingCookies: PendingCookie[] = [];
  const pendingHeaders: Record<string, string> = {};

  const supabase = createServerClient(
    process.env.SUPABASE_URL!,
    process.env.SUPABASE_PUBLISHABLE_KEY!,
    {
      cookies: {
        getAll() {
          return parseCookieHeader(request.headers.get("Cookie") ?? "");
        },
        setAll(cookiesToSet, headers) {
          pendingCookies.push(...cookiesToSet);
          Object.assign(pendingHeaders, headers);
        },
      },
    },
  );

  // Trigger lazy session init / refresh before any route code runs.
  await supabase.auth.getClaims();
  context.set(supabaseContext, supabase);

  const response = await next();

  for (const { name, value, options } of pendingCookies) {
    response.headers.append(
      "Set-Cookie",
      serializeCookieHeader(name, value, options),
    );
  }
  for (const [key, value] of Object.entries(pendingHeaders)) {
    response.headers.set(key, value);
  }

  return response;
};
```

Attach it on a parent route (Framework mode) so child loaders can read the client
from context:

```ts
// app/routes/home.tsx
import type { Route } from "./+types/home";
import { supabaseMiddleware } from "~/middleware/supabase";
import { supabaseContext } from "~/context";

export const middleware: Route.MiddlewareFunction[] = [supabaseMiddleware];

export async function loader({ context }: Route.LoaderArgs) {
  const supabase = context.get(supabaseContext);
  const { data } = await supabase!.auth.getClaims();
  return { claims: data?.claims ?? null };
}
```

See also the [React Router creating-a-client examples](https://supabase.com/docs/guides/auth/server-side/creating-a-client)
in the official SSR guides for `loader` / `action` patterns when you are not
using middleware.

---
_Source: https://npm.io/package/@supabase/ssr · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
