FAQ
Geral
O que é um "fork"?
Um fork é a sua própria cópia completa do template base do Cactus. Você tem total liberdade para customizá-lo — criar componentes, adicionar páginas, mudar estilos, redesenhar o layout, etc.
Por onde começo a customizar?
Os pontos de entrada mais comuns são:
app/config/theme/colors.ts— Cores e tokens do tema (fontes ficam emtheme/fonts.ts)app/config/routes/paths.ts— URLs das páginasapp/config/layout/composition.ts— Composição do layoutapp/router/routes.ts— A árvore de rotas, para adicionar ou remover páginas
Se o seu fork serve mais de uma marca, sobrescreva esses mesmos caminhos dentro de overrides/<sua-marca>/ em vez de editar o base — veja a seção de overrides abaixo.
Mas você não está limitado a esses arquivos. Pode modificar qualquer arquivo, criar novos componentes, adicionar bibliotecas — o fork é completamente seu.
Posso adicionar páginas customizadas?
Sim. Crie um novo arquivo em app/routes/ e registre-o na árvore de rotas, em app/router/routes.ts. Você também pode criar componentes, hooks e stores customizados. Consulte Customização de Rotas.
O que não posso modificar?
A única coisa que você deve evitar modificar diretamente são os pacotes @cactus-agents/* — eles são dependências npm atualizadas via pnpm update. Se precisar de algo que o SDK ainda não suporta, entre em contato com o time Cactus.
SDK e dependências
Como atualizo o SDK (@cactus-agents/*)?
Execute o seguinte comando na raiz do projeto:
pnpm update "@cactus-agents/*"
As aspas em "@cactus-agents/*" são obrigatórias — sem elas o shell tenta expandir o glob antes do pnpm receber o argumento, e no zsh o comando aborta.
Isso atualiza todos os pacotes do SDK para a versão mais recente compatível com os ranges definidos no package.json. Após atualizar, rode pnpm typecheck e teste localmente antes de fazer deploy.
Para atualizar para uma versão específica:
pnpm update @cactus-agents/api-client@<versão>
Consulte SDK Updates para o guia completo.
Meu fork importa @cactus-agents/auth, /user ou /wallet e o install falha
Esses três pacotes foram removidos e unificados em @cactus-agents/accounts. Não existem mais no registry, então nenhum pnpm install consegue resolvê-los. A migração é quase toda troca de caminho de import, com quatro símbolos renomeados. Siga Migração para accounts.
Como instalo e testo localmente?
- Clone seu repositório fork
- Configure o
.npmrccom o registry e o token — veja Prerequisites - Instale as dependências:
pnpm install
- Crie os dois arquivos de variáveis de ambiente a partir do template:
cp .env.example .envcp .env.example .dev.vars
- Preencha as variáveis obrigatórias (principalmente
API_BASE_URLeORIGIN_DOMAIN) - Inicie o servidor de desenvolvimento:
pnpm dev
O servidor sobe em http://localhost:5173, com SSR incluído — o Vite roda o servidor de renderização através do proxy de desenvolvimento da Cloudflare. Não há uma segunda porta para abrir.
Para exercitar o runtime real de Workers, o mesmo que produção usa, faça o build antes e rode o preview:
pnpm build
pnpm preview
Esse sim sobe em http://localhost:8787 (default do Wrangler) e depende de um pnpm build anterior.
:::tip Por que dois arquivos de env?
.dev.vars é lido pelo runtime de Workers que faz o SSR e .env é lido pelo Vite. Nenhum dos dois lê o arquivo do outro, então uma variável que existe só em um está faltando no outro lado. Ambos são gitignored.
Não existe .dev.vars.example no repositório — o único template versionado é o .env.example, e ele serve para os dois arquivos.
:::
Tema e customização visual
Como customizo as cores e o tema?
Edite o arquivo app/config/theme/colors.ts (ou a versão no seu diretório de overrides). Ele exporta themeColors, um objeto aninhado: os tokens globais ficam no nível de cima e cada superfície da interface tem seu próprio grupo aninhado.
// overrides/<sua-marca>/app/config/theme/colors.ts
export const themeColors = {
// tokens globais, sem prefixo
primary: "#FF5500",
secondary: "#1A1A2E",
// ...
// grupos por superfície
header: {
// ...
},
sidebar: {
// ...
},
};
Fontes são um arquivo separado: app/config/theme/fonts.ts, que exporta themeFonts. Não existe uma chave fonts dentro de themeColors.
Os tokens são aplicados via variáveis CSS e Tailwind. Consulte a documentação de Theming para a estrutura completa e a lista de grupos e tokens disponíveis.
Como funciona o sistema de overrides por marca?
Cada marca tem seu próprio diretório em overrides/<brand-key>/, espelhando a árvore app/. Quando um arquivo existe ali, o build usa ele no lugar do arquivo base.
Estrutura típica de overrides:
overrides/
└── minhamarca-com/
└── app/
└── config/
├── routes/
│ └── paths.ts ← URLs customizadas
├── theme/
│ ├── colors.ts ← Cores e tokens
│ └── fonts.ts ← Fontes
├── layout/
│ └── composition.ts ← Composição do layout
└── features/
└── features.ts ← Feature flags
O brand-key não vem de uma variável que você define: ele é derivado do ORIGIN_DOMAIN, normalizando o domínio (minhamarca.com → minhamarca-com). Localmente o ORIGIN_DOMAIN é lido do .dev.vars; em produção, do ambiente do worker. Arquivos ausentes no diretório de override usam o valor padrão do template.
:::caution Override substitui o arquivo inteiro
O override é substituição de arquivo, não merge campo a campo. Se você sobrescreve app/config/features/features.ts, o seu arquivo tem que declarar todas as flags que o arquivo base declara — o que você omitir chega como undefined, não cai no valor do base.
Por isso, quando o template ganha um campo novo em um config que você sobrescreve, você precisa propagar esse campo para o seu override. A única exceção é app/config/layout/composition.ts, que é mesclado via defineLayoutConfig().
:::
Rotas e navegação
Como adiciono novas rotas?
Para adicionar uma página nova ao seu fork:
-
Crie o arquivo de página em
app/routes/:// app/routes/minha-pagina.tsxexport default function MinhaPagina() {return <div>Minha página customizada</div>;} -
Registre a rota na árvore de rotas, em
app/router/routes.ts:route("/minha-pagina", "routes/minha-pagina.tsx")O ponto de entrada que o React Router lê é o
app/routes.ts, mas ele só chamabuildRoutes()— a árvore em si é montada noapp/router/routes.ts, e é lá que você mexe.
Para páginas que fazem parte do layout principal (header/footer/providers), aninhe dentro do layout('routes/_layout.tsx', [...]).
Como renomeio as URLs das páginas existentes?
Crie ou edite overrides/<sua-marca>/app/config/routes/paths.ts com as URLs customizadas. Consulte Customização de Rotas para o exemplo completo e a lista de todas as chaves disponíveis.
Gamificação (Smartico)
Como configuro a gamificação com Smartico?
O módulo de gamificação já vem ligado no template (enabled: true, provider smartico), com as rotas /vip, /vip/missions, /vip/tournaments etc. ativas. O que falta para ele funcionar de fato são duas coisas específicas da sua marca:
1. Secret do servidor
Configure SMARTICO_SALT_KEY como secret do worker (ou no .dev.vars localmente). Essa chave gera o hash do usuário no servidor — nunca a exponha no client.
2. Chaves da marca no config
As chaves de identificação da marca no Smartico vêm vazias no template. Preencha-as no seu override de app/config/gamification/gamification.ts, que exporta gamificationConfig:
// overrides/<sua-marca>/app/config/gamification/gamification.ts
import type { GamificationConfig } from "@cactus-agents/gamification";
export const gamificationConfig: GamificationConfig = {
enabled: true,
provider: "smartico",
smartico: {
libraryUrl: "/proxy/smartico.js",
labelKey: "SUA_LABEL_KEY",
brandKey: "SUA_BRAND_KEY",
visitorLabelKey: "",
visitorBrandKey: "",
allowLocalhost: true,
enableDebug: false,
allowPush: false,
},
naming: {
programName: "ClubVip",
coinsName: "VipCoins",
},
modules: {
// ...
},
};
:::caution O override precisa ser completo
Como todo override, esse arquivo substitui o do template. Copie o app/config/gamification/gamification.ts do base inteiro e edite o que interessa — inclusive o bloco modules, senão os módulos chegam como undefined. Nem todos vêm ligados por padrão: alguns módulos são enabled: false no template.
:::
Para customizar as URLs, use as chaves com prefixo gamification.* no seu app/config/routes/paths.ts.
Consulte Gamificação para o detalhamento dos módulos e das opções.
SMARTICO_SALT_KEY é uma chave secreta — configure via wrangler secret put SMARTICO_SALT_KEY ou pelo painel do Cloudflare, nunca commitada no repositório.
Técnico
Por que preciso de .dev.vars e .env?
.dev.vars é lido pelo runtime de Workers que faz o SSR e .env é lido pela ferramenta de build (Vite). Ambos são necessários localmente, com o mesmo conteúdo — crie os dois a partir do .env.example.
Em produção nenhum dos dois existe: valem as variáveis configuradas no worker do Cloudflare.
Como atualizo a lógica de negócio?
Execute pnpm update "@cactus-agents/*" para obter os pacotes mais recentes. Consulte SDK Updates.
Onde configuro variáveis de ambiente em produção?
No worker do Cloudflare. Parte das variáveis é injetada automaticamente pelo pipeline de deploy e não deve ser configurada à mão. Consulte Ambiente de deploy para a divisão entre o que você define, o que é secret e o que é injetado.
Fiz push e nada foi publicado. Por quê?
Deploy automático em push é opt-in por ambiente e vem desligado por padrão. Além disso, cada ambiente publica uma branch fixa, que não é necessariamente a main. Consulte Ambiente de deploy.
Suporte
Entre em contato com o time Cactus para:
- Tokens de acesso ao GitHub Packages
- Credenciais de API
- Assistência com deploy
- Ser incluído no time de deployers, quando o seu ambiente exige isso para deploy manual
- Mudar qual branch um ambiente publica
- Reportar bugs
- Solicitar novos ambientes (staging, homolog, etc.)