Architecture
Conventions
Code style, naming, and structural conventions across the monorepo
App Structure
Most apps follow the src/ directory convention with a Convex backend:
apps/{app}/
├── src/
│ ├── app/ # Next.js App Router pages
│ ├── components/ # App-specific components
│ │ └── features/ # Feature-based organization
│ ├── hooks/ # App-specific hooks
│ ├── lib/ # App-specific utilities
│ └── types/ # App-specific types
├── convex/ # Convex backend (per-app deployment)
├── e2e/ # Playwright E2E tests
├── tests/ # Vitest unit tests
└── public/ # Static assets
Exception: Qript uses PostgreSQL + Drizzle ORM + better-auth instead of Convex:
apps/qript/
├── src/
│ └── lib/db/ # Drizzle schema
├── drizzle/ # Drizzle migrations
└── drizzle.config.ts # Drizzle Kit config
Convex Backend Patterns
- Each app has its own Convex deployment
- Use
convex/model/for shared business logic helpers - Keep public API functions thin — delegate to the model layer
- Use
internal.*for server-to-server calls
Testing Conventions
- Unit tests: Vitest with
@hn-monorepo/testinghelpers - E2E tests: Playwright with shared fixtures
- Shared mocks: Available for Next.js, Convex, and i18n
- Coverage target: 60%+ for shared packages
- Convex business logic: Unit tests recommended
- New user flows: E2E test recommended
- Bug fixes: Regression test required
- Playwright: Page object model for complex flows, selectors in
e2e/selectors/
Code Style
- Biome for formatting and linting (not ESLint/Prettier)
- React Compiler enabled — no manual
memo/useCallbackneeded - TypeScript strict mode across all apps and packages
- Server Components preferred — use
"use client"only when needed
Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Files | kebab-case | vocabulary-set-card.tsx |
| Components | PascalCase | VocabularySetCard |
| Hooks | use prefix, camelCase | useVocabularySet |
| Convex functions | camelCase | createVocabularySet |
| Types | PascalCase, no I prefix | VocabularySet |
| Constants | SCREAMING_SNAKE_CASE | MAX_RETRIES |
| Features | directory-based | components/features/<feature>/ |
Import Order
Imports should follow this order:
- External packages (
react,next,convex) - Monorepo packages (
@hn-monorepo/*) - Local aliases (
@/)
Error Handling
- Client-side errors: Toast notifications via Sonner
- Convex mutations: Auth-check first, then validation, then business logic
- API routes: Structured error responses with status codes