Skip to content

Repository files navigation

Rumaria

O rumo da sua próxima terra.

🌐 www.rumaria.com.br — site em produção

Marketplace SaaS de imóveis rurais do Brasil — fazendas, sítios, chácaras e ranchos. Corretores assinam plano mensal para anunciar; compradores navegam grátis e falam direto via WhatsApp.


Por que esse projeto

Mercados de imóveis rurais no Brasil são fragmentados, com portais generalistas mal adaptados ao agro e poucos focados em especificidades técnicas (reserva legal, georreferenciamento, aptidões, fontes de água). A Rumaria é construída de baixo pra cima como marketplace especializado, com:

  • Score automatizado que premia anúncios completos e corretores que respondem rápido.
  • Ficha técnica rural rica (24+ benfeitorias, aptidões, topografia, lat/lng com mapa).
  • Programa Fundador — convite outbound para os primeiros 20 corretores, com landing personalizada via Z-API.
  • Curadoria editorial — Acervos numerados que populam o site no lançamento sem expor identidade de terceiros.

Stack

Camada Tecnologia
Frontend + API Next.js 15 (App Router, Server Components, Server Actions)
Banco + Auth + Storage Supabase (PostgreSQL + RLS + Storage)
Pagamentos Mercado Pago (assinaturas + webhook HMAC)
WhatsApp Outbound Z-API (envio + parsing de respostas)
Email transacional Resend
Cache + Rate limit Upstash Redis
PDF do anúncio Browserless (Puppeteer-as-a-service)
Imagens Pipeline Sharp (WebP, 3 tamanhos)
Mapas Mapbox GL
Estilo Tailwind CSS v4 (tokens em globals.css)
Linguagem TypeScript strict
Deploy Vercel + Cron
Scraper auxiliar Python + Playwright + BeautifulSoup

Diferenciais técnicos

1. Score automatizado

Todo anúncio recebe nota 0–100 baseada em fotos, descrição, completude da ficha técnica e destaques. Score também leva em conta o corretor (anúncios aprovados, dias na plataforma, taxa de resposta a leads, denúncias). Resulta em selos automáticos:

  • Premium (80+) → home + busca destacada
  • Bom (60–79) → busca padrão
  • Baixa qualidade (<60) → só visível no perfil do corretor

Lógica em src/lib/utils.ts com pesos configuráveis em src/lib/constants.ts.

2. Programa Fundador (outbound + onboarding por WhatsApp)

Sistema completo para os primeiros 20 corretores parceiros:

  • Staging seguro (leads_fundador) — dados raspados ficam fora do site público até aceite explícito.
  • Token HMAC assinado com expiração de 7 dias.
  • Z-API integrada — envio do convite por WhatsApp + webhook que reconhece SIM/NÃO/e-mail e completa o aceite sem o corretor precisar abrir landing.
  • Hash de telefone com salt — opt-out via blocklist sem armazenar dado pessoal em claro.
  • Landing premium com hero cinematográfico, watermark Bebas Neue, contadores animados, marquee de credibilidade, preview dos imóveis do corretor já renderizados como anúncio Rumaria.
  • Magic link automático após aceite (Supabase Auth recovery) — corretor define senha, conta vira ativa.

Migration em supabase/migrations/00026_leads_fundador.sql.

3. Curadoria editorial ("Acervo")

Forma legal de popular o marketplace antes da onda de fundadores: importa anúncios públicos de portais de imóveis rurais e publica sob corretores fictícios numerados (Acervo 1, Acervo 2...), sem expor nome/CRECI/foto do anunciante origem. WhatsApp do corretor original fica no anúncio para facilitar contato real, e o anúncio leva selo de "curadoria editorial" + link para o portal de origem.

Script: scripts/scraper/importar_acervo_rumaria.py.

4. Segurança alinhada com LGPD

  • RLS deny-all em tabelas de staging (toda mutação passa por server actions).
  • HMAC timing-safe no webhook Mercado Pago.
  • CSRF via header Origin em mutações sensíveis.
  • Rate limit Upstash em endpoints públicos críticos (signup, aceite, recusa, magic link).
  • LGPD art. 18 VI — exclusão completa de conta + storage cleanup.
  • PII minimization — telefone hashado em blocklist, email só após aceite.

5. Pipeline de imagens

Sharp local + Supabase Storage. Cada upload vira:

  • thumb 320×240 (WebP q70) — cards
  • gallery 1280×960 (WebP q80) — listagem do imóvel
  • zoom 2560×1920 (WebP q90) — lightbox

Cache immutable, max-age=31536000 na URL pública, sem CDN extra.

6. URL SEO-friendly

Formato: /imoveis/{tipo}-em-{cidade}-{uf}-com-{area}ha-r-{preco}-ref-{codigo}

Exemplo: /imoveis/fazenda-em-cachoeira-paulista-sp-com-215-ha-r-12900000-ref-6JAF75

Código alfanumérico de 6 chars gerado por trigger no banco — único e estável.


Arquitetura

