# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview GearBox is a single-user web app for managing gear collections (bikepacking, sim racing, etc.), tracking weight/price, and planning purchases through research threads. Full-stack TypeScript monolith running on Bun. ## Commands ```bash # Development bun run dev # Starts both Vite client (:5173) and Hono server (:3000) concurrently bun run dev:client # Vite dev server on :5173 (proxies /api to :3000) bun run dev:server # Hono server on :3000 with hot reload # Database bun run db:generate # Generate Drizzle migration from schema changes bun run db:push # Apply migrations to gearbox.db # Testing bun test # Run all unit/integration tests bun test tests/services/item.service.test.ts # Run single test file bun run test:e2e # Run Playwright E2E tests bun run test:e2e:ui # Playwright UI mode for debugging # Lint & Format bun run lint # Biome check (tabs, double quotes, organized imports) # Build bun run build # Vite build → dist/client/ ``` ## Architecture **Stack**: React 19 + Hono + Drizzle ORM + SQLite, all running on Bun. ### Client (`src/client/`) - **Routing**: TanStack Router with file-based routes in `src/client/routes/`. Route tree auto-generated to `routeTree.gen.ts` — never edit manually. - **Data fetching**: TanStack React Query via custom hooks in `src/client/hooks/` (e.g., `useItems`, `useThreads`, `useSetups`). Mutations invalidate related query keys. - **UI state**: Zustand store (`stores/uiStore.ts`) for panel/dialog state only — server data lives in React Query. - **API calls**: Thin fetch wrapper in `lib/api.ts` (`apiGet`, `apiPost`, `apiPut`, `apiDelete`, `apiUpload`). - **Styling**: Tailwind CSS v4. ### Server (`src/server/`) - **Routes** (`routes/`): Hono handlers with Zod validation via `@hono/zod-validator`. Delegate to services. - **Services** (`services/`): Pure business logic functions that take a db instance. No HTTP awareness — testable without mocking. - Route registration in `src/server/index.ts` via `app.route("/api/...", routes)`. ### Shared (`src/shared/`) - **`schemas.ts`**: Zod schemas for API request validation (source of truth for types). - **`types.ts`**: Types inferred from Zod schemas + Drizzle table definitions. No manual type duplication. ### Database (`src/db/`) - **Schema**: `schema.ts` — Drizzle table definitions for SQLite. - **Prices stored as cents** (`priceCents: integer`) to avoid float rounding. - **Timestamps**: stored as integers (unix epoch) with `{ mode: "timestamp" }`. - Tables: `categories`, `items`, `threads`, `threadCandidates`, `setups`, `setupItems`, `settings`, `users`, `sessions`, `apiKeys`. ### Testing (`tests/` and `e2e/`) - **Unit/integration**: Bun test runner (`bun test`). Tests at service level and route level. - `tests/helpers/db.ts`: `createTestDb()` creates in-memory SQLite via Drizzle migrations and seeds an "Uncategorized" category. - **E2E**: Playwright (`bun run test:e2e`). Tests in `e2e/` run against a seeded SQLite database with the server in production mode. Seed script: `e2e/seed.ts`. ## Releasing Releases are managed by a Gitea Actions workflow (`.gitea/workflows/release.yml`). **Never create tags or releases manually** — always trigger the pipeline. The workflow runs CI (lint, test, build), computes the next version from the latest tag, generates a changelog, creates the tag, builds and pushes a Docker image, and creates a Gitea release. Trigger via Gitea API: ```bash curl -s -X POST "https://gitea.jeanlucmakiola.de/api/v1/repos/makiolaj/GearBox/actions/workflows/release.yml/dispatches" \ -H "Authorization: token " \ -H "Content-Type: application/json" \ -d '{"ref": "Develop", "inputs": {"bump": "patch"}}' # patch | minor | major ``` ## Branching - **Develop** is the main branch. Keep it clean — don't commit large feature work directly. - For each new brainstorming/implementation session, create a feature branch off Develop (e.g., `feature/setup-impact-preview`, `fix/error-handling`). - Merge back to Develop via PR or fast-forward merge when the work is complete and verified. ## Path Alias `@/*` maps to `./src/*` (configured in tsconfig.json). ## Reusable Components Always use existing components instead of rebuilding with plain HTML. Check `src/client/components/` before creating new form elements or UI patterns. | Need | Use | Not | |------|-----|-----| | Category selection | `CategoryPicker` (icons, search, inline create) | Plain `