Code Standards
Doc Status: Good | ✓ Clear summary | ✓ Easy to read | ✓ Matches code | ✓ Good structure | ✓ Professional look | ✓ Visual components
File Naming
| Type | Convention | Example |
|---|
| Pages | kebab-case.tsx | user-profile.tsx |
| Components | kebab-case.tsx | button-primary.tsx |
| Hooks | use-kebab-case.ts | use-user-profile.ts |
| Utils | kebab-case.ts | format-date.ts |
| Types/Interfaces | kebab-case.types.ts | user.types.ts |
| Tests | kebab-case.test.ts | user-service.test.ts |
Exception: Convex source modules use camelCase.ts (e.g. students.ts) — the Convex runtime rejects hyphens in module paths.
Import Conventions
Path Aliases
{
"compilerOptions": {
"paths": {
"~/*": ["./src/*"],
"@wds/ui": ["../../packages/ui/src"],
"@packages/backend/*": ["../../packages/backend/*"]
}
}
}
Tilde for Project Imports
// ✅ GOOD — tilde path alias
import { Button } from '~/components/ui/button';
import { cn } from '~/lib/cn';
// ❌ BAD — relative path
import { Button } from '../../../components/ui/button';
Same-directory relative imports are allowed.
No Barrel Files
Never use index.ts barrel files. Import directly from the specific file.
// ❌ BAD — barrel file
import { UserService, UserRepository } from '~/domain/user';
// ✅ GOOD — direct import
import { UserService } from '~/application/user/user.service';
Exception: packages/backend/convex/_generated/api is auto-generated by Convex — importing api from it is the standard pattern.
TypeScript Rules
No any Type
Never use any — it bypasses TypeScript’s type checking.
// ❌ BAD
const items: any[] = [];
const data: any = fetchSomething();
// ✅ GOOD — use unknown + type guard or Zod
const items: unknown[] = [];
const data = DataSchema.parse(rawData);
No Type Assertions (as)
Never use as type assertions — they bypass type checking.
// ❌ BAD
const user = data as User;
// ✅ GOOD — Zod or type guard
const user = UserSchema.parse(data);
Boolean Naming
| Prefix | Use for | Example |
|---|
is | Current state | isLoading, isActive |
has | Possession / containment | hasPermission |
can | Capability | canDelete |
should | Decision / condition | shouldRefetch |
Explicit Naming
// ❌ BANNED
function handle(x) {}
const data = await api.users.list();
const res = response;
// ✅ REQUIRED
function sendWelcomeEmail(userId: string) {}
const userList = await api.users.list();
const httpResponse = response;
No console.log
Use consola for structured logging:
import { consola } from 'consola';
// ❌ BAD
console.log('User created:', user);
// ✅ GOOD
consola.success('User created', { userId: user.id });
| Level | Use |
|---|
debug | Development noise |
info | Notable events |
success | Successful operations |
warn | Recoverable issues |
error | Errors that need attention |
ESLint Rules (Summary)
{
"no-explicit-any": "error",
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
"react-hooks/exhaustive-deps": "error",
"no-console": ["warn", { "allow": ["warn", "error", "info"] }],
"prefer-const": "error",
"no-var": "error"
}
Prettier Config
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
Conventional Commits — required for all commits:
feat: add user enrollment form
fix: correct attendance calculation
docs: update deployment guide
refactor: split student service into separate modules