Skip to main content

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

ToolPurpose
LefthookGit hooks manager
lint-stagedRun linters on staged files
OxlintFast JavaScript/TypeScript linter
OxfmtFast code formatter
CommitlintCommit message linter

Git Hooks

Git hooks are configured in lefthook.yml:
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):
1
Audit
2
Security audit on canary branch (checks for vulnerable dependencies)
3
lint-staged
4
Format and lint only staged files
5
Build
6
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:
.lintstagedrc.json
{
  "*": ["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:
.oxfmtrc.jsonc
{
  "$schema": "./node_modules/oxfmt/configuration_schema.json",
  "semi": false,
  "experimentalSortImports": {},
  "experimentalTailwindcss": {},
  "ignorePatterns": ["**/*.lock"]
}
SettingValueDescription
semifalseNo 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:check

Linting with Oxlint

Oxlint runs automatically via lint-staged. For manual linting:
# Lint all files
bun run lint
Oxlint is significantly faster than ESLint while catching common issues.

Commit Message Convention

Commits must follow Conventional Commits:
<type>(<scope>): <subject>

<body>

Types

TypeDescription
featNew feature
fixBug fix
docsDocumentation only
styleCode style (formatting, semicolons)
refactorCode change that neither fixes a bug nor adds a feature
perfPerformance improvement
testAdding or updating tests
choreMaintenance (dependencies, build scripts)
ciCI/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 hook

Breaking Changes

Append ! after type for breaking changes:
feat!: remove deprecated API endpoints

Running 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-types

CI/CD Integration

GitHub Actions runs these checks on every PR in .github/workflows/auto-check-build.yml:
- name: Audit, Lint, and Build
  run: |
    bun audit --audit-level high
    bun run lint
    bun run build

Skipping 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"
Only skip hooks for emergencies. CI will still catch issues.

Troubleshooting

# Reinstall hooks
bunx lefthook install
If formatting creates unexpected changes:
# Format entire codebase
bun run format

# Stage formatted files
git add .
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"

Build docs developers (and LLMs) love