5.1 KiB
5.1 KiB
AGENTS.md — Codebase Guide for AI Coding Agents
This document describes the structure, conventions, and commands for the vibe_coding_timetracker monorepo. Read it in full before making changes.
Repository Structure
/
├── frontend/ # React SPA (Vite + TypeScript + Tailwind)
│ └── src/
│ ├── api/ # Axios API client modules
│ ├── components/# Shared UI components (PascalCase .tsx)
│ ├── contexts/ # React Context providers
│ ├── hooks/ # TanStack React Query hooks (useXxx.ts)
│ ├── pages/ # Route-level page components
│ ├── types/ # TypeScript interfaces (index.ts)
│ └── utils/ # Pure utility functions
├── backend/ # Express REST API (TypeScript + Prisma + PostgreSQL)
│ └── src/
│ ├── auth/ # OIDC + JWT logic
│ ├── errors/ # AppError subclasses
│ ├── middleware/# Express middlewares
│ ├── prisma/ # Prisma client singleton
│ ├── routes/ # Express routers (xxx.routes.ts)
│ ├── schemas/ # Zod validation schemas
│ └── services/ # Business logic classes (xxx.service.ts)
├── ios/ # Native iOS app (Swift/Xcode)
├── timetracker-chart/ # Helm chart for Kubernetes deployment
└── docker-compose.yml
Build, Lint, and Dev Commands
Frontend (frontend/)
- Dev Server:
npm run dev(port 5173) - Build:
npm run build(tsc & vite build) - Lint:
npm run lint(ESLint, zero warnings allowed) - Preview:
npm run preview
Backend (backend/)
- Dev Server:
npm run dev(tsx watch) - Build:
npm run build(tsc to dist/) - Start:
npm run start(node dist/index.js) - Database:
npm run db:migrate(Run migrations)npm run db:generate(Regenerate client)npm run db:seed(Seed database)
Full Stack (Root)
- Run all:
docker-compose up
Testing
No test framework is currently configured. No test runner (jest, vitest) is installed and no .spec.ts or .test.ts files exist.
- When adding tests, set up Vitest (aligned with Vite).
- Add a
testscript topackage.json. - To run a single test file with Vitest once installed:
npx vitest run src/path/to/file.test.ts
Code Style Guidelines
Imports & Exports
- Use
@/for all internal frontend imports:import { useAuth } from "@/contexts/AuthContext" - Use
import type { ... }for type-only imports. Order external libraries first. - Named exports are standard. Avoid default exports (except in
App.tsx).
Formatting
- 2-space indentation. No Prettier config exists; maintain consistency with surrounding code.
- Prefer double quotes. Trailing commas in multi-line objects/arrays.
Types & Naming Conventions
- Define shared types as
interfaceintypes/index.ts. - Suffix input types:
CreateClientInput. - Use
?for optional fields,string | nullfor nullable fields (notundefined). - Components:
PascalCase.tsx(DashboardPage.tsx) - Hooks/Utils/API:
camelCase.ts(useTimeEntries.ts,dateUtils.ts) - Backend Routes/Services:
camelCase.routes.ts,camelCase.service.ts - Backend Schemas: Zod schemas in
backend/src/schemas/index.ts(e.g.,CreateClientSchema).
React Components
- Use named function declarations:
export function DashboardPage() { ... } - Context hooks throw an error if called outside their provider.
State Management
- Server state: TanStack React Query. Never use
useStatefor server data.- Use
mutateAsyncso callers can await and handle errors. - Invalidate related queries after mutations:
queryClient.invalidateQueries.
- Use
- Shared client state: React Context.
- Local UI state:
useState. - NO Redux or Zustand.
Error Handling
- Frontend:
Store errors in local state and render inline as red text. No global error boundary exists.
try { await someAsyncOperation() } catch (err) { setError(err instanceof Error ? err.message : "An error occurred") } - Backend: Throw
AppErrorsubclasses from services.router.get("/:id", async (req, res, next) => { try { res.json(await service.getById(req.params.id)) } catch (error) { next(error) // Always forward to errorHandler middleware } })
Styling
- Tailwind CSS v3 only. No CSS modules or styled-components.
- Use
clsx+tailwind-mergefor class merging. Icons fromlucide-reactonly.
Backend Validation & Database
- Validate all incoming request data with Zod schemas in middleware.
- Prisma v6 with PostgreSQL. Use the Prisma client singleton from
backend/src/prisma/. - DB columns are
snake_case, mapped tocamelCaseTypeScript via@map.
Key Architectural Decisions
- Frontend communicates with Backend exclusively via typed Axios modules in
frontend/src/api/. - iOS app shares no code with the web frontend.
- Backend routes only handle HTTP concerns (parsing, validation, formatting); business logic belongs purely in services.