Supabase
Client, env vars e pacote compartilhado
O Vendee usa Supabase como backend completo: autenticação, PostgreSQL, Row Level Security, funções RPC e edge functions.
Ambientes
| Ambiente | Project ref | Uso |
|---|---|---|
| Desenvolvimento | nwcdzokqsnojkapkdbqe (vendee-db0) | Todo desenvolvimento local e preview |
| Produção | separado, não documentado aqui | Apenas deploy oficial |
Nunca usar o projeto de produção para desenvolvimento local. Todo trabalho local, testes e migrations vão para vendee-db0.
Client
O client Supabase é exportado pelo pacote @repo/supabase:
import { supabase } from "@repo/supabase/client";No apps/app, um re-export local facilita o uso:
// src/lib/supabase.ts
export { supabase } from "@repo/supabase/client";Nunca instancie um novo client com createClient(). Use sempre o singleton exportado do pacote — ele já está configurado com auth persistente e listeners de sessão.
Variáveis de ambiente
O client detecta automaticamente o ambiente:
| Variável | Ambiente |
|---|---|
VITE_SUPABASE_URL | Vite (apps/app) |
VITE_SUPABASE_PUBLISHABLE_KEY | Vite (apps/app); legado VITE_SUPABASE_PUBLISHABLE_DEFAULT_KEY |
NEXT_PUBLIC_SUPABASE_URL | Next.js (docs) |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | Next.js (docs); legado NEXT_PUBLIC_SUPABASE_ANON_KEY |
Tipos
Os tipos são gerados a partir do schema do banco e exportados por @repo/supabase/types:
import type { Database } from "@repo/supabase/types";
type Deal = Database["public"]["Tables"]["deals"]["Row"];
type DealInsert = Database["public"]["Tables"]["deals"]["Insert"];
type DealUpdate = Database["public"]["Tables"]["deals"]["Update"];Regenerar tipos
bunx supabase gen types typescript --project-id <project-id> > packages/supabase/src/types.tsAutenticação
O Supabase Auth gerencia:
- Login com email/senha
- Magic links (convites e login sem senha)
- Reset de senha
- Callback de autenticação (
/auth/callback)
Edge Functions
Edge functions são usadas para lógica server-side que precisa rodar com service_role (bypassando RLS) ou que envolve APIs externas. Exemplos no projeto:
admin-create-workspace— cria workspace + membro gestor + seed inicial- Aceite e recusa de proposta pelo link público (
accept-proposal-by-token,reject-proposal-by-token)
Chamada via client:
const { data, error } = await supabase.functions.invoke("admin-create-workspace", {
body: { name: "Cliente novo", admin_email: "[email protected]" },
});Edge functions devem ser mantidas finas — só lógica que precisa rodar no servidor. Lógica de UI e validação de formulário ficam no client.
O parque de edge functions hoje
São cerca de 40 funções, organizadas por domínio: cobrança (billing-*), API pública
(api-v1-*), e-mail e agenda (email-*, calendar-sync), propostas por link público,
automação (automation-runner), prospecção (prospeccao-search) e webhooks
(asaas-webhook, resend-webhook, webhook-dispatcher).
☠️ Nenhuma edge function gera PDF. A geração de PDF de proposta é 100% no navegador.
☠️ O motor de IA não vive em edge function nenhuma. As edges otto/ e arquiteto/ foram
deletadas — o único motor é o apps/runtime.
☠️ _shared/ é EMBUTIDO no bundle de cada consumidora, não resolvido em runtime. Mudou um
arquivo de _shared/, todas as edges que o importam ficam rodando código velho até serem
republicadas — e o git diff de pastas não mostra isso. Monte a lista de deploy pelo grafo de
imports, e erre para o lado de publicar a mais: deploy é idempotente, esquecer é bug mudo.
☠️ verify_jwt não é uniforme. Várias edges são chamadas por robô, webhook ou cron e nascem
com verify_jwt: false de propósito. Leia a configuração atual de cada uma antes de publicar e
preserve — aplicar uma regra genérica quebra as que dependem disso.
Edge function é Deno, e não entra no check-types do turbo. Rode
deno check supabase/functions/<fn>/index.ts antes de publicar: o comando de deploy só empacota,
não confere tipo — erro de tipo fica latente até estourar em produção.