| name | code-quality |
| description | Complete code quality workflow with ESLint, Prettier, TypeScript, Husky hooks, and type safety standards. Run before every commit/push. |
| triggers | ["lint","eslint","prettier","typescript","type check","code quality","clean code","format","husky","pre-commit","pre-push","tsc","type error","linting error"] |
| version | 1 |
| last_updated | "2025-10-24T00:00:00.000Z" |
Code Quality & Linting
Complete workflow for maintaining code quality through automated checks, linting, formatting, and type safety.
Purpose
Ensure code quality before every commit/push through:
- ESLint - Code style and best practices
- Prettier - Consistent formatting
- TypeScript - Type safety
- Husky - Automated git hooks
- Type Safety Standards - 2-tier approach (production strict, tests pragmatic)
Use when:
- Before committing code
- Fixing linting errors
- Resolving type errors
- Setting up code quality workflow
- Understanding what checks run automatically
Quick Reference
Manual Checks (Run Anytime)
cd app && npx prettier --check .
cd app && npx prettier --write .
cd app && npx eslint . --ext .ts,.tsx
cd app && npx eslint . --ext .ts,.tsx --fix
cd app && npx tsc --noEmit
cd app && npx tsc -p tsconfig.json --noEmit
cd app && npx prettier --check . && npx tsc --noEmit && npx eslint . --ext .ts,.tsx
Automated Checks
| Trigger | When | What Runs |
|---|
| Pre-commit | git commit | Lint-staged, Prettier, TypeScript (staged only) |
| Pre-push | git push | Full TypeScript, Wasp validation, ESLint |
| CI/CD | PR to develop/main | All checks + tests |
| Manual | Run commands above | Individual checks |
Pre-Commit Checks
Automatically runs on git commit (via Husky hook: .husky/_pre-commit.sh)
1. Block Secret Files
Prevents committing:
.env
.env.server
.env.client
.env.local
.env.server.local
.env.client.local
Allow example files:
.env.server.example
.env.client.example
If blocked:
git restore --staged .env.server
git commit
2. Lint-Staged (Fast Checks)
Only checks staged files (configured in .lintstagedrc.json):
| File Pattern | Actions |
|---|
*.md | Prettier format |
app/src/**/*.{ts,tsx} | ESLint auto-fix + Prettier format |
app/src/**/*.{js,jsx} | ESLint auto-fix + Prettier format |
app/**/*.{json,css} | Prettier format |
Auto-fixes applied before commit - staged files updated automatically.
3. Prettier Check (All Files)
Checks ALL files, not just staged (same as CI):
cd app && npx prettier --check .
If fails:
cd app && npx prettier --write .
git add .
git commit
4. TypeScript Check (Staged Files Only)
Fast check - only runs if .ts or .tsx files staged:
cd app && npx tsc -p tsconfig.json --noEmit
If fails: See Type Errors section below.
5. Cleanup .tmp/ Directory
Non-blocking - removes files >7 days old from .tmp/:
- Preserves
README.md, CLAUDE.md, .gitkeep
- Removes empty directories (keeps structure)
- Warns about temp files outside
.tmp/
Pre-Push Checks
Automatically runs on git push (via Husky hook: .husky/_pre-push.sh)
1. Full TypeScript Check
All files, not just staged:
cd app && npx tsc -p tsconfig.json --noEmit
More thorough than pre-commit - catches cross-file type issues.
2. Wasp Configuration Validation
Validates main.wasp syntax:
cd app && wasp version
Catches:
- Syntax errors in main.wasp
- Missing entity declarations
- Invalid route definitions
3. ESLint (Max 50 Warnings)
Full ESLint check with warning tolerance:
cd app && npx eslint . --ext .ts,.tsx,.js,.jsx --max-warnings 50
Why 50 warnings?
- Legacy code cleanup in progress
- Errors always block (0 tolerance)
- Warnings reduced over time
Current warning count: 20 (as of 2025-10-24)
Type Safety Standards
Reference: docs/LINTING-STANDARDS.md
2-Tier Standard
| Context | Standard | any Usage | Why |
|---|
| Production code | Strict (Tier 1) | 0 preferred | Type safety critical |
| Tests/mocks/helpers | Pragmatic | With comment | Practicality over purity |
Key Patterns
Operations (Production Code)
import type { GetDocument } from "wasp/server/operations";
export const getDocument: GetDocument<{ id: string }, A3Document> = async (
args,
context,
) => {
if (!context.user) throw new HttpError(401);
return context.entities.A3Document.findUnique({ where: { id: args.id } });
};
Helper Functions (Choose Pattern)
export async function createWithAudit(
userId: string,
data: Prisma.A3DocumentCreateInput,
a3Delegate: Prisma.A3DocumentDelegate,
) {
return taskRecordDelegate.create({ data: { ...data, userId } });
}
export async function complexHelper(
data: any,
context: any,
) {
}
Test Mocks (Pragmatic)
import { vi } from "vitest";
const mockCreate = vi.mocked(context.entities.A3Document.create);
const mockCreate = context.entities.A3Document.create as any;
See LINTING-STANDARDS.md for:
- Complete 2-tier philosophy
- Helper function decision tree
- ESLint configuration (disable no-undef for TS)
- unknown vs any guidance
- Industry standards alignment
Common Fixes
Type Errors
"Property X does not exist on type Y"
After schema.prisma or main.wasp changes:
./scripts/safe-start.sh
wasp clean
./scripts/safe-start.sh
Missing type annotation:
export const getDocument = async (args, context) => {
};
export const getDocument: GetDocument<{ id: string }, A3Document> = async (
args,
context,
) => {
};
"Cannot find module 'wasp/...'"
./scripts/safe-start.sh
"Unexpected any"
Use inline eslint-disable with reason:
const mockContext = createMockContext() as any;
Or fix with vi.mocked():
const mockCreate = vi.mocked(context.entities.A3Document.create);
Prettier Errors
"Code style issues found"
cd app && npx prettier --write .
cd app && npx prettier --check src/path/to/file.ts
cd app && npx prettier --write src/path/to/file.ts
ESLint Errors
"ESLint found issues"
cd app && npx eslint . --ext .ts,.tsx --fix
cd app && npx eslint . --ext .ts,.tsx
cd app && npx eslint src/path/to/file.ts
Common ESLint errors:
| Error | Fix |
|---|
no-unused-vars | Remove unused variable or prefix with _ |
no-explicit-any | Use proper type or add inline eslint-disable |
react-hooks/exhaustive-deps | Add missing dependency or suppress with comment |
Hook Failures
Pre-commit fails:
cd app && npx prettier --write .
./scripts/safe-start.sh
cd app && npx tsc --noEmit
cd app && npx eslint . --ext .ts,.tsx --fix
git restore --staged .env.server
Pre-push fails:
cd app && npx prettier --check . && npx tsc --noEmit && npx eslint . --ext .ts,.tsx
Bypass hooks (emergency only):
git commit --no-verify
git push --no-verify
Complete Workflow
Before Every Commit
Automated (no action needed):
- ✅ Lint-staged runs on staged files
- ✅ Prettier formats code
- ✅ ESLint auto-fixes issues
- ✅ TypeScript checks staged files
If hook fails:
git commit
Before Every Push
Automated (no action needed):
- ✅ Full TypeScript check
- ✅ Wasp configuration validated
- ✅ ESLint runs (max 50 warnings)
If hook fails:
cd app && npx tsc --noEmit
cd app && npx eslint . --ext .ts,.tsx
git push
Manual Quality Check
Run before creating PR:
cd app && npx prettier --write .
cd app && npx eslint . --ext .ts,.tsx --fix
cd app && npx tsc --noEmit
cd app && wasp test client run
git add .
git commit -m "fix: code quality improvements"
git push
Troubleshooting
"Husky hooks not running"
npx husky install
ls -la .husky/
"lint-staged skipping files"
cat .lintstagedrc.json
git add src/path/to/file.ts
git commit
"TypeScript errors after schema change"
./scripts/safe-start.sh
wasp clean
./scripts/safe-start.sh
"Too many ESLint warnings"
Current: 20 warnings (target: 0)
cd app && npx eslint . --ext .ts,.tsx
cd app && npx eslint src/specific/area --ext .ts,.tsx --fix
Priority order:
- Fix errors first (always block)
- Fix warnings in new code
- Gradually fix legacy warnings
"React 19 issue after wasp clean"
./scripts/safe-start.sh --clean
./scripts/fix-react-version.sh
Configuration Files
.lintstagedrc.json
What: Fast checks on staged files only (pre-commit)
Patterns:
*.md → Prettier
app/src/**/*.{ts,tsx} → ESLint + Prettier
app/src/**/*.{js,jsx} → ESLint + Prettier
app/**/*.{json,css} → Prettier
.husky/_pre-commit.sh
What: Pre-commit hook script
Runs:
- Block .env files
- Lint-staged
- Prettier check (all files)
- TypeScript check (staged files)
- Cleanup .tmp/
.husky/_pre-push.sh
What: Pre-push hook script
Runs:
- Full TypeScript check
- Wasp validation
- ESLint (max 50 warnings)
app/.eslintrc.json
What: ESLint configuration
Key rules:
@typescript-eslint/no-explicit-any: warn (not error)
@typescript-eslint/no-undef: off (TypeScript handles it)
- React hooks rules enabled
- Max warnings: 50 (enforced in pre-push)
app/.prettierrc
What: Prettier configuration
Settings:
- 2 spaces indent
- Single quotes
- Semicolons
- Max line length: 100
References
Examples
Fixing Common Pre-Commit Failures
Scenario 1: Prettier fails
[pre-commit] ❌ Prettier check failed
cd app && npx prettier --write .
git add .
git commit
Scenario 2: TypeScript error in staged file
[pre-commit] TypeScript error: Property 'name' does not exist
./scripts/safe-start.sh
git add src/path/to/file.ts
git commit
Scenario 3: Secret file blocked
[pre-commit] Refusing to commit env files
git restore --staged .env.server
cat .gitignore | grep .env.server
git commit
Fixing Common Pre-Push Failures
Scenario 1: Full TypeScript check fails
[pre-push] TypeScript error in src/utils/helper.ts
cd app && npx tsc --noEmit
git add src/utils/helper.ts
git commit -m "fix: resolve type error in helper"
git push
Scenario 2: ESLint exceeds warning limit
[pre-push] ESLint found 55 warnings (max 50)
cd app && npx eslint . --ext .ts,.tsx
cd app && npx eslint . --ext .ts,.tsx --fix
git add .
git commit -m "fix: resolve ESLint warnings"
git push
Manual Code Quality Workflow
Before creating PR:
cd app && npx prettier --write .
git add .
git commit -m "style: format code with prettier"
cd app && npx eslint . --ext .ts,.tsx --fix
git add .
git commit -m "fix: resolve linting issues"
cd app && npx tsc --noEmit
cd app && wasp test client run
git push
Notes
- Hooks are FAST: Pre-commit averages <5s for typical commits
- Pre-push is thorough: Full checks ensure CI won't fail
- Auto-fix is safe: Lint-staged only modifies staged files
- Warnings tolerated: 50 max (legacy code cleanup in progress)
- Types regenerate on restart: After schema/main.wasp changes
- React 19 bug: Use
safe-start.sh --clean, NOT wasp clean directly
Philosophy: Catch issues early (pre-commit) → Comprehensive check before sharing (pre-push) → CI validates (final gate).