Dá para criar um SaaS com IA hoje: um agente de código como o Claude Code ou o Codex consegue escrever cadastro, assinaturas, um dashboard e uma API em poucos dias. Mas um MVP que funciona precisa de mais do que “crie um SaaS para mim”: um escopo reduzido a um fluxo principal, uma spec escrita que o agente lê em toda sessão e testes nos caminhos onde estão o dinheiro e o isolamento de dados. Este post percorre o processo que eu sigo, do escopo ao deploy.
O objetivo é um guia que alguém que programa pouco ou nada consiga seguir. Tirar um protótipo do papel com vibe coding é fácil; manter um produto de pé quando alguém digita um cartão de crédito é a parte difícil. Por isso vou marcar onde dá para ir rápido e onde é preciso desacelerar.
1. Reduza o escopo a um fluxo principal
MVPs raramente morrem por causa do código. Morrem por causa do escopo. O agente escreve qualquer coisa que você pedir; o problema é que cada recurso adicionado precisa ser testado, mantido e depurado.
Antes de começar, escreva uma frase: “O usuário faz ___ e recebe ___ em troca.” Por exemplo: “Uma agência sobe os posts de redes sociais de um cliente, e o cliente os aprova por um único link.” Tudo o que estiver fora dessa frase vai para a versão dois.
Uma primeira versão geralmente só precisa de:
- Cadastro, login, redefinição de senha
- Uma organização (tenant) com membros convidados
- Um fluxo principal (a frase acima)
- Um plano pago, assinatura mensal
- Uma página de configurações simples e um link para o portal de cobrança
Central de notificações, matriz de papéis, vários idiomas, app para celular, painel de administração: depois. Se os clientes pagarem pelo fluxo principal, eles vão te dizer do que mais precisam.
2. Escreva uma spec que o agente siga
Agentes não carregam memória entre conversas. O Claude Code lê o CLAUDE.md na raiz do projeto em toda sessão; o Codex e muitos outros agentes leem o AGENTS.md. Escreva suas decisões ali e toda nova sessão começa com as mesmas regras. Se você usa os dois agentes, mantenha o conteúdo em um arquivo e faça o outro apontar para ele.
Uma spec útil é curta e concreta:
# Project: ApproveLink (MVP)
## Product
Agencies upload posts; the client approves or comments from one link.
## Stack
- Next.js (App Router, TypeScript), Tailwind
- Supabase: Postgres, Auth, Storage
- Stripe: one plan, monthly subscription, Checkout + Customer Portal
- Tests: Vitest (unit), Playwright (end to end)
## Rules
- Every table has organization_id; RLS is on for every table.
- Subscription status changes only from the Stripe webhook.
- Database changes only through migration files.
- Secrets live in .env.local; never in code or logs.
- Ask before adding a new package.
- After every task: pnpm lint && pnpm test
## Out of scope (for now)
Roles, i18n, mobile, admin panel.
A seção “out of scope” importa. Os agentes tentam ser prestativos e adicionam coisas que você não pediu; um limite escrito reduz isso de forma visível.
3. Escolha a stack: escolha o óbvio
Quando você trabalha com IA, a melhor stack é aquela da qual o agente viu mais exemplos. Para esse tipo de MVP, eu iria de:
- Next.js + TypeScript: frontend e API em um projeto só. O TypeScript pega parte dos erros do agente no build.
- PostgreSQL (Supabase ou outro Postgres gerenciado): dados relacionais, row-level security (RLS) e migrations. O Supabase também te dá autenticação e armazenamento de arquivos no mesmo lugar.
- Autenticação pronta: Supabase Auth, Auth.js ou Clerk. Não peça ao agente para escrever do zero o armazenamento de senhas e o controle de sessão.
- Assinaturas com Stripe: Checkout para a página de pagamento, Customer Portal para mudança de plano e cancelamento. Você nunca constrói um formulário de cartão.
- Vercel ou uma plataforma parecida: faz deploy a cada push e dá a cada branch uma URL de preview.
O que instalar: Node.js (LTS), pnpm, Git, uma conta no GitHub, o Supabase CLI, o Stripe CLI e um agente de código (claude ou codex).
pnpm create next-app@latest approvelink --typescript --tailwind --app
cd approvelink
git init && git add -A && git commit -m "chore: empty project"
Coloque a spec na raiz dessa pasta e faça commit dela também.
4. O primeiro prompt: plano antes, código depois
Minha primeira mensagem não pede código; pede um plano. Ler e corrigir um plano é muito mais barato do que reverter 40 arquivos escritos errado.
Read CLAUDE.md. Don't write code yet.
Produce an implementation plan for this MVP:
1. Database tables (fields, relations, RLS policies)
2. Pages and API routes
3. The Stripe flow (which webhook events, where subscription status lives)
4. 6–8 small steps in order, each with what gets tested at the end
List anything unclear as questions at the end.
Leia o plano, responda as perguntas e atualize a spec se precisar. Depois peça os passos um de cada vez:
Implement step 1 of the plan: write the migration for the organizations,
memberships and projects tables and add the RLS policies. When done,
apply the migration to the local database, write a test proving two
different users can't see each other's data, and run it. Then stop.
O “Then stop” é proposital. Depois de cada passo eu olho o diff e faço commit, então, quando o agente se desvia, existe um ponto limpo para voltar.
5. Isolamento de dados multi-tenant: a parte mais perigosa
O pior bug de um SaaS é “o Cliente A viu os dados do Cliente B”. O código do agente geralmente parece certo, porque você testa com um usuário só enquanto constrói. O problema aparece quando chega o segundo cliente.
Minhas regras:
organization_idem toda tabela. Sem exceções, tabelas filhas incluídas.- Deixe o banco impor o filtro. No Supabase/Postgres, ative o RLS em toda tabela e escreva a policy em torno das organizações às quais o usuário pertence. Um
where organization_id = ...no código do app não basta sozinho; o agente pode esquecê-lo na próxima query que escrever. - A service role key fica no servidor. Ela ignora o RLS. Nunca pode chegar ao código que vai para o navegador; no Next.js, nunca a coloque em uma variável
NEXT_PUBLIC_. - Teste com dois usuários. Crie duas organizações e, logado em uma, tente buscar um registro da outra pelo ID. Esse teste deve ser automatizado e rodar a cada mudança.
Pergunte diretamente ao agente: “Liste todos os lugares deste projeto que ignoram o RLS.” A resposta deve ser o código de servidor que usa a service role e os webhooks; se houver mais, pergunte por quê.
6. Migrations: nunca mude o banco à mão
Quando o agente quer adicionar uma coluna, deve fazer isso com um arquivo de migration, não clicando em um dashboard. Com o Supabase CLI:
supabase start # local Postgres (needs Docker)
supabase migration new add_projects # empty migration file
supabase db reset # apply all migrations from scratch
supabase db push # apply to the remote database
Rode db reset com frequência: se as migrations não aplicam limpas do zero, a produção também vai ter problemas. Depois que estiver no ar, leia toda migration que o agente escrever. Se aparecer DROP COLUMN, DROP TABLE, um UPDATE sem WHERE ou um índice que trava uma tabela grande, pare e pergunte por quê. Uma migration que apaga dados não tem volta.
7. Teste os caminhos do dinheiro
Você não precisa de testes para tudo; o tempo de um MVP é curto. Mas estes caminhos não devem chegar à produção sem teste:
- Cadastro → criar organização → fluxo principal. De ponta a ponta com Playwright.
- Webhooks do Stripe. O status da assinatura é atualizado corretamente em
checkout.session.completed,customer.subscription.updated,customer.subscription.deletedeinvoice.payment_failed? - Acesso sem pagamento. Quando uma assinatura é cancelada ou um pagamento falha, o recurso pago é realmente bloqueado?
- Isolamento de dados. O teste com dois usuários de antes.
Teste os webhooks do Stripe localmente assim:
stripe login
stripe listen --forward-to localhost:3000/api/webhooks/stripe
stripe trigger checkout.session.completed
Um prompt para o agente:
Review the Stripe webhook route. Is the signature verified? What happens
if the same event arrives twice (idempotency)? Which table holds
subscription status? Write tests for these four events:
checkout.session.completed, customer.subscription.updated,
customer.subscription.deleted, invoice.payment_failed.
Run them and show me the result.
Um erro comum: o agente ativa a assinatura na página de “sucesso” para a qual o Stripe redireciona. Qualquer pessoa pode abrir essa URL à mão. O status só deve mudar por um webhook com assinatura verificada.
8. Deploy e monitoramento
Em uma plataforma como a Vercel o fluxo é simples: suba o repositório para o GitHub, conecte o projeto, preencha as variáveis de ambiente no dashboard. Cada pull request ganha sua própria URL de preview; teste as mudanças ali antes da produção.
Meu checklist antes de colocar no ar:
- Variáveis de ambiente definidas em produção; keys live e de teste do Stripe sem mistura
- Um endpoint de webhook live configurado no Stripe, com o signing secret em uma variável de ambiente
- Migrations aplicadas ao banco de produção
- URLs de redirecionamento do Supabase Auth configuradas para o domínio de produção
- Backups do banco ligados
Para monitoramento, adicione um serviço de rastreamento de erros como o Sentry para ver os erros antes de um usuário escrever “quebrou”. Dizer isto ao agente basta: “Add Sentry to the Next.js project, capture server and client errors, and don’t attach user emails or secret values to events.” Adicione também uma checagem simples de uptime.
Onde a IA erra
- Inventa APIs que não existem. Principalmente com versões novas de bibliotecas. Quando o build ou os testes quebrarem, passe o erro como está para o agente e peça que consulte a documentação oficial.
- Muda o teste para fazê-lo passar. Se um arquivo de teste aparecer no diff, pergunte por quê.
- Adiciona pacotes de que você não precisa. A regra “pergunte antes de adicionar um pacote” na spec compensa aqui.
- Engole erros. Blocos
catch {}vazios deixam falhas de pagamento invisíveis. - Autorização no cliente. Esconder um botão não é segurança; a checagem pertence ao servidor e ao banco.
- Amplia o escopo. Reverta recursos que chegam com “também adicionei…” ou mova-os para uma branch separada.
- Perde o contexto em sessões longas. Conforme a conversa cresce, o agente esquece decisões do começo. Comece uma sessão nova por passo; as decisões permanentes já estão na spec. Fechar uma sessão antes que a janela de contexto encha protege tanto a qualidade quanto o custo em tokens.
Segurança: curto, mas sério
- Secrets vão no
.env.local. Confira se ele está no.gitignore. Se uma key já entrou em algum commit, revogue e emita uma nova; apagar do histórico não basta. - Nunca cole API keys no chat. O agente não precisa ver a key, só o nome da variável.
- Leia os comandos que o agente roda. Principalmente
rm,git push --force, comandos de banco ecurl … | sh. Aprove automaticamente só ações seguras, como ler arquivos e rodar testes. - Não aponte o agente para o banco de produção. Deixe-o trabalhar em um banco local ou de teste.
- Valide a entrada no servidor. Faça toda entrada da API ser checada com uma biblioteca de schema como o Zod.
- Audite as dependências. Passe a saída do
pnpm auditpara o agente de vez em quando.
Quando chamar um desenvolvedor humano
Se você chegou a algum destes pontos, algumas horas de revisão de um desenvolvedor experiente valem a pena:
- Antes de receber o primeiro pagamento real (webhooks, status da assinatura, reembolsos)
- Quando os dados dos clientes incluem dados pessoais (LGPD, GDPR e obrigações parecidas)
- Quando um cliente corporativo manda um questionário de segurança
- Quando você e o agente não conseguiram corrigir o mesmo bug em três sessões seguidas
- Quando começam os problemas de desempenho (queries lentas, índices faltando)
Deixe a spec, a pasta de migrations e a saída dos testes à mão para agilizar a revisão. Um projeto escrito com um agente, mas com commits em passos pequenos e coberto por testes, é um projeto que um desenvolvedor entende rápido.
Como eu faço isso com o AgentVera
Tudo acima funciona em um único terminal. Eu uso o AgentVera para gerenciar vários agentes ao mesmo tempo; estas são as partes que ajudam:
- Frontend e backend em worktrees separados. No workspace eu abro um agente Claude Code para a API e os webhooks e um agente Codex para a UI, cada um em seu próprio git worktree. Eles não mexem nos mesmos arquivos, então não quebram o trabalho um do outro. O método está em git worktrees para agentes em paralelo.
- O diff antes do merge. O painel Git mostra as mudanças de cada worktree, e a revisão de código checa cada turno concluído. O que procurar está em revisão de código com IA.
- Ver o banco de dados. Com o gerenciador de banco de dados eu abro as tabelas no Postgres local e confiro o que o agente realmente escreveu; o DB Guard sinaliza migrations arriscadas no fim de um turno.
- Previews. Os ambientes de preview dão ao servidor de desenvolvimento de cada worktree seu próprio endereço, então consigo testar duas branches lado a lado.
- De olho nos tokens. Cada painel mostra o tamanho do contexto ao vivo; quando ele incha, eu fecho a sessão e começo uma nova.
Isso acelera as coisas, mas não substitui as regras acima: a spec, os testes e a sua própria revisão continuam importando.
Concluindo
Criar um SaaS com IA tem menos a ver com gerar código e mais com escrever as decisões e proteger os caminhos críticos. Reduza o escopo a um fluxo, coloque as decisões no CLAUDE.md ou AGENTS.md, escolha uma stack óbvia e popular, imponha o isolamento de tenants no banco, teste os caminhos do dinheiro e configure o monitoramento antes do deploy. Peça para uma pessoa olhar antes de entrar dinheiro e dados reais. Se quiser rodar agentes em paralelo, baixe o AgentVera de graça e abra seus dois primeiros worktrees.