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 é:
- Browser faz login → server recebe o JWT e grava em cookie httpOnly seguro
- Nas próximas requisições, o middleware lê o cookie e injeta o usuário no contexto
- 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.
# 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.
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.
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.
import { createBrowserClient } from '@superdb/auth-js/nextjs'
export const superdb = createBrowserClient(
process.env.NEXT_PUBLIC_SUPERDB_URL!,
process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!
)
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/).
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.
'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.
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.
npm run dev
# → http://localhost:3000/signup (criar conta)
# → http://localhost:3000/login (entrar)
# → http://localhost:3000/dashboard (protegida)
Próximos passos
- Adicionar OAuth com Google
- Ativar MFA TOTP
- Configurar Row Level Security
- Referência completa do SDK
- Integrar MCP para IA coding