A Stack Vercel + Next.js + Supabase + Claude API: Sem CMS Necessário
Tradução para Português Brasileiro
Estou construindo sites com plataformas de CMS headless há anos. Contentful, Sanity, Strapi -- você cita, eu integrei. Mas por volta do final de 2025, comecei a notar um padrão: para um número crescente de projetos, eu não estava buscando um CMS. Em vez disso, eu estava lançando aplicações full-stack com Next.js na Vercel, Supabase para dados e autenticação, e a API Claude para qualquer inteligência de conteúdo que eu precisasse. Sem fornecedor de CMS. Sem UI de modelagem de conteúdo. Sem licenças mensais de assentos.
Isso não é sobre ser contrário. Existem absolutamente projetos onde um CMS headless é a escolha certa -- construímos muito disso na Social Animal (confira nosso trabalho de desenvolvimento de CMS headless). Mas há uma classe específica de aplicação onde essa stack sem fornecedor não é apenas viável, é melhor. Deixe-me guiá-lo através de exatamente como funciona, quando usá-lo, e como configurá-lo do zero.
Índice
- Por que os Desenvolvedores Estão Abandonando o CMS
- A Stack em Resumo
- Configurando seu Projeto Next.js na Vercel
- Supabase como seu Backend: Auth, Banco de Dados e Armazenamento
- Integrando a API Claude para Inteligência de Conteúdo
- Construindo uma Interface de Admin Personalizada
- Custos Reais: O que essa Stack Realmente Custa
- Quando você ainda deve usar um CMS
- Checklist de Implantação em Produção
- FAQ
Por que os Desenvolvedores Estão Abandonando o CMS
Vamos ser honestos sobre o que um CMS oferece: uma UI para pessoas não técnicas editarem conteúdo, uma camada de dados estruturada, talvez alguma gerência de mídia, e uma API para buscar tudo. Isso é genuinamente valioso quando você tem um time de marketing publicando posts de blog todos os dias.
Mas aqui está o que continuo vendo em 2026:
- Produtos SaaS onde o "conteúdo" é dados gerados pelo usuário, não cópia editorial
- Ferramentas internas onde o time é técnico o suficiente para editar um banco de dados diretamente ou usar um painel de admin leve
- Aplicações nativas de IA onde o conteúdo é gerado, resumido ou transformado no voo
- Startups que não conseguem justificar $300-500/mês em um CMS quando têm três usuários
Para esses projetos, um CMS é overhead. Você está pagando por recursos de modelagem de conteúdo que não usará, gerenciando chaves de API para um serviço que é basicamente um wrapper de banco de dados sofisticado, e lidando com complexidade de webhook para manter as coisas em sincronização.
A alternativa? Seja proprietário da sua camada de dados completamente. Supabase oferece Postgres (um banco de dados real, não uma loja de conteúdo proprietária), auth, armazenamento de arquivos e assinaturas realtime. Claude cuida da camada de inteligência. Next.js e Vercel cuidam de todo o resto.
A Stack em Resumo
| Camada | Tecnologia | Papel | Preço 2026 (Inicial) |
|---|---|---|---|
| Frontend & API | Next.js 15 (App Router) | UI, Server Components, Route Handlers | Gratuito (open source) |
| Hosting & Edge | Vercel | Implantação, CDN, Serverless Functions | Tier gratuito / $20/mês Pro |
| Banco de Dados & Auth | Supabase | Postgres, Row Level Security, Auth, Storage | Tier gratuito / $25/mês Pro |
| Camada de IA | Claude API (Anthropic) | Geração de conteúdo, resumo, classificação | Pay-per-token (~$3/$15 por 1M tokens para Sonnet 4) |
| Admin UI | Personalizado (React + Supabase) | Gerenciamento de conteúdo para seu time | $0 (você constrói) |
Custo total para uma aplicação em produção com tráfego moderado: $45-100/mês. Compare isso a uma configuração típica de CMS headless onde apenas o CMS pode custar $99-500/mês antes mesmo de você pagar pela hospedagem.
Configurando seu Projeto Next.js na Vercel
Estou assumindo que você tem Node.js 20+ e uma conta Vercel. Se você é novo no Next.js, nosso time tem escrito extensivamente sobre isso em nossa página de capacidade de desenvolvimento Next.js.
npx create-next-app@latest my-app --typescript --tailwind --app --src-dir
cd my-app
Next.js 15 com o App Router é a fundação aqui. Estamos usando Server Components por padrão, o que significa que a maioria do nosso data fetching acontece no servidor -- nenhuma chave de API exposta, nenhum spinner de carregamento client-side para conteúdo inicial.
Aqui está minha estrutura de projeto típica para essa stack:
src/
├── app/
│ ├── (public)/ # Páginas de marketing, blog
│ ├── (dashboard)/ # Área admin autenticada
│ │ ├── layout.tsx # Wrapper de verificação de auth
│ │ ├── posts/
│ │ ├── media/
│ │ └── settings/
│ ├── api/
│ │ ├── ai/ # Rotas da API Claude
│ │ └── webhooks/ # Hooks realtime do Supabase
│ └── layout.tsx
├── lib/
│ ├── supabase/
│ │ ├── client.ts # Client do navegador
│ │ ├── server.ts # Client do servidor
│ │ └── admin.ts # Client do role de serviço
│ ├── claude.ts # Wrapper do SDK Anthropic
│ └── utils.ts
├── components/
└── types/
Variáveis de Ambiente
Você precisará destas no seu .env.local:
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-key
ANTHROPIC_API_KEY=sk-ant-...
Implantando na Vercel
Push para GitHub. Conecte o repo na Vercel. Adicione suas variáveis de env. Pronto. Não vou alongar isso -- a DX do Vercel para implantação Next.js é a melhor da indústria e você provavelmente já sabe como funciona.
Uma coisa que vale a pena notar: use o Edge Config da Vercel se você precisar de feature flags ou configuração que atualize sem redeploy. É uma pequena coisa mas substitui mais uma ferramenta SaaS.
Supabase como seu Backend: Auth, Banco de Dados e Armazenamento
É aqui que a magia acontece. Supabase não é apenas "Firebase mas Postgres" -- é uma plataforma backend completa que você realmente possui. Seus dados vivem em um banco de dados PostgreSQL padrão. Se você quiser sair, você faz pg_dump e sai. Tente fazer isso com um CMS proprietário.
Schema do Banco de Dados
Digamos que você está construindo um aplicativo orientado por conteúdo (o tipo de coisa onde você normalmente buscaria um CMS). Aqui está um schema que trata de artigos, mídia e taxonomia básica:
-- Ativar geração de UUID
create extension if not exists "uuid-ossp";
-- Tabela de conteúdo (substitui seu modelo de conteúdo CMS)
create table public.posts (
id uuid default uuid_generate_v4() primary key,
title text not null,
slug text unique not null,
body text, -- Conteúdo Markdown
excerpt text,
status text default 'draft' check (status in ('draft', 'published', 'archived')),
author_id uuid references auth.users(id),
featured_image text, -- Caminho Supabase Storage
metadata jsonb default '{}', -- Campos flexíveis, sem migração necessária
published_at timestamptz,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
-- Tags / taxonomia
create table public.tags (
id uuid default uuid_generate_v4() primary key,
name text unique not null,
slug text unique not null
);
create table public.post_tags (
post_id uuid references public.posts(id) on delete cascade,
tag_id uuid references public.tags(id) on delete cascade,
primary key (post_id, tag_id)
);
-- Row Level Security
alter table public.posts enable row level security;
-- Qualquer um pode ler posts publicados
create policy "Public can read published posts"
on public.posts for select
using (status = 'published');
-- Usuários autenticados podem gerenciar seus próprios posts
create policy "Authors can manage own posts"
on public.posts for all
using (auth.uid() = author_id);
Essa coluna metadata jsonb é fundamental. Ela oferece a flexibilidade dos campos personalizados de um CMS sem precisar executar migrações toda vez que o time de marketing quer um novo campo. Precisa de uma descrição SEO? metadata->>'seo_description'. Precisa de uma imagem Open Graph substituída? metadata->>'og_image'. É sem schema onde você precisa de flexibilidade, estruturado onde você precisa de integridade.
Configuração de Auth
Supabase Auth cuida de tudo. Email/senha, magic links, OAuth com Google/GitHub -- está tudo integrado.
// 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() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
},
},
}
)
}
Armazenamento de Arquivos
Supabase Storage substitui qualquer biblioteca de mídia que seu CMS tinha. Crie um bucket chamado media, configure uma política, e você tem uma loja de arquivos compatível com S3 com URLs de CDN automático.
// Upload de um arquivo
const { data, error } = await supabase.storage
.from('media')
.upload(`posts/${slug}/${file.name}`, file, {
cacheControl: '3600',
upsert: false,
})
// Obter URL pública
const { data: { publicUrl } } = supabase.storage
.from('media')
.getPublicUrl(`posts/${slug}/${file.name}`)
Integrando a API Claude para Inteligência de Conteúdo
É aqui que a stack de 2026 diverge mais do desenvolvimento web tradicional. A API Claude não é apenas um chatbot -- é uma camada de inteligência que pode substituir categorias inteiras de plugins de CMS e serviços de terceiros.
Aqui está o que estou usando em produção:
- Auto-geração de metadata SEO a partir do conteúdo do post
- Resumo de conteúdo para excerpts e social cards
- Classificação de conteúdo e auto-tagueamento
- Busca inteligente que entende intenção, não apenas palavras-chave
- Assistência de rascunho para autores de conteúdo
Configurando o SDK Anthropic
npm install @anthropic-ai/sdk
// lib/claude.ts
import Anthropic from '@anthropic-ai/sdk'
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY!,
})
export async function generateSEOMetadata(content: string, title: string) {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [
{
role: 'user',
content: `Given this article title and content, generate SEO metadata.
Title: ${title}
Content: ${content.slice(0, 3000)}
Respond with JSON only:
{
"seo_title": "50-60 char title with primary keyword",
"seo_description": "120-160 char meta description",
"excerpt": "1-2 sentence hook for social sharing",
"suggested_tags": ["tag1", "tag2", "tag3"]
}`,
},
],
})
const text = message.content[0].type === 'text' ? message.content[0].text : ''
return JSON.parse(text)
}
export async function classifyContent(content: string, existingTags: string[]) {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 256,
messages: [
{
role: 'user',
content: `Classify this content into the most relevant tags from the existing list. You may suggest up to 2 new tags if nothing fits.
Existing tags: ${existingTags.join(', ')}
Content: ${content.slice(0, 2000)}
Respond with JSON: { "tags": ["tag1", "tag2"], "new_tags": ["maybe-new"] }`,
},
],
})
const text = message.content[0].type === 'text' ? message.content[0].text : ''
return JSON.parse(text)
}
Rota de API para Recursos de IA
// app/api/ai/seo/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { createClient } from '@/lib/supabase/server'
import { generateSEOMetadata } from '@/lib/claude'
export async function POST(request: NextRequest) {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { content, title } = await request.json()
try {
const metadata = await generateSEOMetadata(content, title)
return NextResponse.json(metadata)
} catch (error) {
return NextResponse.json(
{ error: 'AI generation failed' },
{ status: 500 }
)
}
}
O custo aqui é negligenciável. Uma chamada típica de geração de metadata SEO usa talvez 4.000 tokens de entrada e 200 tokens de saída. Com o preço do Claude Sonnet 4 em aproximadamente $3/1M tokens de entrada e $15/1M tokens de saída, isso é cerca de $0,015 por chamada. Você poderia gerar metadata para 1.000 artigos por $15.
Construindo uma Interface de Admin Personalizada
Essa é a parte que deixa as pessoas nervosas. "Se eu não tenho um CMS, como pessoas não técnicas editam conteúdo?"
Você constrói uma UI de admin simples. E em 2026, "simples" é realmente simples. Aqui está um componente básico de editor de posts:
// app/(dashboard)/posts/[id]/editor.tsx
'use client'
import { useState } from 'react'
import { createBrowserClient } from '@supabase/ssr'
export function PostEditor({ post }: { post: Post }) {
const [title, setTitle] = useState(post.title)
const [body, setBody] = useState(post.body || '')
const [saving, setSaving] = useState(false)
const supabase = createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
async function save() {
setSaving(true)
const { error } = await supabase
.from('posts')
.update({
title,
body,
updated_at: new Date().toISOString(),
})
.eq('id', post.id)
setSaving(false)
if (error) alert('Save failed: ' + error.message)
}
async function generateSEO() {
const res = await fetch('/api/ai/seo', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, content: body }),
})
const metadata = await res.json()
// Aplicar metadata gerada ao post
await supabase
.from('posts')
.update({ metadata, excerpt: metadata.excerpt })
.eq('id', post.id)
}
return (
<div className="max-w-4xl mx-auto p-6">
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="text-3xl font-bold w-full mb-4 border-b pb-2"
/>
<textarea
value={body}
onChange={(e) => setBody(e.target.value)}
className="w-full h-96 font-mono text-sm p-4 border rounded"
/>
<div className="flex gap-4 mt-4">
<button onClick={save} disabled={saving}
className="px-4 py-2 bg-blue-600 text-white rounded">
{saving ? 'Saving...' : 'Save Draft'}
</button>
<button onClick={generateSEO}
className="px-4 py-2 bg-purple-600 text-white rounded">
✨ Generate SEO Metadata
</button>
</div>
</div>
)
}
Sim, isso é um textarea simples. Em um projeto real, você trocaria por algo como Tiptap, MDXEditor, ou BlockNote para edição rica. O ponto é: a interface de admin é seu código. Você controla cada pixel, cada fluxo de trabalho, cada permissão. Nenhuma luta com limitações da UI do CMS.
Para projetos mais complexos, considere Refine ou AdminJS como frameworks de painel admin que plugam diretamente ao Supabase. Eles economizarão semanas.
Custos Reais: O que essa Stack Realmente Custa
Vamos ser específicos com números para um site com muito conteúdo fazendo 100K pageviews/mês:
| Serviço | Tier | Custo Mensal | O que você obtém |
|---|---|---|---|
| Vercel | Pro | $20 | 1TB bandwidth, 1000 GB-hrs serverless |
| Supabase | Pro | $25 | 8GB banco de dados, 250GB bandwidth, 100K auth users |
| Claude API | Pay-as-you-go | ~$10-30 | ~5M tokens/mês (geração SEO, resumos, busca) |
| Domínio | Anual | ~$1 | domínio .com |
| Total | $56-76/mês |
Agora compare com uma stack típica de CMS headless:
| Serviço | Tier | Custo Mensal |
|---|---|---|
| Contentful | Team | $300 |
| Vercel | Pro | $20 |
| Algolia (busca) | Build | $50 |
| Auth0 (auth) | Essentials | $35 |
| Total | $405/mês |
Isso é uma diferença de 5-6 vezes. E a stack Supabase oferece mais flexibilidade, não menos.
Quando você ainda deve usar um CMS
Quero ser claro sobre isso. Não jogue seu CMS fora para cada projeto. Um CMS headless ainda é a melhor escolha quando:
- Grandes equipes editoriais precisam de fluxos de trabalho estruturados (cadeias de aprovação, agendamento, papéis que vão além do RBAC básico)
- Conteúdo é o produto -- editoras, empresas de mídia, sites de documentação com centenas de contribuidores
- Você precisa de edição visual -- algumas plataformas CMS oferecem pré-visualização ao vivo e construtores visuais que levariam meses para replicar
- Entrega multi-canal -- se o mesmo conteúdo alimenta um website, app móvel, sinalização digital e email, o modelo de conteúdo estruturado de um CMS se justifica
- Localização em escala -- plataformas CMS como Contentful e Sanity têm fluxos de trabalho i18n maduros
Ainda construímos muito dos projetos de CMS headless na Social Animal. Se isso é o que seu projeto precisa, fale conosco sobre isso. Mas para a categoria crescente de apps onde isso não é o que você precisa, pare de pagar por isso.
Checklist de Implantação em Produção
Antes de você enviar essa stack para produção, revise essa lista:
- Políticas Row Level Security testadas para cada tabela (o simulador de políticas do Supabase ajuda aqui)
- Rate limiting em rotas da API Claude (use o rate limiter
@vercel/edgedo Vercel ou upstash/ratelimit) - Validação de entrada em todas as rotas de API (Zod é seu amigo)
- Error boundaries em sua árvore React para falhas de IA (Claude ocasionalmente terá timeout)
- Estratégia de caching -- use
unstable_cacheourevalidateTagno Next.js para páginas apoiadas em banco de dados - Monitoramento -- Vercel Analytics para performance, Painel Supabase para métricas de banco de dados, Console Anthropic para uso de API
- Estratégia de backup -- Supabase Pro inclui backups diários, mas também configure replicação lógica ou cron
pg_dumppara tranquilidade - Content Security Policy headers configurados no
next.config.js - Otimização de imagem -- use o componente
<Image>do Next.js com URLs Supabase Storage
FAQ
Supabase realmente pode substituir um CMS headless?
Para muitos casos de uso, sim. Supabase oferece um banco de dados PostgreSQL com API REST e GraphQL auto-geradas do seu schema, armazenamento de arquivos, auth e assinaturas realtime. O que não oferece é uma UI de edição de conteúdo polida pronta -- você precisará construir isso você mesmo ou usar uma ferramenta como Refine. Se seu time é técnico ou pequeno, esse tradeoff absolutamente vale a pena.
Quanto custa a API Claude para um website típico?
Para um site de conteúdo que usa Claude para geração de metadata SEO, resumo de conteúdo e classificação básica, espere gastar $10-30/mês com uso moderado (algumas centenas de operações de IA). O preço do Claude Sonnet 4 em 2026 fica em aproximadamente $3 por milhão de tokens de entrada e $15 por milhão de tokens de saída. Uma chamada única de geração de metadata SEO custa aproximadamente $0,01-0,02.
Essa stack é adequada para aplicações enterprise?
Depende da sua definição de enterprise. Vercel e Supabase oferecem tiers enterprise com SLAs, conformidade SOC 2 e suporte dedicado. A stack lida bem com alto tráfego -- Next.js na Vercel escala automaticamente, e Supabase Pro suporta connection pooling e read replicas. Para indústrias pesadas em conformidade, você gostaria da opção auto-hospedada do Supabase para manter dados em sua própria infraestrutura.
E quanto a pré-visualizações de conteúdo e fluxos de trabalho de rascunho?
Você constrói. Next.js Draft Mode combinado com uma coluna status em sua tabela posts oferece fluxos de trabalho draft/published. Para pré-visualizações, crie uma rota autenticada que busca posts independentemente do status. São talvez 50 linhas de código versus configurar URLs de pré-visualização em um painel de CMS.
Como você lida com edição de rich text sem um CMS?
Use uma biblioteca de editor de rich text moderna. Tiptap (construído em ProseMirror) é a escolha mais popular em 2026 -- suporta edição colaborativa, blocos personalizados, slash commands e atalhos Markdown. BlockNote é outra opção sólida com uma UI estilo Notion. Armazene a saída como HTML, Markdown ou JSON em sua coluna body do Supabase.
Posso migrar de um CMS headless para essa stack?
Absolutamente. A maioria das plataformas CMS headless têm APIs de exportação. Escreva um script de migração que puxa conteúdo da API de seu CMS e insere em tabelas Supabase. Fazemos essa migração para vários clientes, migrando do Contentful e Sanity para setups apoiados por Supabase. A parte mais difícil é geralmente mapear o formato de rich text proprietário do CMS para HTML ou Markdown padrão.
O que acontece se Supabase cair?
Supabase teve uptime sólido em 2025-2026, mas nenhum serviço é perfeito. Porque seus dados vivem em PostgreSQL padrão, você tem opções: configure read replicas, mantenha backups automatizados em S3, ou até execute uma instância standby. Se você está no tier auto-hospedado do Supabase, você controla a infraestrutura completamente. Isso é realmente mais resiliente que depender de um fornecedor de CMS -- se Contentful tem uma queda, você não pode apenas "mudar para outro Contentful".
Devo usar essa stack para um blog ou site de marketing?
Para um blog pessoal de desenvolvedor ou um site de marketing de startup, essa stack é perfeita. Você obtém controle completo, custos mínimos e recursos potenciados por IA que exigiriam plugins caros em um CMS. Para um grande time de marketing publicando 20+ artigos por semana com fluxos de aprovação complexos, você provavelmente gostaria de um CMS apropriado. É sobre combinar a ferramenta ao time. Se você não tem certeza de qual abordagem se encaixa em seu projeto, confira nossa página de preços ou entre em contato para uma consulta rápida.