02 — Bootstrap
02 — Bootstrap
Do repositório vazio até
npm run devservindo a aplicação. Siga na ordem; cada passo assume o anterior. Ao final, o checklist "Fundação" de 00-INDICE.md deve estar todo marcado.
1. Node
O projeto exige Node ≥ 24 (última LTS). Fixe a versão no repositório para que os git hooks consigam validá-la sem depender do shell do dev.
// .node-version
24.19.0
Com fnm:
fnm install 24 && fnm use
Armadilha conhecida. Se o
fnmnão estiver avaliado no perfil do shell (fnm env), o Node ativo pode ser uma versão antiga e osetEnvironment.jsfalha emprocess.loadEnvFile. GUIs de Git tipicamente não herdam o perfil — por isso opre-commitvalida a versão explicitamente (ver 14).
2. Esqueleto
npm create vite@latest . -- --template react-ts
Depois remova o que o template traz e não usamos: src/App.css, src/index.css,
src/assets/. Mantenha eslint.config.js — o próprio scaffold do Vite já gera flat config,
e é isso que este guia usa (ver 14); você vai reescrever o conteúdo,
não trocar de formato.
3. Dependências
Sem @latest em nada. npm i sem versão instala o mais novo do registro, o que pode não ter sido
verificado ainda contra este guia — hoje só o TypeScript está deliberadamente atrás do latest
(01). Pin explícito em tudo:
npm i @curio/client@^1.4.2 @emotion/react@^11.14.0 @emotion/styled@^11.14.1 @hookform/resolvers@^5.9.1 @mui/icons-material@^9.3.1 @mui/material@^9.3.1 @mui/x-date-pickers@^9.11.0 @tanstack/react-query@^5.101.4 @tanstack/react-query-devtools@^5.101.4 date-fns@^4.4.0 react@^19.2.0 react-dom@^19.2.0 react-hook-form@^7.85.0 react-router-dom@^7.18.2 zod@^4.4.3
npm i -D @eslint/js@^10.0.1 @types/node@^26.2.0 @types/react@^19.2.2 @types/react-dom@^19.2.4 @typescript-eslint/eslint-plugin@^8.67.0 @typescript-eslint/parser@^8.67.0 @vitejs/plugin-react@^6.0.5 eslint@^10.8.1 eslint-config-prettier@^10.1.8 eslint-plugin-react-hooks@^7.1.1 eslint-plugin-react-refresh@^0.5.4 globals@^17.11.0 husky@^9.1.7 lint-staged@^17.3.0 prettier@^3.9.6 typescript@^6.0.3 vite@^8.2.1 vite-plugin-checker@^0.14.5
Versões exatas em 01-STACK-E-DECISOES.md — essa tabela é a fonte de verdade; se as duas divergirem, ela vence.
@types/node@^26com Node>=24em runtime é uma folga deliberada. A linha 26.x dos tipos é a mais recente disponível hoje; a linha 24.x parou em24.13.3(sem novas patches). Não houve conflito detsc/build ao testar essa combinação de verdade, mas se aparecer algum tipo de API que não existe no Node 24 real, prenda de volta em^24.
4. package.json
{
"name": "nome-do-projeto",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"env:dev": "node ./setEnvironment.js dev",
"env:homolog": "node ./setEnvironment.js homolog",
"env:prod": "node ./setEnvironment.js prod",
"dev": "npm run env:dev && vite",
"start": "npm run env:dev && vite",
"start:homolog": "npm run env:homolog && vite",
"start:prod": "npm run env:prod && vite",
"build": "npm run lint && npm run env:prod && tsc && vite build",
"build:homolog": "npm run env:homolog && tsc && vite build",
"preview": "vite preview",
"lint": "eslint . --report-unused-disable-directives --max-warnings 0",
"format": "prettier --write \"src/**/*.{ts,tsx,css,json,md}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx,css,json,md}\"",
"prepare": "husky"
},
"lint-staged": {
"src/**/*.{ts,tsx}": [
"eslint --fix --report-unused-disable-directives --max-warnings 0",
"prettier --write"
],
"**/*.{json,css,scss,md,html,yml,yaml}": ["prettier --write"]
},
"engines": { "node": ">=24.0.0" }
}
preparedepende do layout do repositório. Acima está a forma para um repositório de módulo único (projeto web na raiz). Se o web for submódulo de um monorepo, o script muda de forma — algo como"prepare": "cd ../.. && husky caminho/do/modulo/.husky", apontando para a raiz real do repositório git. Se o projeto novo for um módulo dentro de um monorepo, replique essa forma — ver 14.
5. vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { resolve } from "path";
import checker from "vite-plugin-checker";
export default defineConfig({
plugins: [
react(),
checker({
typescript: true,
overlay: { initialIsOpen: false, position: "tl" },
terminal: true
})
],
define: {
// curio espera globals de node; browser nao tem
global: "globalThis",
"process.env": {}
},
resolve: {
alias: {
"@": resolve(import.meta.dirname, "./src"),
"@components": resolve(import.meta.dirname, "./src/components"),
"@pages": resolve(import.meta.dirname, "./src/pages"),
"@hooks": resolve(import.meta.dirname, "./src/hooks"),
"@utils": resolve(import.meta.dirname, "./src/utils"),
"@types": resolve(import.meta.dirname, "./src/types"),
"@api": resolve(import.meta.dirname, "./src/api"),
"@context": resolve(import.meta.dirname, "./src/context"),
"@theme": resolve(import.meta.dirname, "./src/theme")
}
},
server: { port: 5000, open: true },
build: { outDir: "dist", sourcemap: true }
});
O bloco define não é opcional: @curio/client referencia global e process.env, que não
existem no browser. Sem ele a aplicação quebra em runtime no primeiro request.
6. tsconfig.json
{
"compilerOptions": {
"types": ["vite/client"],
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"],
"@pages/*": ["./src/pages/*"],
"@hooks/*": ["./src/hooks/*"],
"@utils/*": ["./src/utils/*"],
"@types/*": ["./src/types/*"],
"@api/*": ["./src/api/*"],
"@context/*": ["./src/context/*"],
"@theme/*": ["./src/theme/*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
Regra: todo alias novo entra nos dois arquivos. Só no
vite.config.ts→ o build passa e o editor reclama. Só notsconfig.json→ o editor aceita e o build quebra.
7. Configuração de ambiente
Crie setEnvironment.js, config/*.json e .env.example conforme
04-AMBIENTES-E-CONFIG.md. Sem isso, npm run dev falha no primeiro passo.
8. .gitignore
# .gitignore
node_modules
dist
dist-ssr
*.local
.env
# gerado por setEnvironment.js — nao versionar
public/config.json
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Harness (Claude Code) — estado local, nao versionado
harness/state/*.json
harness/state/*.md
!harness/state/_examples/
harness/handoffs/*.md
!harness/handoffs/_examples/
harness/user_preferences.md
9. Ponto de entrada
index.html, src/main.tsx e src/App.tsx conforme
03-ESTRUTURA-DE-PASTAS.md.
10. Hooks reutilizáveis
Copie os doze hooks/módulos de 21-CATALOGO-DE-HOOKS.md para src/hooks/, mais
src/utils/useCaseTriggersLogger.ts, e crie o src/hooks/index.ts.
Faça isso agora, não na primeira tela: useCurioMutation e useUseCaseControls são a única forma
suportada de chamar um caso de uso (06), e useAuthQuery é exigido pelo
AuthProvider (05).
11. Tela de exemplo (placeholder)
Antes de existir qualquer contrato real com o backend, crie uma tela Exemplo seguindo exatamente
a estrutura de 17-PRIMEIRA-TELA.md, mas com todo id de caso de uso e nome
de RM como placeholder explícito ("SUBSTITUA_USE_CASE_ID", "RM_SUBSTITUA_SALVAR", ...) — nunca
invente um valor plausível que pareça real.
Isso é obrigatório, não opcional, por dois motivos:
- É a única forma de provar, com
tsc+lint+buildreais, que a cadeia completa (service/constants.ts→service/interfaces.ts→service/hooks.ts→Page.tsx→UseCaseManager→paths.ts/routes.ts/menuTree.ts) compila e roteia antes de qualquer feature de negócio existir. - Dá ao time um exemplo executável para copiar, em vez de reconstruir o padrão de memória a cada tela nova.
Nomeie a entidade de forma que não possa ser confundida com domínio real — Exemplo, não uma
entidade do produto. Comente no topo do arquivo que é placeholder e que deve ser removido/substituído
quando a primeira tela de negócio for criada. Registre a rota e o item de menu normalmente
(09, 10) — a tela precisa ser navegável e
verificável no browser, não só compilar.
12. Qualidade e harness
13. Verificar
npm run lint && npx tsc --noEmit && npm run dev
Os três precisam passar. Se npm run dev abrir a página mas o console mostrar erro de global is not defined, o bloco define do passo 5 está faltando.