# Milestones ## v2.3 Global & Social Ready (Shipped: 2026-04-19) **Phases completed:** 3 phases (32-34), 18 plans **Timeline:** 6 days (2026-04-13 → 2026-04-19) **Codebase:** 217 files changed (+24,291 / -991), 99 commits **Key accomplishments:** - Setup visibility system: isPublic replaced with private/link/public visibility column, shares table with 128-bit token entropy, visibility-transition side effects (deactivate/reactivate links) - ShareModal with Google Docs-style UX: visibility picker, share link creation with expiry, active links list with revoke, deactivation warning - Shared setup viewer: `/s/:token` short URL redirect, `/api/shared/:token` public endpoint, read-only mode with owner controls gated, inline "Shared setup" banner - Multi-currency foundation: market_prices + community_prices tables, ECB exchange rates via frankfurter.app with 24h cache, currency conversion service - Community price aggregation: ownership-validated submissions, PERCENTILE_CONT(0.5) median with 3-report minimum, market-aware MSRP on catalog detail pages - i18n framework: react-i18next + 6 namespaces (common/collection/threads/setups/onboarding/settings/catalog), English + German locales, language picker in settings, locale-aware formatting **Known deferred items at close:** 6 (see STATE.md Deferred Items) **Archive:** `.planning/milestones/v2.3-ROADMAP.md`, `.planning/milestones/v2.3-REQUIREMENTS.md` --- ## v2.2 User Experience Polish (Shipped: 2026-04-13) **Phases completed:** 36 phases, 68 plans, 120 tasks **Key accomplishments:** - Parameterized formatWeight with g/oz/lb/kg conversion and useWeightUnit settings hook, backed by 21 TDD tests - Segmented g/oz/lb/kg toggle in TotalsBar with all 8 weight display call sites wired to user-selected unit - Candidate status tracking (researching/ordered/arrived) with schema migration, service/Zod updates, 5 TDD tests, and clickable StatusBadge popup on CandidateCard - Sticky search/filter toolbar on gear tab with text+category filtering, and shared icon-aware CategoryFilterDropdown on both gear and planning tabs - Per-setup item classification (base/worn/consumable) with click-to-cycle badge, classification-preserving sync, and full test coverage - Recharts donut chart with category/classification toggle, weight subtotals card, and hover tooltips inside setup detail page - Nullable pros/cons TEXT columns added to thread_candidates from SQLite schema through Drizzle migration, service layer, Zod validation, React form inputs, and CandidateCard visual badge - sortOrder REAL column, reorderCandidates transaction service, and PATCH /api/threads/:id/candidates/reorder endpoint with active-thread guard - 1. [Rule 2 - Missing] Added pros/cons fields to CandidateWithCategory in useThreads.ts - Side-by-side candidate comparison table with sticky labels, weight/price delta highlighting, and resolved-thread winner marking via a new "compare" candidateViewMode - PostgreSQL schema with 13 pgTable definitions, postgres.js connection, PGlite test infrastructure, and initial migration - PostgreSQL 16 Docker Compose for dev and production, lean Dockerfile without native SQLite build dependencies - All 9 service files (30 functions) converted from synchronous SQLite to async PostgreSQL operations with PGlite smoke test validation - All 9 route files and auth middleware converted to properly await async service/DB calls, preventing Promise-as-JSON responses - One-time data migration script converting all 13 tables from SQLite to PostgreSQL with timestamp/boolean type conversions and serial sequence reset - All 18 test files converted to async PGlite with 161 tests passing across service, route, and MCP layers - Logto OIDC provider added to Docker Compose with Postgres init script, users/sessions tables removed from schema - Three-way auth middleware with @hono/oidc-auth for browser sessions, API keys for programmatic access, and MCP OAuth consent flow - OIDC login redirect page, cleaned auth hooks (string user id, no credential forms), API-key E2E seed, and three-way auth test coverage - pgTable schema with users table, userId FK on 6 entity tables, composite constraints, and auth middleware resolving userId for all auth methods - All 7 service files accept userId parameter with and(eq) isolation on every query — no unscoped reads or writes remain - Complete userId propagation chain from auth middleware through routes and MCP tools to service layer - Route tests, MCP tests, and cross-user isolation tests updated with userId context for multi-user data model - S3 storage abstraction with uploadImage/deleteImage/getImageUrl using @aws-sdk/client-s3, plus MinIO in Docker Compose with automatic bucket creation - Replaced all local filesystem image operations with S3 storage service calls across routes, services, and MCP tools - Replaced all client /uploads/ path references with presigned S3 URLs and created one-time image migration script - Global items table, item-global links, user profile columns, setup visibility, Zod schemas, and 18-item bikepacking seed catalog - Global item catalog backend with LIKE search, owner count aggregation, item linking, idempotent seeding, and full test coverage - Profile service with CRUD and public profile data, public setup viewing, setup visibility toggle, and auth middleware bypass for public endpoints - Global catalog browse/search page, item detail with owner count, and link-to-catalog component using TanStack Router and Query - Profile edit UI in settings with avatar upload, public profile page with setup listing, and setup visibility toggle with globe icon - Database schema updated with direct globalItemId FK on items/candidates, tags system tables, and data migration from itemGlobalLinks - COALESCE merge pattern in item/thread services for transparent reference item data, branched thread resolution, and link/unlink endpoint removal - Tag-filtered global item search with AND logic, owner count via direct FK, and COALESCE merge propagated to setup/totals/profile/CSV services - Tags endpoint with alphabetical ordering, global-items route registration, UIStore FAB/catalog-search state, and tag-aware useGlobalItems hook - Global FAB with animated mini menu and full-screen catalog search overlay with debounced search, tag chip AND-filtering, and result card grid - Private item detail page with edit mode toggle at /items/:id, and enhanced catalog detail page with Add to Collection stub button - Candidate detail page with edit mode toggle at /threads/:threadId/candidates/:candidateId, thread route directory restructured for nested routes, add-candidate modal replacing slide-out panel - All card components rewired from slide-out panels to detail page navigation, panels removed from root layout, UIStore cleaned of panel state - AddToCollectionModal with category/notes/price fields, sonner toasts, and wired catalog search + detail page entry points - AddToThreadModal with existing thread picker, new thread + candidate creation, and session thread memory for catalog search flow - ManualEntryForm component with CategoryPicker, ImageUpload, and cents conversion wired into CatalogSearchOverlay as inline mode with entry points, success card, and context-sensitive navigation - createRateLimit(max, windowMs) factory with browse (120/min) and detail (60/min) tiers applied to all public GET endpoints before auth middleware - globalItems attribution columns (sourceUrl, imageCredit, imageSourceUrl) with unique(brand, model) constraint, upsertGlobalItem/bulkUpsertGlobalItems service functions, and Zod schemas — 21 tests passing - POST /api/global-items, POST /api/global-items/bulk, upsert_catalog_item and bulk_upsert_catalog MCP tools, and catalog detail page attribution display — 61 tests passing, lint clean, build succeeds - One-liner: - One-liner: - Discovery landing page replacing personal dashboard — hero search trigger, popular setups feed, recent catalog items, trending categories, with auth-conditional CTA and PublicSetupCard enhanced with item counts and creator names - 1. [Rule 1 - Bug] Used 'house' icon instead of plan-specified 'home' - One-liner: - TopNav replaces TotalsBar across all pages, BottomTabBar wired for mobile, hero removed from landing page, and /setups added as a public route - Shared hobby config, popular-items-by-tags endpoint with owner count ordering, and batch onboarding completion service with auto-category creation - 5-step catalog-driven onboarding with hobby cards, selectable item grid, review list, and CSS step transitions following UI-SPEC design contract - Replaced old OnboardingWizard with new OnboardingFlow in root route, deleted old component, verified build and no stale references --- ## v2.0 Platform Foundation (Shipped: 2026-04-08) **Phases completed:** 10 phases, 32 plans **Timeline:** 22 days (2026-03-17 to 2026-04-08) **Codebase:** 23,970 LOC TypeScript (17,859 src + 6,111 tests), 210 files changed (+47,370 / -2,244) **Key accomplishments:** - PostgreSQL migration: 13 pgTable definitions, async services, PGlite test infrastructure, Docker Compose - External OIDC authentication via Logto with three-way auth middleware (browser sessions, API keys, MCP OAuth) - Multi-user data model with userId on all entities, cross-user isolation, and composite constraints - S3 object storage via MinIO replacing local filesystem for all image operations - Global item catalog with search, owner count aggregation, idempotent seeding, and 18-item bikepacking catalog - User profiles with avatar, bio, public setup sharing, and visibility toggle - Reference item model with COALESCE merge pattern for transparent global-to-personal data overlay - Tag system for global item discovery with AND-filtered search - Global FAB with animated mini menu and full-screen catalog search overlay with tag chip filtering - Item and catalog detail pages replacing slide-out panels, with edit mode toggle - Add-from-catalog flow for both collection items and thread candidates - Manual entry fallback with non-functional catalog submission prompt **Archive:** `.planning/milestones/v2.0-ROADMAP.md`, `.planning/milestones/v2.0-REQUIREMENTS.md` --- ## v1.3 Research & Decision Tools (Shipped: 2026-04-08) **Phases completed:** 4 phases, 6 plans **Timeline:** 23 days (2026-03-16 to 2026-04-08) **Codebase:** ~8,300 LOC TypeScript, 52 files changed (+3,106 / -158) **Key accomplishments:** - Pros/cons text fields on candidates with full-stack support (schema, service, Zod, form, card indicator) - Candidate ranking with sortOrder column, drag-to-reorder UI, and gold/silver/bronze rank badges - Side-by-side comparison table with sticky labels, weight/price delta highlighting, and resolved-thread winner marking - Setup impact preview showing per-candidate weight and cost deltas against a selected setup with replacement detection **Archive:** `.planning/milestones/v1.3-ROADMAP.md`, `.planning/milestones/v1.3-REQUIREMENTS.md` --- ## v1.2 Collection Power-Ups (Shipped: 2026-03-16) **Phases completed:** 3 phases, 6 plans, 11 tasks **Timeline:** 3 days (2026-03-14 → 2026-03-16) **Codebase:** 7,310 LOC TypeScript, 66 files changed (+7,243 / -206) **Key accomplishments:** - Weight unit conversion (g/oz/lb/kg) with segmented toggle wired across all 8 display call sites - Candidate status tracking (researching/ordered/arrived) with clickable StatusBadge popup - Sticky search/filter toolbar with text search and icon-aware CategoryFilterDropdown - Per-setup item classification (base/worn/consumable) with click-to-cycle badge - Recharts donut chart with category/classification toggle, hover tooltips, and weight subtotals - Classification-preserving sync that maintains metadata across atomic setup re-sync **Archive:** `.planning/milestones/v1.2-ROADMAP.md`, `.planning/milestones/v1.2-REQUIREMENTS.md` --- ## v1.1 Fixes & Polish (Shipped: 2026-03-15) **Phases completed:** 3 phases, 7 plans **Timeline:** 1 day (2026-03-15) **Codebase:** 6,134 LOC TypeScript, 65 files changed (+5,049 / -1,109) **Key accomplishments:** - Fixed threads table and thread creation with categoryId support, modal dialog flow - Overhauled planning tab with educational empty state, pill tabs, and category filter - Fixed image display bug (Zod schemas missing imageFilename — silently stripped by validator) - Redesigned image upload as hero preview area with 4:3 placeholders on all cards - Migrated categories from emoji to Lucide icons with 119-icon curated picker - Built IconPicker component with search, 8 group tabs, portal popover **Archive:** `.planning/milestones/v1.1-ROADMAP.md`, `.planning/milestones/v1.1-REQUIREMENTS.md` --- ## v1.0 MVP (Shipped: 2026-03-15) **Phases completed:** 3 phases, 10 plans **Timeline:** 2 days (2026-03-14 → 2026-03-15) **Codebase:** 5,742 LOC TypeScript, 53 commits, 114 files **Key accomplishments:** - Full gear collection with item CRUD, categories, weight/cost totals, and image uploads - Planning threads with candidate comparison and thread resolution into collection - Named setups (loadouts) composed from collection items with live totals - Dashboard home page with summary cards linking to all features - Onboarding wizard for first-time setup experience - Complete test suite with service-level and route-level integration tests **Archive:** `.planning/milestones/v1.0-ROADMAP.md`, `.planning/milestones/v1.0-REQUIREMENTS.md` ---