This document translates the repository standards into day-to-day engineering practice. Use it when adding routes, changing business logic, introducing UI, or preparing a pull request.
- Baseline Standards
- Project Conventions By Area
- Recommended Workflow
- Testing Expectations
- Documentation Maintenance
- Pull Request Checklist
- Design and Frontend Notes
- Legacy and Transitional Areas
- If You Are Unsure
| Standard | Details |
|---|---|
| Strict mode | Keep TypeScript strict |
| Types | Avoid any |
| Typing | Prefer explicit domain types and Zod inference over ad hoc inline object typing |
| Contracts | Preserve existing serialization contracts for route handlers and hooks unless the change is intentional and documented |
| Standard | Details |
|---|---|
| Boundary | Validate request bodies, query parameters, and path-dependent payloads at the route boundary |
| Layer | Zod is the default runtime validation layer |
| Safety | Do not let unvalidated values reach Prisma or raw SQL |
| Standard | Details |
|---|---|
| API errors | API handlers should return explicit, human-readable JSON errors |
| Client errors | Client-facing flows should surface meaningful failures through Sonner |
| Silent failures | Avoid silent failures or logging-only error handling when the user needs feedback |
| Standard | Details |
|---|---|
| Components | New UI must use components from @/components/ui/* |
| Libraries | Do not introduce a parallel UI component library |
| Accessibility | Keep accessibility intact: labels, focus states, semantic markup, and dialog titles are required |
| Styling | Prefer rounded-md when adding rounded corners |
| Standard | Details |
|---|---|
| Library | Use react-icons only |
| Import | Import from subpaths such as react-icons/fi and react-icons/fa |
| Decorative | Decorative icons should usually be aria-hidden="true" and use className="size-4" unless the design needs something else |
When editing src/app/api/v1/**/route.ts:
| Step | Action |
|---|---|
| 1 | Validate early with Zod |
| 2 | Resolve the actor and enforce role access before business logic |
| 3 | Keep serialization explicit |
| 4 | Return stable JSON envelopes |
| 5 | Update docs with pnpm docs:api |
Practical rule: If you changed a route signature, added a query parameter, renamed a route, or introduced a new handler file, the docs must be regenerated in the same change.
When code starts growing inside a route handler or component:
| Action | Destination |
|---|---|
| Move reusable logic | src/lib |
| Move repeated query logic | Domain helper |
| Keep serializers | Close to the owning domain |
Good examples in the repository:
| Area | Location |
|---|---|
| Booking lifecycle helpers | src/lib/bookings |
| Pricing rule logic | src/lib/pricing-rules* |
| Provider integrations | src/lib/providers |
| Notification mapping | src/lib/notifications |
| Standard | Details |
|---|---|
| React Query | Use React Query for business data that benefits from caching and invalidation |
| Location | Put API-oriented hooks in src/hooks/api |
| Alignment | Keep hook APIs aligned with the route contracts they depend on |
The repository explicitly treats raw SQL as a review hotspot.
If you need raw SQL:
| Step | Action |
|---|---|
| 1 | Prefer Prisma query building when possible |
| 2 | If raw SQL is necessary, validate inputs first |
| 3 | Keep SQL in multi-line template strings |
| 4 | Preserve parameter binding and avoid string concatenation |
| 5 | Document why the query is safe in code review |
Before changing a feature:
- read the route or component you are touching;
- trace supporting
src/libhelpers; - inspect related hooks and page-level UI;
- check whether the behavior is already described in
docs/features.mdordocs/api-reference.md.
Prefer minimal diff churn, but do not preserve a bad abstraction just to keep the patch small. If the current structure causes duplication or hides business logic, extract the logic properly.
pnpm docs:apiThis updates:
public/openapi.jsondocs/api-reference.md
At minimum, run:
pnpm lint
pnpm test
pnpm buildIf your change affects Prisma schema or migrations, also run:
pnpm prisma generate| Target | Details |
|---|---|
| Business logic | src/lib |
| Complex hooks | src/hooks |
| Route behavior | New or high-risk API changes |
| Edge cases | Role access, validation failure, and status transitions |
| Command | Purpose |
|---|---|
pnpm test |
Run the Vitest suite |
pnpm test:watch |
Run Vitest in watch mode |
pnpm test:coverage |
Run Vitest with coverage reporting |
The following areas deserve extra care:
- booking lifecycle transitions
- pricing rule evaluation
- wallet and payout side effects
- verification and moderation flows
- AI assistant tool execution boundaries
- account deactivation and deletion workflows
Documentation is now a first-class maintenance task.
| Trigger | Action |
|---|---|
| New route handler added | Update docs |
| Route removed or renamed | Update docs |
| Request or response contract changed | Update docs |
| Auth requirements changed | Update docs |
| Feature moved from legacy to active state or vice versa | Update docs |
| Setup prerequisites changed | Update docs |
| Surface | When to update it |
|---|---|
README.md |
Entry-point understanding, commands, and major capability changes |
docs/setup.md |
New env vars, services, extensions, or setup steps |
docs/architecture.md |
Domain boundaries, route groups, or subsystem ownership changes |
docs/features.md |
User-visible behavior changes |
pnpm docs:api output |
Any src/app/api/v1 change |
Use this before opening or updating a PR:
| # | Check |
|---|---|
| 1 | Run pnpm lint |
| 2 | Run pnpm test |
| 3 | Run pnpm build |
| 4 | Run pnpm docs:api if API routes changed |
| 5 | Confirm no secrets were added |
| 6 | Check keyboard accessibility for UI changes |
| 7 | Verify user-facing error states are still clear |
The project standards are explicit:
| Standard | Details |
|---|---|
| Design language | Preserve the existing design language when working inside an established screen |
| External libraries | Do not introduce random visual systems or external component libraries |
| Composition | Use shadcn/ui primitives and compose from there |
| Forms | Keep forms accessible and properly labeled |
| Dialogs | Keep dialog content paired with dialog titles |
Be careful with features that still exist as compatibility surfaces.
Legacy base-rate routes still exist under:
/api/v1/spaces/{space_id}/areas/{area_id}/rates/api/v1/spaces/{space_id}/areas/{area_id}/rates/{rate_id}
They intentionally return 410 Gone. Do not build new pricing work against them. Use partner pricing-rule endpoints instead.
/api/v1/ai-search is a deprecated alias for /api/v1/ai-assistant. Prefer the assistant route for new work.
When the right location for logic is unclear, default to this order:
| Priority | Location |
|---|---|
| 1 | Business rules in src/lib |
| 2 | Thin route handlers in src/app/api/v1 |
| 3 | Data hooks in src/hooks/api |
| 4 | UI composition in src/components/pages |
That order matches how the codebase is already organized and helps prevent route files and React components from becoming the place where everything accumulates.