Files
GearBox/.planning/PROJECT.md

11 KiB

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
  • ✓ Candidate pros/cons annotation and ranking with drag-to-reorder — v1.3
  • ✓ Side-by-side candidate comparison table with weight/price deltas — v1.3
  • ✓ Setup impact preview for candidates (replacement vs addition detection) — v1.3
  • ✓ PostgreSQL database with async operations, PGlite test infra, Docker Compose — v2.0
  • ✓ External OIDC auth via Logto with three-way auth middleware — v2.0
  • ✓ Multi-user data model with userId isolation on all entities — v2.0
  • ✓ S3 object storage (MinIO) for images replacing local filesystem — v2.0
  • ✓ Global item catalog with search, owner count, and 18-item seed — v2.0
  • ✓ User profiles with avatar/bio, public setup sharing — v2.0
  • ✓ Reference item model with COALESCE merge for global-to-personal overlay — v2.0
  • ✓ Tag system for catalog discovery with AND-filtered search — v2.0
  • ✓ Global FAB with catalog search overlay and tag chip filtering — v2.0
  • ✓ Item and catalog detail pages replacing slide-out panels — v2.0
  • ✓ Add-from-catalog flow for collection items and thread candidates — v2.0
  • ✓ Manual entry fallback with catalog submission prompt stub — v2.0
  • ✓ Catalog attribution fields (sourceUrl, imageCredit, imageSourceUrl) on global items — v2.1
  • ✓ Unique constraint on (brand, model) preventing catalog duplicates — v2.1
  • ✓ Bulk import API with upsert semantics for catalog enrichment — v2.1
  • ✓ MCP catalog tools (upsert_catalog_item, bulk_upsert_catalog) for agent seeding — v2.1
  • ✓ Discovery landing page with catalog search, popular setups feed, recent items, trending categories — v2.1

Active

Current Milestone: v2.2 User Experience Polish

Goal: Fix broken user-facing features and polish the experience for real users — working profiles, better image handling, refreshed onboarding, and mobile refinements.

Target features:

  • Profile page with Logto integration for account management, branded login screens, email verification
  • Image fit-within framing (letterbox/pillarbox) instead of hard crops
  • Catalog-driven onboarding flow with visual refresh
  • Mobile UX improvements (icon actions, touch refinements)

Next milestone: v2.3 Global & Social Ready — setup sharing system, multi-currency, i18n

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 v2.0 with 23,970 LOC TypeScript across 210+ files. All milestones v1.0-v2.0 complete. Tech stack: React 19, Hono, Drizzle ORM, PostgreSQL, 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. Auth: External OIDC via Logto (browser sessions) + API keys (programmatic) + MCP OAuth (Claude). Infrastructure: PostgreSQL, MinIO (S3-compatible image storage), Docker Compose for dev/prod. Features: MCP server (21 tools), global item catalog with attribution and bulk import, user profiles, public setup sharing, catalog-driven gear flow, item/candidate detail pages, candidate ranking/comparison/impact preview. Public discovery landing page with catalog search, popular setups feed, recent items, and trending categories. 20+ test files (service-level, route-level integration, MCP). E2E tests pending rewrite for OIDC auth (backlog 999.1).

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: PostgreSQL with Drizzle ORM
  • 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 ✓ Good
External auth provider (Logto) Avoid in-house auth security burden, self-hosted + open-source ✓ Good
SQLite to Postgres Multi-user platform needs proper concurrent DB; auth provider needs Postgres anyway ✓ Good
Single-user mode diverges at v2.0 Platform features irrelevant for solo use; maintained as separate artifact if needed ✓ Good
Structured UGC only (no freeform) Minimize moderation burden; ratings + predefined fields cover 80% of value ✓ Good
Discovery-first, not social-first Users come to research gear decisions, not to build social graphs ✓ Good
COALESCE merge for reference items Global base + personal overlay without data duplication ✓ Good
Catalog-first add flow with manual fallback Encourages catalog usage while preserving flexibility ✓ Good
Detail pages replacing slide-out panels Better UX for complex data, shareable URLs ✓ Good
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-10 after Phase 27 complete — top nav restructure & search bar rethink