Code Quality
Git hooks, linting, formatting, and commit conventions.
Overview
ZeroStarter enforces code quality through automated tools that run on every commit. This ensures consistent code style, catches errors early, and maintains a clean commit history.
Tools
| Tool | Purpose |
|---|---|
| Lefthook | Git hooks manager |
| lint-staged | Run linters on staged files |
| Oxlint | Fast JavaScript/TypeScript linter |
| Oxfmt | Fast code formatter |
| Commitlint | Commit message linter |
Git Hooks
Git hooks are configured in lefthook.yml:
pre-commit:
piped: true
commands:
audit:
run: bun audit --audit-level high
use_stdin: true
only:
- ref: canary
lint-staged:
run: bunx lint-staged --verbose
stage_fixed: true
build:
run: bun run build
interactive: true
commit-msg:
commands:
commitlint:
run: bunx commitlint --edit {1}Pre-commit Hook
Runs before each commit in sequence (piped):
- Audit: Security audit on
canarybranch (checks for vulnerable dependencies) - lint-staged: Format and lint only staged files
- Build: Verify the project builds successfully
Commit-msg Hook
Validates commit messages follow conventional commit format.
Lint-Staged Configuration
The .lintstagedrc.json defines what runs on staged files:
{
"*": ["oxfmt --no-error-on-unmatched-pattern", "oxlint"],
"package.json": ["bun .github/scripts/deps-manager.ts"]
}- All files: Format with Oxfmt, then lint with Oxlint
- package.json: Run dependency manager script (ensures consistent dependency versions)
Formatting with Oxfmt
Oxfmt configuration in .oxfmtrc.jsonc:
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"semi": false,
"experimentalSortImports": {},
"experimentalTailwindcss": {},
"ignorePatterns": ["**/*.lock"],
}| Setting | Value | Description |
|---|---|---|
semi | false | No semicolons (like Prettier with semi: false) |
experimentalSortImports | {} | Auto-sort imports |
experimentalTailwindcss | {} | Sort Tailwind CSS classes |
ignorePatterns | ["**/*.lock"] | Skip lock files |
Manual Formatting
# Format all files
bun run format
# Check formatting without changes
bun run format:checkLinting with Oxlint
Oxlint runs automatically via lint-staged. For manual linting:
# Lint all files
bun run lintOxlint is significantly faster than ESLint while catching common issues.
Commit Message Convention
Commits must follow Conventional Commits:
<type>(<scope>): <subject>
<body>Types
| Type | Description |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation only |
style | Code style (formatting, semicolons) |
refactor | Code change that neither fixes a bug nor adds a feature |
perf | Performance improvement |
test | Adding or updating tests |
chore | Maintenance (dependencies, build scripts) |
ci | CI/CD changes |
Examples
feat(auth): add Google OAuth provider
fix(api): handle null user in session middleware
docs(readme): update installation instructions
chore(deps): bump dependencies to latest versions
refactor(web): extract form validation into hookBreaking Changes
Append ! after type for breaking changes:
feat!: remove deprecated API endpointsRunning Checks Manually
# All checks (what CI runs)
bun audit --audit-level high
bun run lint
bun run build
bun run check-types
# Format all files
bun run format
# Just type checking
bun run check-typesCI/CD Integration
GitHub Actions runs these checks on every PR:
# .github/workflows/auto-check-build.yml
- name: Audit, Lint, and Build
run: |
bun audit --audit-level high
bun run lint
bun run buildSkipping Hooks
In rare cases, you can skip hooks:
# Skip all hooks (use sparingly!)
git commit --no-verify -m "emergency fix"
# Skip specific hook
LEFTHOOK=0 git commit -m "message"Warning: Only skip hooks for emergencies. CI will still catch issues.
Troubleshooting
Hooks Not Running
# Reinstall hooks
bunx lefthook installFormat Conflicts
If formatting creates unexpected changes:
# Format entire codebase
bun run format
# Stage formatted files
git add .Commitlint Failing
Check your message follows the format:
# Good
git commit -m "feat: add user profile page"
# Bad (missing type)
git commit -m "add user profile page"
# Bad (wrong type)
git commit -m "added: user profile page"