# Milestone v2.3: Global & Social Ready **Status:** ✅ SHIPPED 2026-04-19 **Phases:** 32-34 **Total Plans:** 18 ## Overview Made GearBox work for a global audience. Setup sharing with fine-grained visibility control, a full multi-currency pricing system with ECB exchange rates and community price aggregation, and an i18n foundation with English + German translations — all delivered in 6 days across 3 phases and 18 plans. ## Phases ### Phase 32: Setup Sharing System **Goal**: Setup owners can toggle visibility between private, link-shared, and public, with schema designed for future likes, friends, and collaborative editing **Depends on**: Phase 28 (profiles working) **Plans**: 4 plans Plans: - [x] 32-01-PLAN.md — Schema migration (isPublic to visibility) + shares table + full-stack update - [x] 32-02-PLAN.md — Share link service, API routes, and short URL redirect - [x] 32-03-PLAN.md — Share modal UI component with visibility picker and link management - [x] 32-04-PLAN.md — Shared setup viewer with token detection and read-only mode **Details:** - `visibility` text column (private/link/public) replaces `isPublic` boolean on setups table - `shares` table with token, permission, expiresAt, userId, revokedAt — schema future-proofed for person-specific shares and write permissions - Share tokens use randomBytes(16).toString("base64url") — 128-bit entropy, URL-safe - Visibility→private deactivates share links; switching back reactivates non-expired ones - `/s/:token` short URL redirects to `/setups/:id?share=token`; `/api/shared/:token` returns setup data without auth - ShareModal replaces old globe toggle — Google Docs-style with visibility picker + link management - Three-way data source in setup detail page: share token > authenticated owner > public viewer ### Phase 33: Currency System **Goal**: Users can select their preferred currency (USD/EUR/GBP) and all prices display accordingly — full market-aware pricing system with community price data **Depends on**: Phase 32 **Plans**: 6 plans Plans: - [x] 33-01-PLAN.md — Schema (market_prices, community_prices tables) + currency conversion service - [x] 33-02-PLAN.md — Database migration generation and push - [x] 33-03-PLAN.md — Market prices API, exchange rates endpoint, item/candidate currency context - [x] 33-04-PLAN.md — Community price service (ownership validation, median aggregation) + setup totals - [x] 33-05-PLAN.md — Formatter evolution, market/currency selector, auto-suggestion, conversion toggle - [x] 33-06-PLAN.md — Catalog detail market prices, comparison table normalization, MCP tool updates **Details:** - `market_prices` and `community_prices` tables with unique constraints - `priceCurrency` column on items; `foundPriceCents/Currency/Date` on thread_candidates - Exchange rates fetched daily from ECB via frankfurter.app with 24h module-level cache - Community price aggregation: PERCENTILE_CONT(0.5) median with 3-report minimum, ownership-validated submissions - Converted prices labeled with ~ prefix and dual display format - `CurrencyContext` interface (currency, market, showConversions) from `useCurrency()` - Market-aware MSRP section on catalog detail page with collapsible "Other Markets" ### Phase 34: i18n Foundation **Goal**: Translation framework in place with string extraction, locale-aware formatting, and at least English + one additional language **Depends on**: Phase 33 **Plans**: 8 plans Plans: - [x] 34-01-PLAN.md — i18next + react-i18next setup, English namespace JSON files - [x] 34-02-PLAN.md — German translations for all 6 namespaces - [x] 34-03-PLAN.md — Component wiring (collection, threads, setups namespaces) - [x] 34-04-PLAN.md — Settings and onboarding namespace wiring - [x] 34-05-PLAN.md — Language picker component in settings - [x] 34-06-PLAN.md — Locale-aware formatting (dates, numbers) - [x] 34-07-PLAN.md — catalog namespace for global-items/discover page - [x] 34-08-PLAN.md — Final wiring and verification **Details:** - react-i18next with i18next-browser-languagedetector - 6 namespaces: common, collection, threads, setups, onboarding, settings (+ catalog added in 34-07) - Detection order: localStorage (key: gearbox-language) then navigator.language - Static lookup tables (icons, CSS) kept at module level; only label strings moved inside components for t() access - English + German locales, language picker in settings --- ## Milestone Summary **Key Decisions:** - isPublic boolean replaced with visibility text column (private/link/public) — RESOLVED - shares table future-proofed for person-specific shares and write permissions — RESOLVED - Share tokens: randomBytes(16).toString("base64url") — 128-bit entropy, URL-safe — RESOLVED - Visibility→private deactivates share links; switching back reactivates non-expired ones — RESOLVED - EUR as default price currency matching existing data assumption — RESOLVED - Module-level caching for exchange rates (simple, effective for single-process) — RESOLVED - Community price aggregation uses PERCENTILE_CONT(0.5) with 3-report minimum — RESOLVED - Detection order for locale: localStorage first, then navigator.language — RESOLVED - defaultNS is common; escapeValue: false (React handles XSS) — RESOLVED **Issues Resolved:** - isPublic boolean → visibility text migration handled with data migration SQL - Dynamic import in setup.service.ts to avoid circular dependency with share.service.ts **Issues Deferred:** - ComparisonTable currency normalization (hooks available, deferred pending real multi-currency test data) - MCP tool currency updates (existing priceCents responses work with currency context client-side) - E2E tests rewrite for OIDC auth (backlog 999.1) **Technical Debt Incurred:** - 6 pending todos deferred to v2.4 (cursor pointers, image loading, auth redirect, add-candidate modal) **Known deferred items at close:** 6 (see STATE.md Deferred Items) --- _For current project status, see .planning/ROADMAP.md_