Adds concurrently to start both the Vite frontend and Hono backend simultaneously in one terminal via the `bun run dev` command. Also updates documentation in README.md and CLAUDE.md to reflect the new development workflow.
3.5 KiB
3.5 KiB
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
# 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 tests
bun test tests/services/item.service.test.ts # Run single test file
# 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 torouteTree.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.tsviaapp.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.
Testing (tests/)
- Bun test runner. Tests at service level and route level.
tests/helpers/db.ts:createTestDb()creates in-memory SQLite with full schema and seeds an "Uncategorized" category. When adding schema columns, update bothsrc/db/schema.tsand the test helper's CREATE TABLE statements.
Path Alias
@/* maps to ./src/* (configured in tsconfig.json).
Key Patterns
- Thread resolution: Resolving a thread copies the winning candidate's data into a new item in the collection, sets
resolvedCandidateId, and changes status to "resolved". - Setup item sync:
PUT /api/setups/:id/itemsreplaces all setup_items atomically (delete all, re-insert). - Image uploads:
POST /api/imagessaves to./uploads/with UUID filename, returned asimageFilenameon item/candidate records. - Aggregates (weight/cost totals): Computed via SQL on read, not stored on records.