Files
GearBox/CLAUDE.md
Jean-Luc Makiola 725901623b chore: unify dev setup with concurrently
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.
2026-03-24 09:28:31 +01:00

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 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.

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 both src/db/schema.ts and 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/items replaces all setup_items atomically (delete all, re-insert).
  • Image uploads: POST /api/images saves to ./uploads/ with UUID filename, returned as imageFilename on item/candidate records.
  • Aggregates (weight/cost totals): Computed via SQL on read, not stored on records.