Aplicacao web/mobile para marketplace local, pedidos, lojas, pagamentos, entregas por motoboy, condominios e destinos turisticos.
O projeto roda como monorepo e hoje tem quatro servicos principais em producao:
- Frontend: SPA React/Vite servida por nginx.
- APIs BFF: camada Express intermediaria em
apis/, responsavel por rotas proprias e proxy para o backend. - Backend: API Express/TypeORM em
backend/, com regras de negocio, banco, pagamentos, uploads, jobs e webhooks. - Face worker: worker Python para verificacao assistida de documentos de motoboy.
- Cliente: home do app, busca de lojas, carrinho, checkout, meus pedidos, acompanhamento publico e notificacoes.
- Lojista/Admin: dashboard, cardapio, fila de pedidos, produtos, pagamentos, motoboys, condominios e destinos.
- Motoboy: fila de entregas, entrega atual, ganhos, perfil, documentos e repasse/recebimento de gorjetas.
- Super Admin: gestao de lojas, planos, usuarios, KYC de motoboy, destinos, banners da home, e-mails, seguranca e configuracoes globais.
- Destinos turisticos: cidades, chale/pousada, servicos locais, lojas que atendem hospedagens e convites comerciais.
- Portal do parceiro de destinos: chalés, pousadas, serviços e restaurantes aprovados podem atualizar dados próprios com permissão limitada.
- Condominios: vitrines por condominio/evento, lojas participantes e fluxo normal de pedido.
flowchart LR
U[Cliente / Lojista / Motoboy / Super Admin] -->|HTTPS| N[Nginx EC2]
N -->|/| F[Frontend container :80]
N -->|/api/*| B[APIs BFF :5000]
N -->|/uploads/*| A[Backend :4000]
B -->|proxy interno| A
A --> P[(PostgreSQL 16)]
A --> S3[(S3 uploads publicos)]
A --> MP[Mercado Pago]
A --> FCM[Firebase/FCM]
A --> FW[Face worker]
Fluxo importante:
- O frontend sempre chama rotas relativas em
/api/.... - O nginx entrega a SPA e encaminha
/api/*para o BFF. - O BFF fica em
apis/e encaminha a maioria das rotas parahttp://backend:4000/api. - O backend em
backend/e o motor real de dados, migrations, jobs, uploads, pagamentos e webhooks. - Arquivos publicos novos devem ir para S3 pelo fluxo de upload existente; nao adicionar novas imagens dinamicas em
frontend/public.
frontend/: React + Vite, PWA/Capacitor, telas web/mobile, testes unitarios e Playwright.apis/: BFF Express, rotas intermediarias e proxy para o backend.backend/: API principal, TypeORM, migrations, entidades, jobs, uploads, Mercado Pago, MFA e push.mobile/: shell Android/Capacitor e build AAB quando houver mudanca nativa.face-worker/: FastAPI/Python para verificacao facial de documentos.docs/: documentacao operacional, QA, SQLs, handoff e guias de manutencao.scripts/: deploy, compose local, backup, release e utilitarios.server/: codigo legado de mapas; nao sobe no compose padrao atual.
A Home principal do app fica em frontend/src/pages/MarketplacePage.tsx.
Depois do refactor, essa pagina deve ser tratada como orquestradora: ela junta dados, hooks, componentes e callbacks principais, mas nao deve voltar a acumular blocos grandes de estado, polling, cache, localStorage, chamadas de API ou JSX repetido.
Documentacao detalhada do refactor e manutencao: docs/HUB_MARKETPLACE_REFACTOR.md.
Estrutura atual para manutencao:
frontend/src/pages/MarketplacePage.tsx: shell principal da Home/Hub, composicao dos blocos e integracao com navegacao.frontend/src/components/Marketplace/Hub/: componentes visuais do Hub, como header, filtros, cards, carrosseis, favoritos, estados da lista e popup.frontend/src/hooks/hub/: hooks de regra de tela, estado, cache e polling especificos do Hub.frontend/src/services/: servicos HTTP usados pelos hooks e pela pagina.frontend/src/utils/: funcoes puras compartilhadas, formatadores, assets, links e regras reutilizaveis.
Hooks atuais do Hub:
useHubSearchPlaceholder: controla a rotacao do placeholder da busca.useHubFavorites: controla favoritos de loja no localStorage e ordenacao visual de favoritos.useHubFeaturedProducts: busca e monta os itens em destaque patrocinados/organicos.useHubLocation: resolve endereco principal do cliente, GPS, regiao ativa e link de destinos.useHubStores: carrega a vitrine de lojas, controla refresh e alternancia entre regiao/todas as lojas.useHubStoreDistances: calcula/cacheia distancias locais quando a API nao entrega distancia pronta.useHubAnonymousOrders: hidrata pedidos anonimos salvos no navegador e reconcilia status publico.useHubCustomerActiveOrders: faz polling dos pedidos ativos do cliente logado.
Regra para novas features no Hub:
- Nova UI deve virar componente pequeno em
frontend/src/components/Marketplace/Hub/. - Nova logica de estado/cache/polling/localStorage deve virar hook em
frontend/src/hooks/hub/. - Evitar colocar efeitos grandes e chamadas de API diretamente em
MarketplacePage.tsx. - Preservar a ordenacao das lojas e regras de filtro existentes, salvo pedido explicito.
- Se a feature mexer em busca, filtros, lojas, destaques, pedidos ativos ou navegacao mobile, criar ou ajustar teste unitario/e2e correspondente.
Validacao minima para mudancas no Hub:
npm --prefix frontend run test:unit
npm --prefix frontend run build
sh scripts/compose-dev-frontend.shApos rebuild local Docker, validar tambem:
curl -I http://localhost:8080/hub
curl -I http://localhost:8080/api/public/stores
docker exec janocaminho-postgres psql -U postgres -d espetinho -c "SELECT 'users' entidade, COUNT(*) total FROM users UNION ALL SELECT 'stores', COUNT(*) FROM stores UNION ALL SELECT 'products', COUNT(*) FROM products UNION ALL SELECT 'orders', COUNT(*) FROM orders UNION ALL SELECT 'site_settings', COUNT(*) FROM site_settings ORDER BY entidade;"Para mudancas que afetem UX critica ou navegacao:
npm --prefix frontend run test:e2eBanco principal: PostgreSQL.
Fontes versionadas do schema:
backend/schema.sql: schema base.backend/src/utils/runMigrations.ts: evolucoes incrementais e DDL complementar.backend/docs/database-schema.html: documentacao HTML gerada do schema.
Configuracoes globais ficam em site_settings.
Chaves importantes:
home.config: JSON dos banners da Home e Popup de Marketing.trial_days: dias de teste gratis padrao para loja.founder_vip_enabled: ativa/desativa a campanha VIP fundador.founder_vip_store_limit: limite de lojas contempladas pela campanha.founder_vip_days: dias concedidos na campanha.founder_vip_label: texto interno gravado na atribuicao da loja.legal.termselegal.lgpd: textos legais exibidos ao usuario.
Configuracoes por loja em store_settings:
order_types: tipos de pedido aceitos pela loja (delivery,pickup,table).table_service_settings: JSON do atendimento em mesa, com couvert artistico e taxa de servico opcionais. Quando ativo, a fila do lojista mostra botoes para aplicar no pedido e esses valores saem na impressao como itens do pedido.
Pedidos de entrega com orders.fulfillment_mode = 'postal' usam uma extensao propria em order_shipments.
order_shipments: serviço postal escolhido, código/URL de rastreio, data de postagem, entrega e último evento conhecido.order_shipment_events: timeline do envio postal exibida ao cliente, separando origemseller,systemecarrier.- O vendedor informa ou edita o rastreio por
PATCH /api/orders/:orderId/postal. - O acompanhamento público usa o mesmo payload do pedido e inclui
shipment.eventseshipment.trackingSummary. - A integração externa fica atrás de
ShippingTrackingProvider; enquanto não houver provedor contratado/configurado, o sistema opera com eventos internos e link oficial dos Correios como fallback.
Configuração atual:
SHIPPING_TRACKING_PROVIDER=manualpor padrão.- Para consultar Site Rastreio/Wonca, usar
SHIPPING_TRACKING_PROVIDER=siterastreioe configurarSITE_RASTREIO_API_KEY. - Se o provedor externo falhar ou ficar sem crédito, o pedido continua exibindo a timeline interna e o link oficial de rastreio como fallback.
- O provider pode ser trocado futuramente sem mudar tela ou regra de pedido.
Guia tecnico: docs/POSTAL_SHIPPING_TRACKING.md.
Guia SQL de manutencao:
docs/SQL_CONSULTAS_MANUTENCAO.md
A home principal nao depende mais de banners hardcoded para configuracao operacional.
- Tela:
Super Admin > Configuracao da Home. - Persistencia:
site_settings.key = 'home.config'. - Estrutura:
homeBannerscom ate 4 banners emarketingPopup. - Imagens: upload pelo backend para S3/public uploads.
- Fallback: se a configuracao nao existir ou estiver invalida, o app usa banners padrao temporarios para nao quebrar producao.
A ordem publica dos destinos turisticos e controlada no Super Admin em Destinos.
travel_destinations.sort_order: prioridade da cidade/destino na Home.hospitality_places.sort_order: prioridade de chales/pousadas dentro do destino.destination_listings.sort_order: prioridade geral de servicos/restaurantes no destino.destination_listing_hospitality_places.sort_order: prioridade do mesmo servico dentro de uma hospedagem especifica.
Use numeros menores para aparecer primeiro. O vinculo por hospedagem permite monetizar destaque por chale sem duplicar o cadastro do servico.
Distancias e rotas de chales, pousadas, servicos, restaurantes e lojas devem tratar lat/lng com nivel de confianca. CEP generico de cidade nao deve ser salvo ou exibido como ponto preciso.
Plano tecnico e fases de evolucao: docs/GEO_LOCATION_QUALITY_PLAN.md.
O backend concentra geocoding em backend/src/services/GeoLocationService.ts. A ordem padrao de provedores e geoapify,locationiq,photon,openstreetmap; Geoapify e LocationIQ so rodam quando as chaves GEOAPIFY_API_KEY e LOCATIONIQ_API_KEY forem configuradas. Photon e OpenStreetMap funcionam como fallback gratuito com cache/limite, mas local rural/turistico com CEP amplo ainda deve ter pin manual confirmado no Super Admin quando a precisao for baixa.
O parceiro aprovado pelo Super Admin recebe convite por e-mail para acessar /parceiro e manter dados públicos básicos do próprio cadastro.
Documentacao detalhada: docs/DESTINATION_PARTNER_PORTAL.md.
Arquivos principais:
backend/src/services/DestinationPartnerPortalService.tsbackend/src/controllers/DestinationPartnerPortalController.tsfrontend/src/pages/DestinationPartnerPortal.tsxfrontend/src/pages/DestinationPartnerActivate.tsx
O parceiro pode editar fotos, descrição, contato e endereço. Campos estratégicos continuam exclusivos do Super Admin, como ativo/inativo, destino, categoria, ordem/prioridade, destaque e vínculos.
Fluxos comerciais suportados:
- convite para assumir perfil já cadastrado sem duplicar chalé/pousada;
- reenvio de convite pelo Super Admin com novo link de ativação;
- CTA no portal para serviço/restaurante virar loja usando
/createpré-preenchido; após confirmar o e-mail da loja, o backend cria solicitação pendente no Super Admin e, na aprovação, desativa o serviço antigo e mostra a loja nos chalés/pousadas escolhidos. - proteção contra claim indevido: aprovação exige confirmação explícita, o Super Admin vê alerta de titularidade e o backend bloqueia segundo parceiro ativo no mesmo cadastro.
- checklist no portal para o parceiro completar imagem, descrição, contato, endereço e localização.
Os e-mails do sistema agora usam templates gerenciados no banco, com preview e teste pelo Super Admin.
- Tela:
Super Admin > E-mails e templates. - Persistencia:
email_templates,email_template_versions,email_send_logseemail_suppressions. - Catalogo base:
backend/src/utils/emailTemplateCatalog.ts. O backend cria os templates padrao sob demanda quando a tela ou um envio acessa a feature. - Layout padrao:
backend/src/utils/emailTemplateRenderer.ts, com logo oficial, preheader, conteudo HTML/texto e rodape. - Auditoria: cada envio/mock/falha/descadastro bloqueado fica registrado em
email_send_logs. - Descadastro: vale apenas para categoria
marketingcomallowUnsubscribe = true; e-mails de senha, OTP, seguranca, pagamento, conta e avisos internos continuam sendo enviados. - Rota publica:
/email/unsubscribe?token=.... - One-click unsubscribe de provedores:
/api/public/email/unsubscribe/one-click?token=.... - Rotas admin passam pelo BFF em
/api/admin/email/templatese/api/admin/email/suppressions.
Para variaveis em template, use {{VARIAVEL}} para conteudo escapado e {{{HTML_RAW}}} apenas quando o valor ja for HTML seguro gerado pelo backend.
A campanha permite dar acesso VIP/teste estendido para as primeiras lojas cadastradas sem alterar o fluxo manual de VIP do Super Admin.
Configuracao atual esperada em site_settings:
INSERT INTO site_settings ("key", "value") VALUES
('founder_vip_enabled', 'true'),
('founder_vip_store_limit', '50'),
('founder_vip_days', '90'),
('founder_vip_label', 'Campanha fundador - 3 meses de acesso VIP')
ON CONFLICT ("key") DO UPDATE
SET "value" = EXCLUDED."value",
updated_at = NOW();Comportamento:
- A campanha so atua no cadastro de loja nova.
- O acesso e aplicado como assinatura
TRIALestendida, nao comoplan_exempt. - O VIP manual do Super Admin continua em
store_settings.plan_exempt. - A atribuicao fica em
store_settings.acquisition_attribution.
MFA/TOTP usa:
mfa_settings: configuracao MFA por dono (USER,PLATFORM_ADMIN,CONDOMINIUM_USER).mfa_challenges: desafios de login temporarios.trusted_devices: dispositivos confiaveis.
O tempo de "lembrar aparelho" vem de variavel de ambiente do backend, nao de site_settings.
Tabelas de seguranca adicionais:
customer_security_blockscustomer_risk_eventsaccess_logspassword_resetsemail_verifications
Tokens ficam separados por publico:
- Cliente logado/guest:
customer_push_tokens. - Motoboy:
motoboy_push_tokens. - Usuario de loja:
store_user_push_tokens.
Sempre trate tokens como dado sensivel em logs e consultas; para manutencao, use left(token, 16) em vez de selecionar o token completo.
Fluxo recomendado por servico:
cp backend/.env.docker.example backend/.env.docker
cp apis/.env.docker.example apis/.env.docker
sh scripts/compose-dev-backend.sh
sh scripts/compose-dev-apis.sh
sh scripts/compose-dev-frontend.shStack completa quando a mudanca atravessar varios servicos:
sh scripts/compose-dev.shServicos locais principais:
- Frontend:
http://localhost:8080 - APIs BFF:
http://localhost:5000 - Backend:
http://localhost:4000 - Swagger backend:
http://localhost:4000/api/docs - PostgreSQL:
localhost:5432 - pgAdmin:
http://localhost:5050
Backend:
cd backend
yarn test
npm run buildFrontend:
cd frontend
npm run test:unit
npm run test:e2e
npm run buildAPIs BFF:
cd apis
npm run buildMudancas de schema/migration exigem tambem:
sh scripts/compose-dev-backend.sh
docker compose --env-file .env.dev ps backend
docker logs janocaminho-backend --tail 80
cd backend && npm run docs:schemaDeploy normal e feito por imagem GHCR.
Workflow de imagens:
.github/workflows/publish-ghcr.yml- Nome:
Publish Docker Images (GHCR)
Workflow aprovado:
.github/workflows/deploy-production.yml- Nome:
Deploy to EC2 (Approval)
Scripts preferenciais no servidor:
scripts/./deploy-release-api.sh
scripts/./deploy-release-apis.sh
scripts/./deploy-release-frontend.shRegra pratica:
- Mudou
backend/: rodarscripts/./deploy-release-api.sh. - Mudou
apis/: rodarscripts/./deploy-release-apis.sh. - Mudou
frontend/: rodarscripts/./deploy-release-frontend.sh. - Mudou mais de um servico: rodar os scripts dos servicos afetados ou aprovar o workflow de deploy com o escopo correto.
- Mudou script/compose/infra: pode precisar de
git pullno servidor antes do deploy.
Fallback legado, somente se o fluxo por imagem falhar:
scripts/./deploy-api.sh
scripts/./deploy-frontend.shGerar novo AAB somente quando houver mudanca nativa mobile, Capacitor, plugins, Manifest, Gradle, resources Android ou configuracao que exija novo binario.
Validacao esperada:
npm --prefix frontend run build
npm --prefix mobile run android:sync
mobile/android/gradlew.bat clean bundleReleaseAo gerar AAB:
- Incrementar
versionCode. - Atualizar
versionName. - Informar caminho do
.aabgerado. - Preparar texto curto de novidades para o Google Play Console.
O volume do Postgres e fixado por nome em docker-compose.yml:
POSTGRES_VOLUME_NAMEcom defaultedespetohub_postgres-data.
Em producao, docker-compose.prod.yml trata o volume como externo para reduzir risco de perda acidental.
Scripts relevantes:
scripts/pg-backup-rotate.sh: backup SQL gz com rotacao.scripts/backup-config.sh: backup de configuracoes runtime/SSM para S3 privado.
Exemplo de backup manual:
BACKUP_DIR=/home/ec2-user/backups/janocaminho MIN_INTERVAL_HOURS=4 KEEP_LATEST=1 sh /home/ec2-user/EdEspetoHub/scripts/pg-backup-rotate.sh- Orientacao para agentes:
AGENTS.md - Configuracao MCP:
docs/MCP_SETUP.md - Guia SQL:
docs/SQL_CONSULTAS_MANUTENCAO.md - Hub de destinos:
docs/DESTINATION_HUB.md - Entregas:
docs/DELIVERY.md - Jobs backend:
docs/BACKEND_JOBS.md - Guia de testes:
docs/TESTING_GUIDE.md - Servidor de producao:
docs/SERVIDOR_PRODUCAO.md - Contingencia, restore e migracao:
docs/DISASTER_RECOVERY_RUNBOOK.md - Schema HTML:
backend/docs/database-schema.html
- Nao refatorar rotas, autenticacao ou regras de negocio sem necessidade.
- Toda rota nova consumida pelo frontend precisa existir no BFF ou ser proxyada por ele.
- Toda regra de negocio persistente deve ficar no backend.
- Toda mudanca de schema deve atualizar
schema.sql,runMigrations.tsquando aplicavel, ebackend/docs/database-schema.html. - Toda alteracao de backend deve terminar com
cd backend && yarn test. - Antes de commitar, revisar diff e evitar incluir arquivos gerados de build-info sem necessidade.