Maintaining consistent code quality is essential for long-term project sustainability.
In this project, code quality is protected by a six-layer defense system.
The first layer ensures that the entire codebase follows consistent formatting rules.
We use two tools for this purpose:
- EditorConfig - ensures consistent formatting across different editors and IDEs
- Prettier - enforces automatic code formatting
These tools eliminate stylistic discussions during code reviews and ensure a uniform code style across the project.
The second layer introduces stricter rules through ESLint.
While ESLint can be configured in many different ways, this project uses the following plugins:
typescript-eslint- TypeScript-specific linting ruleseslint-plugin-import-lite- default export in modules are prohibitedeslint-plugin-no-only-tests- only statement in tests are prohibitedeslint-plugin-regexp- validation and best practices for regular expressionseslint-plugin-prettier- integration with Prettiereslint-plugin-perfectionist- sorting of imports and object propertieseslint-plugin-package-json- validation rules forpackage.jsoneslint-plugin-check-file- file naming conventions@eslint/json- additional validation for JSON files@eslint/js- JavaScript linting support for auxiliary scripts
Even in TypeScript projects, it is useful to lint JavaScript files that may exist in tooling scripts or configuration files.
ESLint should be integrated with your IDE so that checks run automatically on save or paste.
This ensures developers receive immediate feedback during development.
The third layer prevents problematic code from entering the repository.
This is implemented using Husky and lint-staged.
Before each commit:
- ESLint checks are executed
- formatting is validated
- only modified files are analyzed
This ensures that commits do not break the CI pipeline or introduce formatting issues.
Consistent commit messages are an important part of maintaining a readable and traceable project history. Clear commit messages help developers understand what changed, why it changed, and make it easier to navigate the codebase over time.
In this project we use commitlint to enforce a standardized commit message format. This ensures that all commits follow the same structure and remain meaningful.
Standardized commits also allow us to automatically generate a clean and structured changelog using tools like release-it during the release process.
This approach improves:
- readability of the git history
- traceability of changes
- automated changelog generation
- overall release management workflow
The final layer runs full validation during the CI pipeline.
At this stage the entire codebase is analyzed to ensure:
- linting rules pass
- formatting rules are satisfied
- tests run successfully
This final check acts as a safeguard before any changes are merged into the main branch.
To keep builds stable and predictable, avoid using ^ versions in package.json.
Minor dependency updates can still introduce breaking changes and unexpectedly break CI or releases even without code changes.
Recommended setup:
- use exact dependency versions
- commit
package-lock.json - use
npm ciin CI environments - add to
.npmrc:
save-exact=trueFor dependency updates, use:
npm i -g npm-check-updates
ncu -u
npm install