Next.js SaaS
Como criar um SaaS com Next.js para produção: autenticação, cobrança, tarefas e implantação
Crie um SaaS Next.js 16 pronto para produção, com autenticação, Postgres, assinaturas, tarefas em segundo plano, configuração segura, testes e implantação.
Um SaaS fica complexo quando as funcionalidades dependem de estado: identidade, autorização, cobrança, novas tentativas, migrações e versões. A árvore de componentes React é apenas uma parte do sistema.
Definir o primeiro fluxo completo do cliente
Comece com um fluxo que o cliente consiga concluir: descobrir o produto, criar uma conta, passar pelo onboarding, criar o recurso principal, receber o resultado e voltar depois para encontrar o mesmo estado. Isso revela os limites reais do sistema mais cedo do que uma longa lista de funcionalidades.
Documente as transições de estado junto das telas. Defina quem pode executar cada transição, quais registros mudam, quais chamadas externas ocorrem e o que acontece se uma chamada se repetir ou falhar. Um SaaS confiável é projetado em torno dessas transições, não de uma coleção de cartões no painel.
- —Rotas públicas de aquisição e documentação.
- —Autenticação, sessão e recuperação de conta.
- —O objeto de domínio primário e suas regras de propriedade.
- —Um direito de acesso vinculado à cobrança ou um limite explícito do plano gratuito.
- —Evidências de e-mails, tarefas, auditoria e falhas.
Separar código público, código da aplicação e código exclusivo do servidor
Use grupos de rotas para dar layouts diferentes às rotas de marketing e às rotas autenticadas da aplicação, sem alterar suas URLs. Mantenha páginas e layouts como Server Components e acrescente Client Components nos formulários e controles que precisam do estado do navegador. Assim, o conteúdo público continua acessível aos robôs de busca e o painel exige menos JavaScript.
Coloque acesso ao banco de dados, autorização, adaptadores de cobrança e integrações que usam segredos em módulos exclusivos do servidor. Uma camada de acesso a dados concentra as leituras seguras em um ponto auditável. Server Actions cuidam das alterações iniciadas pela interface React; Route Handlers cuidam dos webhooks, das verificações de saúde e das interfaces HTTP usadas fora dela.
A practical SaaS route tree
src/app/
├── (marketing)/page.tsx
├── (marketing)/pricing/page.tsx
├── (auth)/login/page.tsx
├── (app)/dashboard/page.tsx
├── (app)/projects/[id]/page.tsx
├── api/stripe/webhook/route.ts
└── api/health/route.ts
src/lib/
├── auth.ts
├── dal.ts
├── db.ts
└── billing.tsModelar a propriedade dos dados no banco
Use um banco de dados relacional para contas, vínculos de membros, registros de domínio, direitos de acesso, eventos de webhook e tarefas que exigem transações e restrições. Dê a cada registro com proprietário uma chave de conta ou tenant. Imponha unicidade e chaves estrangeiras no banco para que a concorrência não contorne as premissas do código da aplicação.
Migrações são código de produção. Faça primeiro alterações aditivas, preencha os dados existentes separadamente quando necessário, implante código capaz de ler a estrutura transitória e remova os campos antigos depois. Uma versão não deve pressupor que todas as réplicas e tarefas mudam de esquema no mesmo instante.
Tratar o faturamento como estado assíncrono
O Checkout inicia o processo de cobrança, mas não determina sozinho o estado da assinatura. Crie a Checkout Session no servidor, redirecione para o provedor e atualize os direitos de acesso locais a partir de eventos de webhook verificados. Armazene os IDs de cliente e assinatura do provedor junto da conta proprietária.
Processe novas tentativas com segurança, registrando IDs de eventos com uma restrição de unicidade. Trate explicitamente ativação, mudanças de plano, falhas de pagamento, cancelamento e exclusão. Defina quais ações exigem um direito de acesso ativo e como um período de carência afeta o acesso. A interface deve ler o estado local normalizado da cobrança, em vez de consultar o provedor em cada página.
Retirar das requisições o trabalho demorado e sujeito a novas tentativas
E-mails, importações, exportações, sincronização com provedores e geração de relatórios não devem manter uma requisição HTTP aberta. Grave uma tarefa durável ou emita um evento de workflow como parte da alteração, retorne um estado útil ao usuário e deixe um worker executar o trabalho demorado com novas tentativas e prazos.
Torne as tarefas idempotentes, registre as tentativas e diferencie falhas do provedor que permitem nova tentativa de entradas inválidas. O painel deve mostrar estados pendentes, concluídos e com falha, em vez de fingir que toda ação em segundo plano termina imediatamente.
- —Identidade estável da tarefa e chave de deduplicação.
- —Novas tentativas limitadas, com espera progressiva.
- —Limites de tempo para chamadas externas.
- —Um erro final que possa ser inspecionado e um caminho de recuperação.
Testar limites e recuperação
Use testes unitários para as regras de domínio, testes de integração para a camada de acesso a dados e as alterações, e testes de navegador para cadastro, onboarding, workflow principal e cobrança. Acrescente cenários adversos: um usuário solicita um registro de outra conta, um webhook se repete, operações concorrentes disputam uma restrição do banco e um provedor externo excede o tempo limite.
Execute a compilação de produção separadamente do lint, da verificação de tipos e dos testes. Inicie a aplicação compilada com valores de ambiente semelhantes aos de produção, aplique as migrações em uma etapa controlada e faça testes básicos do conteúdo público, das leituras autenticadas, de uma alteração, da rota de webhook e do comportamento dos controles de saúde.
Implantar o contrato de execução completo
A Adios executa o servidor de produção padrão do Next.js como um processo Node.js persistente. Assim, Server Components, Route Handlers, conexões com o banco de dados e páginas autenticadas compartilham uma versão da aplicação. O manifesto registra a compilação, o comando de inicialização, a porta, o caminho de saúde, os recursos e as referências a segredos junto do código-fonte.
Implante uma prévia, inspecione os logs de compilação e execução, verifique migrações e serviços obrigatórios e promova a versão após a rota de saúde funcionar. Os domínios personalizados e o TLS gerenciado permanecem associados à versão promovida. Se uma versão candidata não iniciar ou não informar que está saudável, suas evidências continuam disponíveis sem que ela se torne a versão pública operacional.
adios.yaml
name: northstar-saas
build_cmd: npm ci && npm run build
start_cmd: npm start
runtime:
name: node@24
port: 3000
health_path: /api/health
requires:
- db
env:
DATABASE_URL: secret://DATABASE_URL
AUTH_SECRET: secret://AUTH_SECRET
STRIPE_SECRET_KEY: secret://STRIPE_SECRET_KEY