Skip to content

ADR-0015: Code Quality Tooling — ESLint + Prettier ⚠️ SUPERSEDED

Status: This ADR has been superseded. The project migrated from ESLint + Prettier to Biome (single-tool linter + formatter) on 2026-06-25. See biome.json at repo root for the current configuration. This document is kept for historical reference.

Context

The Neemias monorepo (pnpm workspace) lacked automated code quality checks for JavaScript/TypeScript code. While markdownlint existed for documentation and Husky ran tests on pre-commit, there was no linter or formatter for the primary codebase (~200+ source files across app/, workers/, packages/).

The CI pipeline (deploy.yml) only triggered on version tags; PRs and push to main had no automated quality gates.

Decision

We introduce ESLint (static analysis) + Prettier (formatting) as the code quality foundation, deferring Turborepo (task orchestration + caching) to a future round.

Tool selection

ConcernChoiceWhy
LinterESLint 10 (flat config)Industry standard, TypeScript-native via typescript-eslint, ESLint 10 is the latest major with stable flat config
TypeScript rulestypescript-eslint (tseslint.configs.recommended)First-class eslint.config.js integration, @typescript-eslint rules tuned for strictness
React rules@eslint-react/eslint-pluginESLint 10-compatible replacement for eslint-plugin-react (which broke on ESLint 10). Includes recommended rules + React Hooks checks built-in
Vite HMR safetyeslint-plugin-react-refreshWarns when components are exported in ways that break React Refresh HMR
FormatterPrettier 3Zero-config, widely adopted, eslint-config-prettier disables conflicting ESLint rules
Pre-commitHusky + lint-stagedRuns ESLint --fix + Prettier --write on staged files, then unit tests, then smoke E2E

Configuration approach

ESLint flat config (eslint.config.js) at workspace root, covering all packages:

  1. Ignores: dist/, node_modules/, .wrangler/, generated docs, lock files
  2. Base: @eslint/js recommended
  3. TypeScript: typescript-eslint recommended — strict mode reserved for future
  4. React (tsx): @eslint-react recommended + react-refresh/only-export-components
  5. Relaxations: no-console: off (console logging is intentional), unused vars with _ prefix ignored
  6. Prettier: eslint-config-prettier as last layer to disable conflicting rules

Prettier (.prettierrc) at workspace root — single source of truth for formatting across all contributors.

lint-staged configured in package.json — only touches staged files, keeping pre-commit fast (~2s for a typical commit).

Scripts added to root package.json

json
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --check \"**/*.{ts,tsx,js,json,css,md}\"",
"format:fix": "prettier --write \"**/*.{ts,tsx,js,json,css,md}\""

CI integration

The existing deploy.yml (tag-triggered) and future PR workflow (ci.yml) should run:

  • pnpm lint
  • pnpm format
  • pnpm -r test
  • pnpm docs:check

Consequences

Positive:

  • Consistent code style enforced automatically (no more bikeshedding in reviews)
  • TypeScript errors caught earlier (no-unused-vars, no-explicit-any)
  • Pre-commit hook catches formatting + lints before code leaves the dev machine
  • Flat config is future-proof and easy to extend per-package

Negative:

  • Initial eslint . may surface pre-existing warnings — these are expected and can be addressed incrementally; the config is intentionally lenient
  • @eslint-react is newer than eslint-plugin-react; its rule set may differ slightly — adjust as the project's React patterns evolve

Risks:

  • Pre-commit hook may feel slow on large commits (lint-staged mitigates by only scanning staged files)
  • Turborepo (deferred) would bring caching — without it, pnpm lint always scans everything

🚫 Hard rule: no force push

During the v0.39.0 release a git push --force was mistakenly used to overwrite a tag (v0.35.0), requiring tag deletion, re-creation, and a corrective version bump to v0.39.0. This is a process incident.

Rule: git push --force and git push --force-with-lease are strictly prohibited on any shared branch or tag. See docs/community/contributing.md for the full policy.

  • Issues: #159 (rebranding, this was part of infra setup)
  • ADRs: ADR-0014 (plugin registry, another dev-infra decision)
  • Future: Turborepo integration for task orchestration + remote caching

Distribuído sob licença MIT.