GitHub Repository
Boilerplate mínimo de assinatura com Next.js, Supabase e Dodo Payments.
Live Demo
Explore a demonstração implantada.
Visão geral
O starter de assinatura do Supabase é um app Next.js 15 e React 19 que vende assinaturas com o Dodo Payments. O Supabase fornece o login OAuth do Google e o banco de dados Postgres, enquanto o Drizzle ORM define o schema. Uma Supabase Edge Function recebe os webhooks do Dodo Payments e armazena pagamentos e assinaturas, e um painel básico mostra o plano e as faturas de cada usuário. Se você precisa apenas de checkout, Customer Portal e handlers de rota de webhook para um app existente, use um adaptador de framework:Next.js Adaptor
Express Adaptor
Pré-requisitos
Antes de começar, você precisa de:- Node.js 18 ou posterior, ou Bun 1.0 ou posterior.
- Um projeto do Supabase. Você precisa da URL, da chave anon, da chave de função de serviço e da string de conexão do banco de dados.
- Uma conta do Dodo Payments, para obter uma chave de API e um segredo de assinatura de webhook.
- Um cliente OAuth do Google Cloud, para obter o Client ID e o Client Secret.
Início rápido
1
Clone and Install
Clone o repositório e instale as dependências com Bun, npm ou pnpm:
2
Create a Supabase Project
Crie um projeto do Supabase. As etapas posteriores usam a referência do projeto, o subdomínio em
https://[your-project-ref].supabase.co. Copie estes valores:NEXT_PUBLIC_SUPABASE_URL, a URL do projetoNEXT_PUBLIC_SUPABASE_ANON_KEY, a chave anonSUPABASE_SERVICE_ROLE_KEY, a chave de função de serviçoDATABASE_URL, a string de conexão do banco de dados
3
Configure Google OAuth
No Google Cloud, adicione este URI de redirecionamento autorizado ao seu cliente OAuth:
https://[your-project-ref].supabase.co/auth/v1/callback. Em seguida, no Supabase Auth, habilite o provedor do Google com seu Client ID e Client Secret.4
Configure Dodo Payments
Com o seletor Live Mode desativado na barra lateral, crie uma chave de API em Developer → API Keys, no painel do Dodo Payments. Mantenha
DODO_PAYMENTS_ENVIRONMENT definido como test_mode enquanto estiver desenvolvendo.5
Add the Webhook in Dodo Payments
Em Developer → Webhooks, adicione um endpoint com esta URL. Você implantará a função que o disponibiliza em uma etapa posterior.Selecione os eventos de pagamento e assinatura que a função tratará:
- Eventos de pagamento:
payment.succeeded,payment.failed,payment.processingepayment.cancelled - Eventos de assinatura:
subscription.active,subscription.plan_changed,subscription.renewed,subscription.on_hold,subscription.cancelled,subscription.expiredesubscription.failed
DODO_WEBHOOK_SECRET.6
Create .env.local
Crie um arquivo O app Next.js lê todas as variáveis deste arquivo, exceto
.env.local no diretório raiz:DODO_WEBHOOK_SECRET. A Edge Function lê DODO_WEBHOOK_SECRET dos secrets do Supabase, que você define ao implantá-la.7
Provision the Database Schema
Envie o schema do Drizzle para o banco de dados do Supabase:
Tabelas criadas:
users, subscriptions, payments.8
Deploy the Webhook Function
Faça login no Supabase, armazene o segredo de assinatura como um secret da função e implante a Edge Function O script Uma resposta
dodo-webhook. Substitua [your-project-ref] pela referência do seu projeto:deploy:webhook executa supabase functions deploy dodo-webhook --no-verify-jwt, para que o Dodo Payments possa chamar a função sem um token de autenticação do Supabase. O Supabase fornece SUPABASE_URL e SUPABASE_SERVICE_ROLE_KEY à função por padrão.Para verificar a implantação, envie uma requisição sem assinatura:cURL
400 com Invalid webhook signature significa que a função está em execução e possui o secret. Uma resposta 500 com Server configuration error significa que DODO_WEBHOOK_SECRET não está definido. Para enviar um evento de teste assinado, abra o endpoint em Developer → Webhooks e use a aba Testing.9
Create Products and Features
Em Products, no painel do Dodo Payments, clique em Add Product para criar um produto de assinatura para cada plano. Opcionalmente, para listar os recursos do plano no app, adicione uma entrada de metadata com a chave Os valores de metadata são strings, números ou booleanos, portanto armazene o array como uma string JSON. A interface de preços analisa o valor de
features e um array JSON de strings como valor. A metadata do produto ficará assim:features e renderiza cada item.10
Run the Dev Server
Agora você tem um SaaS de assinatura funcional, estruturado com Supabase e Dodo Payments. Para confirmá-lo de ponta a ponta, assine um plano usando um cartão de teste. Depois que o webhook chegar, o painel mostrará seu novo plano.
O que está incluído
- Autenticação por meio do Supabase, com OAuth do Google configurado
- Checkout de assinatura por meio do Dodo Payments
- Uma Supabase Edge Function para webhooks (
dodo-webhook) - Um schema do Drizzle ORM, com os scripts
db:generateedb:migratepara migrações - Um painel com faturas, status da assinatura e recursos do plano
- Server actions para alterar planos, cancelar uma assinatura e restaurar uma assinatura cancelada
Arquivos e caminhos principais
O handler de webhook, as rotas do app e o schema do banco de dados estão nestes arquivos:- Edge Function
- Next.js Routes
- Database (Drizzle)
Variáveis de ambiente
O app Next.js e a Edge Function leem estas variáveis:Supabase
Supabase
.env.example não lista SUPABASE_SERVICE_ROLE_KEY, mas o cliente administrativo do app em lib/supabase/admin.ts precisa dele. Adicione-o manualmente.Dodo Payments
Dodo Payments
Google OAuth
Google OAuth
O app não lê as credenciais do Google a partir de variáveis de ambiente. Insira o Client ID e o Client Secret nas configurações do provedor do Google no Supabase Auth e adicione este URI de redirecionamento ao cliente OAuth no Google Cloud:
Verificação e solução de problemas
Webhook signature invalid (400)
Webhook signature invalid (400)
- Certifique-se de que o secret da função
DODO_WEBHOOK_SECRETcorresponda ao signing secret do endpoint no dashboard do Dodo Payments. - Confirme que você fez o deploy da versão mais recente da função
dodo-webhook. - A função verifica os headers do Standard Webhooks
webhook-id,webhook-signatureewebhook-timestamp. Certifique-se de que um proxy não os remova.
Database push fails
Database push fails
- Verifique a sintaxe de
DATABASE_URL. - A conexão direta (
db.[project-ref].supabase.co:5432) usa IPv6, a menos que seu projeto tenha o complemento de IPv4. Em uma rede somente IPv4, use a connection string do session pooler (documentação de conexão do Supabase). - Aguarde de 2 a 3 minutos após criar o projeto antes do primeiro push.
OAuth redirect mismatch
OAuth redirect mismatch
- O redirect URI deve ser
https://[ref].supabase.co/auth/v1/callback. - Use a mesma URI no Google Cloud e no provedor de autenticação do Supabase.
Para acessar o repositório original e as etapas detalhadas, consulte dodo-supabase-subscription-starter.