Pular para o conteúdo
▲ QUICKSTART

Next.js 15 + SuperDB Auth.

SSR com cookies httpOnly, middleware de proteção de rotas e session segura — tudo em 5 minutos.

Por que Next.js é diferente dos outros frameworks

Next.js 15 usa SSR (Server-Side Rendering), o que significa que o servidor renderiza as páginas antes de enviar ao browser. Por isso a session deve viver em cookies httpOnly — não em localStorage.

O fluxo completo é:

  1. Browser faz login → server recebe o JWT e grava em cookie httpOnly seguro
  2. Nas próximas requisições, o middleware lê o cookie e injeta o usuário no contexto
  3. Server components acessam o usuário via auth.getUser() sem nenhuma chamada extra do browser
💡

Prefere uma SPA sem SSR? Use o Quickstart React + Vite — session em localStorage, sem middleware.

Passo a passo

1Criar o app Next.js

Crie um novo app Next.js 15 com TypeScript e App Router. Se preferir partir do template oficial do SuperDB (com auth já configurado), use a segunda opção.

terminal
# App novo zerado
npx create-next-app meu-app \
  --typescript --app --eslint --tailwind
cd meu-app

# OU — template SuperDB (auth + middleware já configurados)
npx create-next-app meu-app --example \
  https://github.com/superdb/superdb/tree/main/templates/quickstart-nextjs
cd meu-app

2Instalar o SDK

Instale o @superdb/auth-js. Para Next.js, o pacote expõe utilitários específicos em @superdb/auth-js/nextjs para criação de cliente SSR e middleware.

terminal
npm install @superdb/auth-js
# ou: bun add @superdb/auth-js

3Configurar variáveis de ambiente

Crie o arquivo .env.local na raiz do projeto. Copie as credenciais do seu projeto em app.superdb.com.br → API Keys.

⚠️

SUPERDB_SERVICE_KEY nunca recebe prefixo NEXT_PUBLIC_. Ela só deve existir no servidor.

.env.local
NEXT_PUBLIC_SUPERDB_URL=https://auth.superdb.com.br
NEXT_PUBLIC_SUPERDB_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiJ9.XXXXX
SUPERDB_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIn0.XXXXX

4Criar o cliente

Para Next.js, use createBrowserClient nos componentes client-side. Ele gerencia cookies automaticamente via next/headers.

Este cliente é singleton — crie uma vez e importe onde precisar.

lib/superdb.ts
import { createBrowserClient } from '@superdb/auth-js/nextjs'

export const superdb = createBrowserClient(
  process.env.NEXT_PUBLIC_SUPERDB_URL!,
  process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!
)
lib/superdb-server.ts (server components)
import { createServerClient } from '@superdb/auth-js/nextjs'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPERDB_URL!,
    process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!,
    { cookies: { getAll: () => cookieStore.getAll() } }
  )
}

5Middleware de proteção de rotas

O middleware intercepta todas as requisições. Aqui validamos o cookie de sessão e redirecionamos usuários não autenticados que tentam acessar /dashboard/*.

Crie o arquivo middleware.ts na raiz do projeto (ao lado de app/).

middleware.ts
import { createMiddlewareClient } from '@superdb/auth-js/nextjs'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  const { auth, response } = await createMiddlewareClient(request)
  const { data: { user } } = await auth.getUser()

  if (!user && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return response
}

export const config = {
  matcher: ['/dashboard/:path*', '/api/protected/:path*']
}

6Signup e login

Crie os formulários de signup e login como Client Components (com 'use client'). Use o cliente do browser criado no passo 4.

Após o login bem-sucedido, o SDK grava o JWT em cookie httpOnly automaticamente — sem localStorage.

app/signup/page.tsx
'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
import { superdb } from '@/lib/superdb'

export default function SignupPage() {
  const router = useRouter()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [error, setError] = useState<string | null>(null)

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    const { error } = await superdb.auth.signUp({ email, password })
    if (error) { setError(error.message); return }
    router.push('/dashboard')
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={e => setEmail(e.target.value)}
        placeholder="Email" required />
      <input type="password" value={password} onChange={e => setPassword(e.target.value)}
        placeholder="Senha (mín. 6 chars)" required />
      {error && <p style={{color:'red'}}>{error}</p>}
      <button type="submit">Criar conta</button>
    </form>
  )
}

7Página protegida (Server Component)

O dashboard lê o usuário diretamente no servidor — sem useEffect, sem loading state no client. O middleware já garante que só usuários autenticados chegam aqui.

Para buscar dados do banco, use fetch direto contra api.superdb.com.br. O cliente @superdb/auth-js é apenas auth — sem .from().

⚠️

Dados via HTTP direto. O endpoint PostgREST do SuperDB é https://api.superdb.com.br/<tabela> — sem prefixo /rest/v1/. Alternativamente, use @supabase/supabase-js com a URL base api.superdb.com.br.

app/dashboard/page.tsx
import { createClient } from '@/lib/superdb-server'
import { redirect } from 'next/navigation'

const ANON_KEY = process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!

export default async function DashboardPage() {
  const superdb = await createClient()
  const { data: { user } } = await superdb.auth.getUser()

  if (!user) redirect('/login')

  // Dados via fetch direto — api.superdb.com.br (sem /rest/v1/)
  const res = await fetch(
    'https://api.superdb.com.br/posts?select=id,title,created_at&order=created_at.desc&limit=10',
    { headers: { 'Authorization': `Bearer ${ANON_KEY}`, 'apikey': ANON_KEY } }
  )
  const posts = await res.json()

  return (
    <main>
      <h1>Olá, {user.email}</h1>
      <ul>
        {posts?.map((p: any) => <li key={p.id}>{p.title}</li>)}
      </ul>
    </main>
  )
}

8Rodar o dev server

Tudo configurado. Inicie o servidor de desenvolvimento e acesse http://localhost:3000.

terminal
npm run dev

# → http://localhost:3000/signup  (criar conta)
# → http://localhost:3000/login   (entrar)
# → http://localhost:3000/dashboard (protegida)

Próximos passos

Essa página ajudou?