Frameworks

Next.js

HostBase in a Next.js (App Router) app with server-side sessions.

The recommended approach for the App Router is the @supabase/ssr package, which keeps the session in cookies and works in Server Components, Route Handlers and Server Actions.

Install

npm install @supabase/supabase-js @supabase/ssr

Environment variables

# .env.local
NEXT_PUBLIC_SUPABASE_URL=https://abcdefghijklmnopqrst.host.ulewicz.space
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

You can keep the same variable names as with Supabase — migrating then only means swapping the values.

Browser client

// lib/supabase/client.ts
import { createBrowserClient } from "@supabase/ssr";

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  );
}

Server client

// lib/supabase/server.ts
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";

export async function createClient() {
  const cookieStore = await cookies();
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll: () => cookieStore.getAll(),
        setAll: (list) => {
          try {
            list.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            );
          } catch {
            // called from a Server Component — the proxy refreshes the session
          }
        },
      },
    }
  );
}

Fetching data in a Server Component

// app/todos/page.tsx
import { createClient } from "@/lib/supabase/server";

export default async function TodosPage() {
  const supabase = await createClient();
  const { data: todos } = await supabase.from("todos").select("id, task, done");
  return (
    <ul>
      {todos?.map((t) => <li key={t.id}>{t.task}</li>)}
    </ul>
  );
}

Refreshing the session

In Next.js 16 middleware is called proxy.ts. Create it in the project root (or src/) and call supabase.auth.getUser() in it to refresh the token on every request — exactly as in Supabase's official @supabase/ssr guide.