Convenções de Código
Linter & Formatter
Todos os repositórios usam Biome (substitui ESLint + Prettier). A versão exata
está no devDependencies de cada repo (@biomejs/biome) — ela sobe a cada poucas
semanas, então não confie em número decorado.
pnpm lint # biome lint
pnpm check # biome check (lint + format)
pnpm format # biome format --write
Configuração em biome.json:
- Indent: spaces (2)
- Line width: 100
- JSX quote style: double
- Organize imports: habilitado
Commits
Padrão Conventional Commits, validado por commitlint. Os dois repos usam
@commitlint/config-conventional, que aceita 11 tipos:
| Prefixo | Uso | Gera release no core? |
|---|---|---|
feat | Nova funcionalidade | ✅ minor |
fix | Correção de bug | ✅ patch |
refactor | Mudança de código sem alterar comportamento | ✅ patch |
perf | Melhoria de performance | ✅ patch |
revert | Reversão de commit anterior | ✅ patch |
docs | Documentação | — |
test | Testes | — |
style | Formatação (sem mudança de lógica) | — |
chore | Manutenção, deps | — |
build | Sistema de build, deps de build | — |
ci | Configuração de CI | — |
feat: add login modal
fix: handle 401 on profile fetch
refactor: extract brand transform helpers
perf: defer marquee hydration on low-end devices
docs: update auth flow documentation
chore: bump @cactus-agents/accounts to 2.9.0
:::caution O tipo do commit decide o release do SDK
No front-cactus-core, o job changeset do ci-release.yml faz o parse das
mensagens de commit e deriva o bump: ! antes do : → major, feat →
minor, o resto dos releasable → patch. Um push só com chore/ci/docs
não publica nada. Detalhes em Workflow de Release.
:::
Regras customizadas em commitlint.config.ts (idênticas nos dois repos):
header-max-length→ off (sem limite de tamanho do título)body-max-line-length→ 200
Git hooks (Husky)
Três hooks, em ambos os repos. Os pre-push são diferentes entre base e
core.
| Hook | front-web-base | front-cactus-core |
|---|---|---|
pre-commit | pnpm lint-staged → biome check --write --no-errors-on-unmatched em *.{js,jsx,ts,tsx,json,css} | pnpm lint-staged → mesmo comando em *.{ts,tsx} |
commit-msg | pnpm exec commitlint --edit "$1" | idem |
pre-push | biome check nos arquivos alterados → pnpm typecheck:ci → CACTUS_FORCE_REGISTRY=1 pnpm vitest run --changed --passWithNoTests | pnpm lint && pnpm check && pnpm build && pnpm test |
:::info Por que o pre-push do base força o registry
pnpm typecheck:ci usa tsconfig.ci.json, que resolve @cactus-agents/* só de
node_modules — não do source do front-cactus-core clonado ao lado. Idem para
CACTUS_FORCE_REGISTRY=1 nos testes.
O objetivo é deliberado: o push tem que validar o que o package.json
declara. Uma edição local no core que ainda não foi publicada e bumpada deve
falhar aqui, senão o push manda pra main um commit que funciona na sua máquina e
quebra em CI, prod e na máquina de todo mundo.
O pnpm typecheck local continua source-first, para feedback rápido no editor.
:::
Os hooks do base carregam o nvm antes de rodar, para funcionar em clientes git
GUI (VS Code, etc.) onde o PATH não inclui ~/.nvm/*/bin.
Quality gate
No front-web-base, pnpm quality roda o mesmo conjunto que o CI:
pnpm quality
# = pnpm lint && pnpm check && pnpm check:dev-vars && pnpm typecheck && pnpm test
check:dev-vars (scripts/sync-dev-vars-cache-policy.mjs) verifica se a política
de cache do .dev.vars local está sincronizada com o front-ops. É parte do gate
— rode pnpm check:dev-vars --write para sincronizar.
:::caution pnpm quality ≠ o job quality do CI
O CI roda typecheck:ci (registry-resolved) e pnpm test com
CACTUS_FORCE_REGISTRY=1; o pnpm quality local roda typecheck (source-first)
e testes sem a flag. Para reproduzir o CI exatamente, use o pre-push.
:::
No front-cactus-core não há quality; o equivalente é
pnpm lint && pnpm check && pnpm build && pnpm test (o que o pre-push faz).
Por pacote:
cd packages/games && npx vitest run
Package manager
pnpm é obrigatório em todos os repos — não use npm ou yarn.
Os dois repos declaram hoje:
{
"engines": {
"node": ">=24.0.0",
"pnpm": ">=10.0.0"
}
}
:::info engines vs .nvmrc
O .nvmrc do workspace pina 24.14.1, que é a versão que os devs e o setup
usam. O engines.node dos repos é mais frouxo (>=24.0.0) — ele é um piso, não a
versão-alvo. Instale a do .nvmrc.
:::
O monorepo SDK (front-cactus-core) também usa Turborepo para orquestração de
builds e cache de tarefas.
TypeScript
- Strict mode habilitado em todos os pacotes
- Tipos explícitos em exports públicos
anydeve ser evitado — useunknownquando o tipo é desconhecido- Tipos compartilhados ficam em
@cactus-agents/types
Dois tsconfigs no base
| Arquivo | Resolve @cactus-agents/* de | Usado por |
|---|---|---|
tsconfig.json | source do core clonado, com fallback pro node_modules | editor, pnpm typecheck, Vite, Vitest |
tsconfig.ci.json | só node_modules | pnpm typecheck:ci — CI e pre-push |
Ao adicionar um pacote novo no core, rode node scripts/regen-tsconfig-paths.mjs
no base para atualizar os dois.
Estrutura de pacotes (@cactus-agents/*)
Cada pacote segue:
packages/nome/
├── src/
│ ├── index.ts # Exports públicos
│ ├── *.ts # Implementação
│ └── types.ts # Tipos do pacote
├── tests/
│ └── *.test.ts
├── package.json
├── tsconfig.json
├── tsup.config.ts # Build: ESM + CJS + .d.ts
└── vitest.config.ts
Regra: app/config no template
A pasta app/config no template (front-web-base) deve conter somente dados
estáticos de configuração por brand:
| Permitido | Proibido |
|---|---|
| Objetos de config exportados | Hooks (use*) |
| Tipos e interfaces de config | Parsers e helpers de lógica |
| Re-exports de tipos do SDK | Dados globais (país, DDI, currency) |
Hooks devem ficar em app/hooks/. Dados globais (catálogo de países, DDI,
mapeamento moeda→país) vêm exclusivamente do SDK @cactus-agents/*.
app/config/ é organizada em subpastas semânticas por domínio, e os imports
usam o path completo sem sufixo .config — ex. ~/config/theme/colors,
~/config/widgets/sidebar-buttons. A lista viva de domínios é o próprio
diretório app/config/.
Testes
- Vitest para todos os pacotes e apps
- React Testing Library para testes de componente
- Nome do arquivo:
*.test.tsou*.test.tsx - Testes ficam em pasta
tests/ou ao lado do arquivo
Testes end-to-end vivem num repo separado — ver Testes E2E.