Pular para o conteúdo principal

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 em theme/fonts.ts)
  • app/config/routes/paths.ts — URLs das páginas
  • app/config/layout/composition.ts — Composição do layout
  • app/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?

  1. Clone seu repositório fork
  2. Configure o .npmrc com o registry e o token — veja Prerequisites
  3. Instale as dependências:
    pnpm install
  4. Crie os dois arquivos de variáveis de ambiente a partir do template:
    cp .env.example .env
    cp .env.example .dev.vars
  5. Preencha as variáveis obrigatórias (principalmente API_BASE_URL e ORIGIN_DOMAIN)
  6. 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.comminhamarca-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:

  1. Crie o arquivo de página em app/routes/:

    // app/routes/minha-pagina.tsx
    export default function MinhaPagina() {
    return <div>Minha página customizada</div>;
    }
  2. 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ó chama buildRoutes() — a árvore em si é montada no app/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.

cuidado

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.)