Browse documentation

@motherbase/ssr wraps @motherbase/client with the cookie plumbing needed by Next.js. Its root barrel, packages/ssr/src/index.ts, exports createBrowserClient, createServerClient, and updateSession, plus selected client types.

Exported API

ExportSignatureIntended runtime
createBrowserClient(url, key?, options?) => MotherbaseClientClient Components and browser modules
createServerClient(url, key, { cookies, ...clientOptions }) => MotherbaseClientServer Components, Route Handlers, and Server Actions
updateSession(request, url, key?, { fetch? }?) => Promise<NextResponse>Next.js middleware

The barrel also re-exports the MotherbaseClient, Session, User, ClientOptions, CookieMethods, CookieToSet, and CookieOptions types from @motherbase/client.

Browser client

createBrowserClient calls the base createClient and defaults storage to cookieStorage(). Passing a custom ClientOptions.storage overrides that default. Source: packages/ssr/src/browser.ts.

'use client'
 
import { createBrowserClient } from '@motherbase/ssr'
 
export const motherbase = createBrowserClient(
  process.env.NEXT_PUBLIC_MOTHERBASE_URL!,
  process.env.NEXT_PUBLIC_MOTHERBASE_ANON_KEY,
)

The default browser cookie is readable by JavaScript so the server can receive the serialized session on the next request. Its client defaults come from packages/client/src/cookie.ts: name motherbase.session, path /, SameSite=lax, and Secure enabled.

Warning

The default cookie is not HttpOnly because browser auth code must update it. Treat the serialized bearer session as sensitive and keep the application protected against script injection.

Server client

createServerClient removes storage from the accepted options and always installs serverCookieStorage(cookies). All other ClientOptions, including fetch, headers, autoRefresh, and realtimeIoFactory, are forwarded. Source: packages/ssr/src/server.ts.

A reusable Next.js helper:

import { cookies } from 'next/headers'
import { createServerClient } from '@motherbase/ssr'
import type { CookieToSet } from '@motherbase/ssr'
 
export async function createMotherbaseServerClient() {
  const cookieStore = await cookies()
 
  return createServerClient(
    process.env.NEXT_PUBLIC_MOTHERBASE_URL!,
    process.env.NEXT_PUBLIC_MOTHERBASE_ANON_KEY,
    {
      cookies: {
        getAll: () => cookieStore.getAll(),
        setAll: (cookiesToSet: CookieToSet[]) => {
          try {
            for (const { name, value, options } of cookiesToSet) {
              cookieStore.set(name, value, options)
            }
          } catch {
            // Server Components cannot write cookies.
            // Middleware refreshes the session cookie instead.
          }
        },
      },
    },
  )
}

Use it in a Server Component:

import { createMotherbaseServerClient } from '@/lib/motherbase/server'
 
export default async function ProductsPage() {
  const client = await createMotherbaseServerClient()
  const { data: products, error } = await client
    .from<{ id: string; name: string }>('products')
    .select('id,name')
 
  if (error) return <p>{error.message}</p>
 
  return <pre>{JSON.stringify(products, null, 2)}</pre>
}

serverCookieStorage reads all cookies, selects motherbase.session, decodes its JSON, and returns null for missing or malformed data. Writes are batched through setAll; signing out writes an empty cookie with maxAge: 0. Source: packages/client/src/cookie.ts.

Note

A Server Component can read cookies but cannot persist a refreshed or cleared session. The wrapper deliberately allows setAll to be guarded with try/catch; updateSession owns the response-cookie write during navigation.

Middleware refresh

updateSession in packages/ssr/src/middleware.ts creates a server client from NextRequest.cookies, calls client.auth.refreshSession(), and returns a NextResponse.

import type { NextRequest } from 'next/server'
import { updateSession } from '@motherbase/ssr'
 
export function middleware(request: NextRequest) {
  return updateSession(
    request,
    process.env.NEXT_PUBLIC_MOTHERBASE_URL!,
    process.env.NEXT_PUBLIC_MOTHERBASE_ANON_KEY,
  )
}

When the client writes cookies, the helper:

  1. updates request.cookies;
  2. recreates NextResponse.next({ request }) so downstream code sees the new request cookie;
  3. writes the same cookies and their options onto the response.

refreshSession() revalidates the existing Better Auth bearer session. A valid session refreshes the stored user and emits TOKEN_REFRESHED. An invalid session clears the cookie. A network failure is caught and navigation continues with the existing session.

Warning

Return the NextResponse produced by updateSession. Replacing it with a new response drops the refreshed or cleared Set-Cookie values.

Framework adapter contract

The package has no hard dependency on next/headers. Framework integration is expressed through CookieMethods:

interface CookieMethods {
  getAll(): { name: string; value: string }[]
  setAll(cookies: CookieToSet[]): void
}

That makes createServerClient usable anywhere a framework can provide batch cookie reads and writes. Only updateSession imports NextRequest and NextResponse directly. The Next.js peer range is >=14 in packages/ssr/package.json.