Aplicação SaaS de produtividade com autenticação, controle de acesso e painel admin.
- Frontend e backend: Next.js (App Router + API Routes)
- Banco e auth: Supabase (PostgreSQL + RLS + Supabase Auth)
- Pagamento: Stripe Checkout + Webhook
- Deploy: Vercel
- Copie
.env.examplepara.env.local - Preencha as variáveis
- Execute:
npm install
npm run devExecute o arquivo supabase/schema.sql no SQL Editor do Supabase.
Depois execute também supabase/production-hardening.sql para índices e hardening incremental.
Esse schema já inclui:
- tabelas principais
- RLS
profiles.is_authorizedeprofiles.is_admin- trigger para criar profile automático no signup
- Usuário sem login: redirecionado para
/auth - Usuário logado sem assinatura ativa: redirecionado para
/pagamento - Usuário admin: acesso também ao
/admin - Autorização padrão: somente por pagamento (Stripe webhook atualiza
billing_statuseis_authorized)
- Defina
PAYMENT_PROVIDER=kiwify. - Defina
NEXT_PUBLIC_CHECKOUT_URLcom o link de checkout da Kiwify. - Defina
KIWIFY_WEBHOOK_SECRET. - Configure webhook na Kiwify para:
POST https://SEU_DOMINIO/api/v1/kiwify/webhook
- Com pagamento aprovado, o webhook ativa:
profiles.billing_status = activeprofiles.is_authorized = true- valida usuario por email e tambem por CPF (quando o payload da Kiwify envia CPF)
- envia email de confirmação de compra
- envia email com link para
/acesso(redirecionamento para login)
Para enviar os dois emails pós-compra, configure:
SMTP_HOST(ex.:smtp.gmail.com)SMTP_PORT(ex.:465)SMTP_SECURE(truepara SSL)SMTP_USERSMTP_PASS(App Password do Gmail)EMAIL_FROMEMAIL_REPLY_TO(opcional)
ALLOW_MANUAL_AUTHORIZATION=false(padrão): painel admin não libera acesso manual.ALLOW_LEGACY_MANUAL_AUTH=false(padrão):is_authorizedmanual legado não concede acesso.- Acesso real considera
billing_statusativo (activeoutrialing), com exceção de admin.
Proteção centralizada em src/middleware.ts.
GET /api/v1/admin/userslista usuários (admin)PATCH /api/v1/admin/users/:id/authorizationlibera/bloqueia usuário (admin)POST /api/v1/billing/checkoutcria checkout StripePOST /api/v1/stripe/webhookprocessa eventos Stripe
- Suba o repositório no GitHub
- Importe na Vercel
- Configure variáveis de ambiente da
.env.example - Deploy
- No Stripe, configure webhook para:
https://SEU_DOMINIO/api/v1/stripe/webhook
No Supabase SQL Editor:
update public.profiles
set is_admin = true, is_authorized = true
where id = (
select id from auth.users where email = 'seu-email@exemplo.com'
);- Testes unitários (Vitest):
npm run test:ci - Lint:
npm run lint - Build de produção:
npm run build - CI automático em GitHub Actions:
.github/workflows/ci.yml