# GearBox ## What This Is A gear management and discovery platform. Users catalog their gear collections (bikepacking, sim racing, or any hobby), track weight, price, and source details, research purchases through planning threads with side-by-side comparison, and compose named setups (loadouts) with weight classification and visualization. A global item database with crowd-verified specs and structured reviews helps users make informed purchase decisions. Multi-user with public setup sharing and gear discovery. ## Core Value Help people make better gear decisions — discover what others use, compare real-world data, and see how a potential buy affects your setup before committing. ## Requirements ### Validated - ✓ Gear collection with item CRUD (name, weight, price, category, notes, product link) — v1.0 - ✓ Image uploads for gear items — v1.0 - ✓ User-defined categories with automatic weight/cost totals — v1.0 - ✓ Planning threads for purchase research with candidate products — v1.0 - ✓ Thread resolution: pick a winner, it moves to collection — v1.0 - ✓ Named setups (loadouts) composed from collection items — v1.0 - ✓ Live weight and cost totals per setup — v1.0 - ✓ Dashboard home page with summary cards — v1.0 - ✓ Onboarding wizard for first-time setup — v1.0 - ✓ Thread creation with category assignment via modal dialog — v1.1 - ✓ Planning tab with educational empty state and pill tab navigation — v1.1 - ✓ Image display on item detail views and gear cards with placeholders — v1.1 - ✓ Hero image upload area with preview and click-to-upload — v1.1 - ✓ Lucide icon picker for categories (119 curated icons, 8 groups) — v1.1 - ✓ Automatic emoji-to-Lucide icon migration for existing categories — v1.1 - ✓ Search items by name with instant filtering — v1.2 - ✓ Filter collection items by category with icon-aware dropdown — v1.2 - ✓ Combined text search with category filter and result count — v1.2 - ✓ One-action filter clear — v1.2 - ✓ Weight unit selection (g, oz, lb, kg) with persistence — v1.2 - ✓ All weight displays respect selected unit across entire app — v1.2 - ✓ Per-setup item classification (base weight, worn, consumable) — v1.2 - ✓ Setup weight subtotals by classification — v1.2 - ✓ Donut chart visualization with category/classification toggle — v1.2 - ✓ Chart hover tooltips with weight and percentage — v1.2 - ✓ Candidate status tracking (researching/ordered/arrived) — v1.2 - ✓ Planning category filter with Lucide icons — v1.2 ### Active ## Current Milestone: v2.0 Platform Foundation **Goal:** Transform GearBox from a single-user gear tracker into a multi-user platform where people discover gear, research purchases using crowd-verified data, and share their setups. **Target features:** - External auth provider (self-hosted, open-source) for multi-user registration - Migrate from SQLite to Postgres - Multi-user data model (user ownership on all entities, public/private visibility) - Global item database (seeded from manufacturer data, enrichable by users) - Public user profiles with shared setups - Structured item reviews (ratings + predefined fields, not freeform text) - Discovery feed (browse setups, new items, popular gear) - Item detail pages with aggregated specs, owner count, setup appearances ### Future - [ ] Freeform reviews with moderation system - [ ] Comments on setups - [ ] Follow users / activity feeds - [ ] OAuth / social login providers - [ ] User-to-user messaging ### Out of Scope - Custom comparison parameters — complexity trap, weight/price covers 80% of cases - Mobile native app — web-first, responsive design sufficient - Price tracking / deal alerts — requires scraping, fragile - Barcode scanning — poor UX, manual entry is fine with global database - Real-time weather integration — only outdoor-specific, GearBox is hobby-agnostic - Freeform UGC (reviews, comments) — defer until moderation infrastructure exists - User-to-user messaging — high moderation burden, not core to discovery - Wiki-style open item editing — structured contributions only for data quality - Maintaining SQLite single-user mode in parallel — diverged at v2.0 ## Context Shipped through v1.4 with 11,333 LOC TypeScript across 90 files. Starting v2.0 platform transformation. Tech stack: React 19, Hono, Drizzle ORM, SQLite (migrating to Postgres), TanStack Router/Query, Tailwind CSS v4, Lucide React, Recharts, framer-motion, all on Bun. Primary use case is bikepacking gear but data model is hobby-agnostic. Existing auth: single-user with cookie sessions + API keys. Will be replaced by external auth provider. Existing features: MCP server (19 tools), E2E tests (Playwright), CSV import/export, item comparison, candidate ranking, setup impact preview. 21 test files (service-level, route-level integration, and E2E). ## Constraints - **Runtime**: Bun — used as package manager and runtime - **Design**: Light, airy, minimalist — white/light backgrounds, lots of whitespace, no visual clutter - **Navigation**: Dashboard-based home page, not sidebar or top-nav tabs - **Auth**: External self-hosted provider — no in-house auth maintenance - **Database**: Postgres for platform deployment - **UGC**: Structured input only (ratings, predefined fields) — no freeform text until moderation exists - **Scope**: Multi-user platform with public discovery ## Key Decisions | Decision | Rationale | Outcome | |----------|-----------|---------| | Cookie/API key auth | Single user, public read + authenticated write | ✓ Good | | Generic data model | Support any hobby, not just bikepacking | ✓ Good | | Dashboard navigation | Clean entry point, not persistent nav | ✓ Good | | Bun runtime | User preference | ✓ Good | | Service layer with DI | Accept db as first param for testability | ✓ Good | | Hono context variables for DB | Enables in-memory SQLite integration tests | ✓ Good | | Prices stored as cents | Avoids float rounding issues | ✓ Good | | Vite proxy dev setup | Required by TanStack Router plugin | ✓ Good | | drizzle-kit needs better-sqlite3 | bun:sqlite not supported by CLI | ✓ Good | | Tab navigation via URL params | Shareable URLs between gear/planning | ✓ Good | | Setup item sync: delete-all + re-insert | Simpler than diffing, atomic in transaction | ✓ Good | | Onboarding state in SQLite settings | Source of truth in DB, not Zustand | ✓ Good | | Stay with SQLite | Single-user app, no need for Postgres complexity | ✓ Good | | Lucide Icons for categories | Best outdoor/gear icon coverage, tree-shakeable, clean style | ✓ Good | | categoryId on threads (NOT NULL FK) | Every thread belongs to a category | ✓ Good | | Modal dialog for thread creation | Cleaner UX, supports category selection | ✓ Good | | Hero image area at top of forms | Image-first UX, 4:3 aspect ratio consistent with cards | ✓ Good | | Emoji-to-icon automatic migration | One-time schema rename + data conversion via Drizzle migration | ✓ Good | | ALTER TABLE RENAME COLUMN for SQLite | Simpler than table recreation for column rename | ✓ Good | | Platform pivot at v2.0 | Single-user model proven, now build for multi-user discovery | — Pending | | External auth provider | Avoid in-house auth security burden, self-hosted + open-source | — Pending | | SQLite → Postgres | Multi-user platform needs proper concurrent DB; auth provider needs Postgres anyway | — Pending | | Single-user mode diverges at v2.0 | Platform features irrelevant for solo use; maintain as separate artifact if needed | — Pending | | Structured UGC only (no freeform) | Minimize moderation burden; ratings + predefined fields cover 80% of value | — Pending | | Discovery-first, not social-first | Users come to research gear decisions, not to build social graphs | — Pending | | Weight conversion precision: g=0dp, oz=1dp, lb=2dp, kg=2dp | Matches common usage conventions | ✓ Good | | Unit toggle in TotalsBar (not settings page) | Visible, quick access for frequent switching | ✓ Good | | CategoryFilterDropdown separate from CategoryPicker | Filter vs form concerns are different | ✓ Good | | No debounce on search input | Collection under 1000 items, instant feedback | ✓ Good | | StatusBadge popup with click-outside dismiss | Consistent with CategoryPicker pattern | ✓ Good | | Classification on setupItems join table | Same item can have different roles per setup | ✓ Good | | Click-to-cycle for ClassificationBadge | Only 3 values, simpler than popup | ✓ Good | | Classification-preserving sync via Map | Save metadata before delete, restore after re-insert | ✓ Good | | Recharts for charting | Mature React chart library, composable API | ✓ Good | ## Evolution This document evolves at phase transitions and milestone boundaries. **After each phase transition** (via `/gsd:transition`): 1. Requirements invalidated? → Move to Out of Scope with reason 2. Requirements validated? → Move to Validated with phase reference 3. New requirements emerged? → Add to Active 4. Decisions to log? → Add to Key Decisions 5. "What This Is" still accurate? → Update if drifted **After each milestone** (via `/gsd:complete-milestone`): 1. Full review of all sections 2. Core Value check — still the right priority? 3. Audit Out of Scope — reasons still valid? 4. Update Context with current state --- *Last updated: 2026-04-03 after v2.0 milestone start*