Boilerplate moderno para APIs REST com Fastify e TypeScript.
Projetado como ponto de partida para novos serviços ou migração de sistemas legados. Com foco em camadas bem definidas, testes, segurança e automação desde o dia zero.
Este boilerplate suporta Bun e Node.js — escolha o que faz mais sentido para o seu time e remova o que não vai usar.
| Bun | Node.js | |
|---|---|---|
| Dev | dev:bun (hot reload nativo) |
dev:node (via tsx) |
| Build | build:bun (binário standalone) |
build:node (tsc + tsc-alias) |
| Docker | bun.Dockerfile (~133MB, distroless) |
node.Dockerfile (~192MB, Alpine) |
| Install | bun install |
npm install |
Vai usar apenas um runtime? Delete os arquivos do outro: o Dockerfile, o script de build correspondente em
package.json, e a devDependency do runtime que não vai usar (@types/bunou@types/node). O código da aplicação emsrc/funciona igual nos dois.
| Camada | Tecnologia |
|---|---|
| Framework | Fastify |
| Linguagem | TypeScript (strict mode) |
| Runtime | Bun / Node.js 22+ |
| Validação | Zod |
| Query Builder | Knex |
| Banco de Dados | PostgreSQL |
| Testes | Vitest |
| HTTP Client | Ky |
| Lint / Formatter | Biome |
| Logs | Pino |
| CI | GitHub Actions |
| CD | Docker |
| SAST | Semgrep |
- Bun >= 1.0 ou Node.js >= 22 (escolha um)
- Docker + Docker Compose (para banco local)
- PostgreSQL 16+ (via Docker ou instalação local)
- Clique em "Use this template" → "Create a new repository" no GitHub
- Clone o repositório criado
# 3. Instale as dependências
bun install # Com Bun
npm install # Com Node.js
# 4. Configure o ambiente
bun run scripts/setup-env.ts
# Ou copie manualmente: cp .env.example .env
# 5. Suba o PostgreSQL local
docker compose -f docker/docker-compose.local.yml up -d
# 6. Rode as migrations e seeds
bun run db:migrate:latest
bun run db:seed:run
# 7. Inicie o servidor
bun run dev:bun # Com Bun
npm run dev:node # Com Node.jsA API estará disponível em http://localhost:3003.
- Health check:
GET /api/status - Documentação:
GET /api/v1/(Scalar UI)
Clean Architecture pragmática — sem DDD, foco em camadas simples e bem definidas.
Client → HTTP → Route (Zod) → Handler → Service (Either) → Repository → Knex → PostgreSQL
| Camada | Responsabilidade |
|---|---|
| Routes | Mapeamento de endpoints + validação Zod na borda |
| Handlers | Orquestração: recebe request, chama service, devolve response |
| Services | Lógica de negócio. Retorna Either<AppError, T> — nunca lança exceções |
| Repositories | Toda interação com banco via Knex. Retorna dados puros |
src/
├── core/ # Domínio: erros, serviços, repositórios, utils
│ ├── errors/ # AppError, SchemaError, Either<L,R>
│ ├── repositories/ # Interfaces e implementações
│ ├── services/ # Lógica de negócio
│ └── utils/ # UUIDv7, helpers
├── infra/ # Infraestrutura: banco, logs, providers
│ ├── db/ # Knex config, migrations, seeds
│ ├── common/ # Constants, timezone
│ └── observability/ # Pino logger
└── main/ # Bootstrap: app, rotas, middleware
├── app.ts # Factory do Fastify (plugins, error handler)
├── routes/ # Endpoints organizados por domínio
└── infra/ # Error handler, graceful shutdown
dev:bun # Bun com hot reload nativo
dev:node # Node.js com tsxbuild:bun # Binário standalone via bun build --compile
build:node # TypeScript → JavaScript via tsc + tsc-aliastest # Executar uma vez (CI)
test:watch # Modo watch (desenvolvimento)
test:coverage # Com relatório de coberturalint # Biome em src/
lint:test # Biome em __tests__/docker:db:up # Sobe PostgreSQL + PgAdmin
docker:db:down # Derruba containers
db:migrate:latest # Roda migrations pendentes
db:migrate:rollback # Rollback da última batch
db:migrate:make # Cria nova migration
db:seed:run # Roda seedsdocker:build:bun # Build imagem Bun (~133MB)
docker:build:node # Build imagem Node (~192MB)
docker:test # Sobe ambas + PG via compose para comparaçãoServices retornam Either<AppError, T> — erros são valores, não exceções:
const result = await userService.getUser(id)
if (!result.success) {
// result.error: AppError com code e statusCode
return reply.status(result.error.statusCode).send(...)
}
// result.data: User
return result.dataSem container automático. Factory functions explícitas e type-safe:
export function makeUserService() {
const repo = new UserRepository(db)
return new UserService(repo)
}Schemas Zod validam antes do handler executar:
fastify.post('/', {
schema: { body: CreateUserSchema },
handler: async (request) => {
// request.body já está validado e tipado
}
})| Hook | O que roda |
|---|---|
pre-commit |
lint-staged (Biome nos arquivos staged) + tsc --noEmit |
commit-msg |
commitlint (Conventional Commits) |
pre-push |
Vitest (suíte completa) |
A cada push/PR, o pipeline roda sequencialmente:
Biome → tsc → bun audit → Semgrep SAST → Vitest
| Imagem | Base | Tamanho | Estratégia |
|---|---|---|---|
bun.Dockerfile |
distroless/cc-debian12 | ~133MB | Binário standalone compilado |
node.Dockerfile |
node:22-alpine | ~192MB | tsc + tsc-alias, user não-root |
main ─────────────────────────── produção (protegida, só via PR)
│
develop ──────────────────────── integração (protegida, só via PR)
│
├── feature/nova-funcionalidade
├── fix/corrige-bug
├── hotfix/correcao-urgente → PR para main E develop
└── chore/atualizacao-deps
<tipo>(escopo): descrição objetiva
feat(auth): adiciona middleware de validação de JWT
fix(repository): corrige query de busca por CPF
refactor(service): extrai cálculo de comissão para helper
Tipos: feat, fix, chore, refactor, test, docs, perf, ci
| Variável | Default | Descrição |
|---|---|---|
NODE_ENV |
development |
Ambiente da aplicação |
PORT |
3003 |
Porta HTTP |
HOST |
0.0.0.0 |
Host de bind |
DATABASE_URL |
- | Connection string PostgreSQL |
TZ |
America/Sao_Paulo |
Timezone IANA |
DEBUG |
false |
Logs de debug |
LOG_PRETTY |
false |
Formatação legível nos logs |
SHOW_ROUTES |
false |
Lista rotas no startup |
Veja .env.example para a lista completa.
| Documento | Conteúdo |
|---|---|
| docs/testing.md | Filosofia de testes, padrões de mock, edge cases, guia para iniciantes |
| docs/ci.md | Pipeline CI, cada etapa explicada, como rodar localmente |
| docs/cd.md | Dockerfiles, build system, teste local com compose |
| CLAUDE.md | Guia completo do projeto — arquitetura, princípios, regras |