Pular para o conteúdo principal

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:

PrefixoUsoGera release no core?
featNova funcionalidademinor
fixCorreção de bug✅ patch
refactorMudança de código sem alterar comportamento✅ patch
perfMelhoria de performance✅ patch
revertReversão de commit anterior✅ patch
docsDocumentação
testTestes
styleFormatação (sem mudança de lógica)
choreManutenção, deps
buildSistema de build, deps de build
ciConfiguraçã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, featminor, 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-lengthoff (sem limite de tamanho do título)
  • body-max-line-length200

Git hooks (Husky)

Três hooks, em ambos os repos. Os pre-push são diferentes entre base e core.

Hookfront-web-basefront-cactus-core
pre-commitpnpm lint-stagedbiome check --write --no-errors-on-unmatched em *.{js,jsx,ts,tsx,json,css}pnpm lint-staged → mesmo comando em *.{ts,tsx}
commit-msgpnpm exec commitlint --edit "$1"idem
pre-pushbiome check nos arquivos alterados → pnpm typecheck:ciCACTUS_FORCE_REGISTRY=1 pnpm vitest run --changed --passWithNoTestspnpm 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
  • any deve ser evitado — use unknown quando o tipo é desconhecido
  • Tipos compartilhados ficam em @cactus-agents/types

Dois tsconfigs no base

ArquivoResolve @cactus-agents/* deUsado por
tsconfig.jsonsource do core clonado, com fallback pro node_moduleseditor, pnpm typecheck, Vite, Vitest
tsconfig.ci.json node_modulespnpm 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:

PermitidoProibido
Objetos de config exportadosHooks (use*)
Tipos e interfaces de configParsers e helpers de lógica
Re-exports de tipos do SDKDados 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.ts ou *.test.tsx
  • Testes ficam em pasta tests/ ou ao lado do arquivo

Testes end-to-end vivem num repo separado — ver Testes E2E.