Open-Source Cold Email & Warmup Platform
Warmbly 是開源的冷郵件平台:溫暖您的收件箱、發送活動、並對每個回覆進行分流。可在我們的雲端運行或自行託管整個系統。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Painel para administrar os links gravados em TAGs NFC e QR Codes de cartões vendidos a negócios locais:
@perfil) ou a um site.Cada link ganha um endereço público https://seu-dominio.com.br/{negocio}/{link}, que conta o acesso, salva os dados do dispositivo e redireciona para a URL de destino.
| Camada | Tecnologia |
|---|---|
| App | Next.js 16 (App Router, Server Actions, proxy.ts) |
| UI | Tailwind CSS v4 + shadcn/ui (Base UI) + temas por variáveis CSS |
| Backend | Supabase (Auth, Postgres, RLS) |
| Testes | Vitest |
| Deploy | Vercel |
...?s=qr, para separar a origem nas estatísticas./comecar: busca o negócio no Google, mostra diagnóstico, meta, prazo estimado e kit recomendado, e captura o contato. Os pedidos aparecem em Painel → Pedidos, onde um clique cria o negócio e o link de avaliação./c/{codigo}), PDF de impressão com o QR de cada peça (gráfica: frente e verso em sequência; ou folhas A4) e CSV com os links para gravar nos chips NFC./relatorio/{token}, não indexado) para mandar ao dono pelo WhatsApp.GOOGLE_PLACES_API_KEY): a mesma busca feita de 25 pontos ao redor do negócio (grade 5×5, 600 m entre os pontos) pela Text Search da Places API, pedindo só o campo places.id.expires_at (30 dias), deixam de aparecer depois disso e são apagados pelo cron diário /api/cron/limpeza. Os dados da Apify não expiram.npm install
cp .env.example .env.local # preencha as variáveis
npm run dev
supabase/migrations/20261003000000_init.sql de uma destas formas:
supabase link --project-ref SEU_REF e depois npm run db:push.| Variável | Descrição |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | URL do projeto Supabase |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | Chave publicável (sb_publishable_...) ou a antiga anon |
SUPABASE_SECRET_KEY | Chave secreta (sb_secret_...) ou a antiga service_role. Usada só no servidor, nas rotas públicas de redirecionamento e Pix |
NEXT_PUBLIC_SITE_URL | Domínio usado nos links das TAGs e QR Codes (ex.: https://cartoes.com.br) |
IP_HASH_SALT | Texto aleatório para anonimizar IPs (openssl rand -hex 32) |
GOOGLE_PLACES_API_KEY | Opcional. Google Places API (New): busca do negócio no quiz e na ativação. Sem ela, os formulários pedem nome e cidade |
APIFY_TOKEN | Token da Apify. Fonte das métricas do Google Maps (painel, Evolução, cron) via scraper |
APIFY_MAPS_ACTOR | Opcional. Actor do scraper (padrão compass~crawler-google-places) |
NEXT_PUBLIC_WHATSAPP_NUMBER | WhatsApp da TopTap (55 + DDD + número), usado no fim do quiz |
OPENAI_API_KEY | Chave da OpenAI para a análise do perfil no Google. Sem ela, o painel mostra só o checklist |
OPENAI_MODEL | Opcional. Modelo da análise (padrão gpt-5-mini) |
CRON_SECRET | Segredo do cron semanal /api/cron/google (a Vercel envia no cabeçalho Authorization) e do webhook da Apify |
Se NEXT_PUBLIC_SITE_URL não estiver definida, o sistema usa o domínio de produção da Vercel (VERCEL_PROJECT_PRODUCTION_URL).
/comecar)APIFY_TOKEN, a pessoa digita nome e cidade e clica em Buscar no Google (scraper da Apify, de 15 a 60 s, até 3 resultados). Cada busca fica em cache por 7 dias (maps_searches) e há limite de 5 buscas por hora por visitante. Sem nenhuma das duas, cadastro manual.leads e o cliente pode enviar o resumo pelo WhatsApp.O progresso é salvo a cada etapa (status quiz) e vira lead ao receber o WhatsApp. Kit, valor e prazo são recalculados no servidor. Preços em src/lib/pricing.ts; regras da projeção em src/lib/quiz.ts (PROJECTION: 26 dias × 1% dos clientes avaliando, ajuste com dados reais).
Painel → Cartões → Gerar lote (ex.: 50 cartões)
→ Imprimir (PDF com QR único por peça) → gráfica
→ Links (CSV) → gravar cada chip NFC na ordem
Cliente abre a peça (/c/k7m2p9qa)
├─ em branco → /c/k7m2p9qa/ativar → busca no Google → cria negócio + link de avaliação
│ → coleta do Google Maps + análise da IA (after())
└─ ativada → conta o acesso e redireciona para a avaliação (igual aos links normais)
g.page/r/.../review). Se o mesmo link (ou Place ID) já existir, a peça entra no mesmo negócio com o próprio link./conta)Na ativação, o dono informa e-mail e WhatsApp. Ele vira membro do negócio (business_members) e recebe um link mágico por e-mail. A área /conta mostra o plano, o histórico de relatórios mensais, as peças e os links, só para leitura. O primeiro membro entra ativo; quem chega depois fica aguardando a liberação no painel (página do negócio → Acesso do cliente). O painel /dashboard é só para quem está em admins; os outros usuários são levados para /conta.
Configuração no Supabase (Authentication):
https://toptap.com.br).supabase/templates/magic_link.html. O botão aponta para
{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email, que abre direto a /conta
em qualquer navegador (o modelo padrão manda o token no # da URL, que o app não lê).
Mesmo com o modelo padrão (em inglês), o link funciona: o Supabase volta com a sessão no # da URL e o
componente SessionFromHash (layout raiz) grava a sessão e abre a /conta.
Os outros modelos (Confirm signup, Invite user, Reset password, Change email address e Reauthentication)
ficam em supabase/templates/ com o mesmo visual, e os assuntos em supabase/config.toml. Os botões também
apontam para /auth/confirm (com type=signup, invite, recovery ou email_change). Como o app não tem
tela de nova senha, o de recuperação só faz o login.O Google Maps Scraper da Apify busca cada negócio (por Place ID ou por "Nome, Cidade - UF") e traz nota, avaliações, distribuição de estrelas, total de fotos, horário, contato e as 20 avaliações mais recentes (com a resposta do dono).
Ativação / "Atualizar dados" → execução síncrona (até ~4 min) → place_snapshots (+ place_id no negócio)
Cron semanal (segunda, 6h) → 1 execução com todos os clientes → Apify chama /api/apify/webhook → place_snapshots
TAG NFC → /padaria/avaliacao ─┐
QR Code → /padaria/avaliacao?s=qr ─┤→ busca link ativo → 302 para a URL de destino
└→ after(): grava o acesso em link_visits
(gatilho incrementa links.click_count)
after()), então o cliente não espera o banco.Cache-Control: no-store, para que nenhum acesso deixe de ser contado.SHA-256(salt + IP), o que basta para contar visitantes únicos (LGPD)./{negocio}/{link}/pix, que gera o BR Code conforme o manual do Banco Central.src/app/globals.css, nos blocos :root (claro) e .dark (escuro), no padrão de variáveis do shadcn/ui. Para mudar o visual, troque os valores ali.next-themes).src/components/brand/logo.tsx e arquivos originais em public/brand/.npm test # roda uma vez
npm run test:watch # modo observação
npm run typecheck
npm run lint
Os testes unitários ficam em src/lib/__tests__ e cobrem:
| Módulo | O que é testado |
|---|---|
slug | geração de endereços (acentos, símbolos), validação, slugs reservados |
urls | URL da TAG/QR, domínio base, normalização de destino (@perfil, sem https://, protocolos inválidos) |
user-agent | detecção de navegador/app, sistema, tipo de aparelho, fabricante e robôs |
visit | IP via proxy, hash do IP, origem NFC/QR, idioma, geolocalização da Vercel |
redirect | decisão de redirecionamento, página Pix, 404, registro adiado do acesso |
pix | CRC16, BR Code (incluindo o exemplo oficial do Banco Central), chaves CPF/CNPJ/telefone/e-mail/aleatória |
analytics | totais, únicos, série diária no fuso de São Paulo, agrupamento "Outros", períodos |
validation | formulários de negócio, link e login |
csv | escape RFC 4180 e proteção contra injeção de fórmulas |
src/
app/
[business]/[link]/route.ts redirecionamento público + contagem
[business]/[link]/pix/page.tsx página Pix Copia e Cola
dashboard/ painel (negócios, links, estatísticas, CSV)
login/ login
components/
dashboard/ formulários, QR Code, gráficos
theme/ provedores e seletor de tema
ui/ componentes shadcn/ui
lib/ regras de negócio (testadas) e clientes Supabase
proxy.ts sessão e proteção do /dashboard
supabase/migrations/ schema, RLS e gatilhos