src/
  app/                       # Next.js App Router
    (public-facing)
      page.tsx               # Home com Premium + Cabeceiras + Trust signals
      imoveis/               # Listagem + detalhe + comparar + SEO por estado
      corretor/[slug]/       # Perfil público do corretor
      corretores/            # Diretório de corretores
      planos/                # Tabela de planos com upgrade flow
      cadastro/              # Signup com convite opcional
      login/, recuperar-senha/, atualizar-senha/
      convite/[token]/       # Landing de Programa Fundador (cinematográfica)
      sobre/, termos/, privacidade/, cookies/, termos-fundador/

    (authenticated)
      painel/                # Área do corretor: imoveis, perfil, pagamentos, fundador
      minha-conta/           # Editar perfil + LGPD delete

    (admin)
      admin/                 # Dashboard com KPIs + alertas
        usuarios/            # Corretores: validar CRECI, marcar fundador
        imoveis/             # Moderação + edição
        leads-fundador/      # Pipeline outbound + import JSON
        comissoes/           # Pagamento de comissões de fundadores
        denuncias/           # Triagem
        importador/          # Curadoria de imóveis

    (api)
      api/webhooks/mercadopago, /zapi
      api/cron/*             # 9 jobs agendados (crons em vercel.json)
      api/admin/leads-fundador  # Endpoint pra scraper postar JSON

  components/                # UI primitives + layouts + emails
  features/                  # Lógica por domínio (auth, properties, payments, fundador, convite)
  lib/                       # constants, utils, env, supabase clients, image-pipeline, rate-limit
  types/                     # database.ts (todo o schema tipado)

supabase/
  migrations/                # 28 migrations (até features mais recentes)

scripts/
  scraper/                   # Python + Playwright (importação automatizada)
  cleanup/                   # SQL de limpeza pontual

Comandos

npm run dev        # servidor de desenvolvimento
npm run build      # build de produção (compila + collect static)
npm run lint       # ESLint (zero warnings exigido)
npm run typecheck  # TypeScript strict, no any

Setup local

# 1. Instalar
npm install

# 2. Configurar env
cp .env.example .env.local
#    preencher com chaves reais (Supabase, MP, Resend, etc)

# 3. Rodar migrations
#    Painel Supabase → SQL Editor → executar arquivos de
#    supabase/migrations/ em ordem numérica

# 4. Subir servidor
npm run dev

Detalhes de cada variável em .env.example.


Crons (Vercel)

Definidos em vercel.json:

Cron Schedule Função
verificar-assinaturas diário 6h Suspende inadimplentes, ativa pagas
expirar-indicacoes diário 7h Janela de 12 meses fim
expirar-convites diário 8h Convites de fundador 7d → recusa
relatorio-mensal dia 1 às 9h Email mensal pros corretores
avisar-convites-expirando diário 14h Aviso 2d antes de expirar
atualizar-cotacoes dias úteis 12h30 Cotação soja/boi/dólar
limpar-vendidos diário 3h Auto-arquiva vendidos antigos
atualizar-irv dia 2 às 4h Índice de Referência de Valores
reset-cabeceira dia 1 às 5h Reset do destaque "cabeceira"

Performance

Cenários de carga em tests/load/ com k6. Cobertura:

  • home.k6.js — fluxo público (home → listagem → detalhe → perfil corretor)
  • webhook-mp.k6.js — webhook Mercado Pago com HMAC válido
  • webhook-zapi.k6.js — webhook Z-API com 5 variantes de payload
  • convite.k6.js — landing pública do Programa Fundador

Resultados reais (build de produção, 2026-04-25, MacBook-class hardware):

Endpoint VUs RPS p50 p95 Erro
GET / + /imoveis + /imoveis/[slug] + /corretor/[slug] 20 6.4 318ms 645ms 0.00%
GET /convite/[token] (HMAC-signed token) 15 74 90ms 181ms 0.00%
POST /api/webhooks/zapi?token=... (5 payload variants) 20 71 122ms 170ms 0.00%
POST /api/webhooks/mercadopago (HMAC validation only) 25 254 44ms 92ms 401 esperado*

* O teste de webhook MP usa secret de teste para validar o caminho de rejeição rápida por HMAC inválido (expected 401). Esse é o caminho mais quente em produção — Mercado Pago re-tenta webhooks com replay, então rejeitar requests inválidas em <100ms é desejado.

Targets calibrados pra carga média realística — o objetivo é detectar regressão, não medir limite máximo. Cada teste tem 3 estágios (warm-up → sustained → ramp-down) totalizando ~40-55s de execução.

Como rodar (sempre contra build de produção, não dev):

# Janela 1 — sobe build otimizado
npm run build
npm run start

# Janela 2 — roda os testes
k6 run tests/load/home.k6.js
k6 run tests/load/convite.k6.js

Webhooks de pagamento/WhatsApp só rodam contra Supabase de teste — processam dados reais quando recebem assinaturas válidas.


Decisões de produto

  • Mobile-first — toda UI começa em 360px, expande pro desktop.
  • WhatsApp como canal primário — botão âmbar cta em destaque, sem captura de e-mail intermediária.
  • Português pt-BR para usuário, inglês para código — evita ambiguidade entre identifiers e copy.
  • Sem ORM — Supabase client direto, types gerados de src/types/database.ts.
  • Sem state management — React context para sessão, URL state para filtros.
  • Tailwind v4 — config no CSS via @theme inline, sem tailwind.config.ts.

Licença

Proprietário. Todos os direitos reservados.

About

O rumo da sua próxima terra.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages