Visão Geral da Arquitetura
Plataforma multi-tenant de apostas esportivas (Cactus Gaming). ~30 sites clientes, cada um com seu fork do template base.
Repositórios
| Repo | Descrição |
|---|---|
front-cactus-core | SDK TypeScript — pacotes @cactus-agents/* (monorepo) |
front-web-base | Template React Router v7 (SSR / Cloudflare Workers) |
front-cactus-docs | Esta documentação (Docusaurus) |
front-web-{marca} | Forks de marca (ex: front-web-vera-bet-br) |
front-web-panel | Painel admin (vault + deploys) |
front-ops | Reusable workflow de deploy + allowlist + vault de envs |
Stack
| Camada | Tecnologia |
|---|---|
| Framework | React Router v7 (SSR nativo no Cloudflare Workers) |
| Build/bundler | Vite (via React Router v7) |
| Styling | Tailwind CSS v3 + CSS custom properties para tokens de tema por cliente |
| State (client) | Zustand (13 stores: auth, layout, brand, gamification, kyc, validationSteps, validationRuntime, passwordValidation, games, payments, wallet, user, accountMenu) |
| State (server) | React Router loaders |
| i18n | i18next + react-i18next (traduções) + @cactus-agents/i18n |
| Ícones | lucide-react |
| Fonte | @fontsource/montserrat |
| Flags | country-flag-icons |
| Linter/formatter | Biome (todos os repos) |
| Testes | Vitest + React Testing Library |
| Pre-commit | Husky + lint-staged → biome check --write |
| Commits | Conventional Commits (commitlint) |
| Package manager | pnpm (enforced) |
| Node | >=20.14.0 (recomendado: 22.18.0) |
SDK — Pacotes @cactus-agents/*
| Pacote | Descrição |
|---|---|
api-client | ApiClient base (fetch, headers, auth) |
auth | AuthService (login, register, logout, profile) |
brand | BrandConfig (appearance, features, settings) |
country-config | Configuração por país (moeda, locale, validações) |
i18n | Internacionalização (setup i18next, namespaces) |
games | GamesService (home, categorias, providers, busca) |
gamification | Smartico SDK integration |
kyc | KYC (operadores, iframe, polling) |
payments | PaymentsService (deposit, withdraw, providers) |
sports | SportsService (Altenar, Betby) |
types | Tipos compartilhados |
user | UserService (perfil, segurança, limites) |
utils | Utilitários compartilhados |
validations | Validações (modules, contexts, runtime) |
wallet | WalletService (saldo, transações, rollover) |
Deploy
- SSR via Cloudflare Workers (React Router v7)
- Assets estáticos → Cloudflare R2
- 1 Worker por ambiente (SSR + static, sem api-proxy separado)
- Deploy centralizado via reusable workflow no
front-ops - Forks chamam
cactus-agents/front-ops/.github/workflows/deploy.yml@main - Allowlist em
config/allowlist.ymlmapeia repo → brand → environments → worker_name - Secrets de deploy (Cloudflare) são org secrets com acesso restrito
Pacotes privados
- GitHub Packages como registry privado
- Token de leitura por cliente (acesso apenas a
@cactus-agents/*, sem código-fonte)
Modelo de fork
O fork é uma cópia completa do front-web-base. O cliente tem liberdade total para personalizar: criar componentes, páginas, regras, redesenhar o tema inteiro.
Pontos rápidos de customização (já preparados no template):
app/config/theme.config.ts— paleta de coresapp/config/routes.config.ts— árvore de rotasapp/config/layout.config.ts— componente de layout
Mas o cliente não está limitado a esses arquivos. Pode modificar qualquer coisa no fork.
Única restrição: não alterar pacotes @cactus-agents/* diretamente — eles são dependências npm atualizáveis via pnpm update.
Decisões técnicas
| Decisão | Motivo |
|---|---|
| Cookie HttpOnly para JWT | Token não fica acessível no browser JS; leitura e validação acontecem no server. |
| AuthService singleton client-side | Um único ApiClient pro browser, separado do SSR. |
| Zustand sem persist para auth | Store mantém apenas user/userInfo/authModal/hydrated; estado inicial vem do loader SSR. |
| 13 Zustand stores separadas | Cada domínio tem sua store isolada. Evita store monolítica e facilita code-splitting. |
| Modais controlados por Zustand | authModal: 'login' | 'register' | null. Qualquer componente abre/fecha. |
| EnvProvider separado do BrandProvider | clientEnv (API_BASE_URL etc.) precisa existir antes de qualquer chamada API client-side. |
| Fork = cópia completa + liberdade total | Config files são atalhos rápidos, não limites. Cliente pode personalizar o que quiser. |
| Biome em vez de ESLint | Mais rápido, config única pra lint + format, sem plugins. |
| i18next para i18n | Biblioteca consolidada com suporte a namespaces, interpolação e pluralização. |