A Régua: seu WhatsApp no automático, sem pagar SaaS todo mês.
Todo mês você paga uma mensalidade pra um SaaS mandar mensagem no seu WhatsApp. Você é o operador de uma ferramenta que não é sua. A Régua vira o jogo: você constrói a máquina uma vez, ela roda no seu servidor, e a mensalidade some.
O motor é sempre o mesmo: um gatilho entra, o contato cai numa fila de mensagens agendadas, e um robô que roda a cada minuto dispara na hora certa. Muda só a copy e o momento de disparo. Com essa mesma base você liga 4 fluxos:
Cinco peças conversando. Você não precisa entender o código de cor, mas entender o desenho ajuda a mandar bem no Prompt Mestre e a caçar erro quando trava.
Um formulário no seu site ou o webhook da Hotmart avisa: "entrou um lead" ou "gerou um Pix". É o pontapé.
Guarda os contatos e cria a fila de mensagens agendadas (cada mensagem já nasce com a hora certa pra sair).
Um robô acorda de minuto em minuto, olha a fila e pega só as mensagens que já venceram (send_at <= agora).
Recebe o texto pronto e manda de verdade pelo seu número, via send-text. É o que conecta seu WhatsApp na máquina.
A mensagem chega no celular da pessoa como se você tivesse digitado. A fila marca sent e segue pra próxima.
// pega as vencidas, faz um "claim" otimista pra nunca enviar 2x const { data: due } = await supabase .from('mensagens') .select('*, contatos!inner(*)') .eq('status', 'pending') .lte('send_at', new Date().toISOString()) .limit(50); for (const m of due) { // só quem conseguir virar 'sending' envia. corrida resolvida. const { data: claimed } = await supabase.from('mensagens') .update({ status: 'sending' }) .eq('id', m.id).eq('status', 'pending') .select('id').maybeSingle(); if (!claimed) continue; await sendWhatsApp(m.contatos.telefone, buildMessage(m)); }
A máquina só precisa de três contas conectadas. Faça uma por vez, copie os valores pras variáveis de ambiente (envs) na Vercel, e pronto.
contatos e mensagens com o RLS já ligado.seu-app.vercel.app.https://seu-app.vercel.app/api/hotmart.Esse é o comando que faz o Claude Code te entrevistar antes de escrever uma linha e depois montar a máquina inteira. Copie, cole numa conversa nova e responda o que ele perguntar.
Máquina rodando, é hora de mexer. Esses prompts menores fazem o Claude ajustar tudo sem você tocar em código.
Abra lib/flows.js. Quero reescrever as mensagens do fluxo "[carrinho abandonado]". Mantenha os mesmos passos e delayMin, e as variáveis {nome} {produto} {valor} {link}. Deixe o tom [mais próximo e informal, com no máximo 3 linhas por mensagem]. Me mostre o antes e o depois de cada passo antes de salvar.
Quero um 5º fluxo chamado "[reativação de aluno sumido]". Gatilho: [entra pelo /api/enter com flow_id "reativacao"]. Adicione ele em lib/flows.js no mesmo formato dos outros (id, gatilho, passos com step/delayMin/texto). Sugira 4 mensagens com bons intervalos. Não quebre os fluxos que já existem.
Crie um endpoint /api/test que, ao ser chamado, usa lib/whatsapp.js pra mandar UMA mensagem de teste ("Régua funcionando ✅") pro meu número [55DDDNUMERO]. Proteja com o mesmo CRON_SECRET (header Authorization: Bearer). Me diga a URL exata pra chamar e como testar pelo navegador.
No api/dispatch.js, antes de enviar, quero passar a mensagem base pela API da Anthropic (ANTHROPIC_API_KEY) pra personalizar pelo {nome} e pelo histórico do contato (campo "notas" em contatos). Use um modelo barato, prompt curto, e se a IA falhar, caia de volta na mensagem base (nunca deixe de enviar). Mantenha o "claim" otimista.
Os problemas que aparecem 90% das vezes, com o motivo e o conserto. Bate o sintoma na tabela e resolve.
| Sintoma | Causa provável | Solução |
|---|---|---|
| Z-API dá 401 ou não conecta | Client-Token faltando ou instância desconectada do celular. | Confira ZAPI_CLIENT_TOKEN na Vercel e reconecte o QR na Z-API. O celular precisa estar com o WhatsApp aberto e online. |
| A mensagem não sai | Telefone salvo sem o 55 na frente ou número digitado errado. | A normalizePhone prefixa 55 em número BR. Cheque se o número no banco tem DDD certo e 11 dígitos. |
| Webhook não dispara nada | HotTok errado ou URL cadastrada errada na Hotmart. | Confira HOTMART_HOTTOK igual ao da Hotmart e a URL apontando pra /api/hotmart. Veja os logs da função na Vercel. |
| O cron não roda | vercel.json sem o bloco "crons" ou CRON_SECRET bloqueando. | Garanta o bloco crons com * * * * * e que o CRON_SECRET na env é o mesmo que o dispatch espera. |
| Mensagem chega duplicada | Faltou o "claim" otimista, dois crons pegaram a mesma linha. | O update pra status='sending' só onde status='pending' tem que estar lá. Quem não conseguir o claim, pula. |
| RLS bloqueando tudo | Usou a chave anon (pública) em vez da service_role. | O servidor tem que usar a SUPABASE_SERVICE_ROLE_KEY. Com RLS ligado e sem policies, só ela enxerga as tabelas. |
Cola o erro no grupo da Dinastia que a gente destrava com você.