docs: complete project research
This commit is contained in:
@@ -1,21 +1,28 @@
|
||||
# Feature Research
|
||||
|
||||
**Domain:** Gear management — candidate comparison, setup impact preview, and candidate ranking
|
||||
**Researched:** 2026-03-16
|
||||
**Confidence:** HIGH (existing codebase fully understood; UX patterns verified via multiple sources)
|
||||
**Domain:** Multi-user gear management and discovery platform
|
||||
**Researched:** 2026-04-03
|
||||
**Confidence:** MEDIUM-HIGH
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
This is a subsequent milestone research file for **v1.3 Research & Decision Tools**.
|
||||
The features below are **additive** to v1.2. All three features operate within the existing
|
||||
`threads/$threadId` page and its data model.
|
||||
This is the feature research for **v2.0 Platform Foundation** -- transforming GearBox from a single-user gear tracker into a multi-user platform with discovery, global item database, structured reviews, and setup sharing.
|
||||
|
||||
**Existing data model relevant to this milestone:**
|
||||
- `threadCandidates`: id, threadId, name, weightGrams, priceCents, categoryId, notes, productUrl, imageFilename, status — no rank, pros, or cons columns yet
|
||||
- `setups` + `setupItems`: stores weight/cost per setup item with classification (base/worn/consumable)
|
||||
- `getSetupWithItems` already returns `classification` per item — available for impact preview
|
||||
**Existing features (already built through v1.4):**
|
||||
- Gear collection CRUD with categories, weight/price, images, quantity
|
||||
- Planning threads with candidate comparison, ranking, pros/cons, impact preview
|
||||
- Named setups (loadouts) with classification, donut chart visualization
|
||||
- Search/filter, CSV import/export, item duplication
|
||||
- Dashboard home page, onboarding wizard
|
||||
- Single-user auth (cookie sessions + API keys), MCP server (19 tools)
|
||||
|
||||
**Key project constraints:**
|
||||
- No freeform UGC until moderation infrastructure exists (structured input only)
|
||||
- Discovery-first, not social-first
|
||||
- External auth provider (self-hosted, open-source)
|
||||
- Postgres for multi-user platform
|
||||
|
||||
---
|
||||
|
||||
@@ -23,119 +30,150 @@ The features below are **additive** to v1.2. All three features operate within t
|
||||
|
||||
### Table Stakes (Users Expect These)
|
||||
|
||||
Features users assume exist in any comparison or decision tool. Missing these makes the thread
|
||||
detail page feel incomplete as a decision workspace.
|
||||
Features users assume exist on any multi-user gear platform. Missing these makes the platform feel broken or pointless.
|
||||
|
||||
| Feature | Why Expected | Complexity | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| Side-by-side comparison view | Any comparison tool in any domain shows attributes aligned per-column. Card grid (current) forces mental juggling between candidates. E-commerce, spec sheets, gear apps — all use tabular layout for comparison. | MEDIUM | Rows = attributes (image, name, weight, price, status, notes, link), columns = candidates. Sticky attribute-label column during horizontal scroll. Max 3–4 candidates usable on desktop; 2 on mobile. Toggle between grid view (current) and table view. |
|
||||
| Weight delta per candidate | Gear apps (LighterPack, GearGrams) display weight totals prominently. Users replacing an item need the delta, not just the raw weight of the candidate. | LOW | Pure client-side computation: `candidate.weightGrams - existingItemWeight`. No API call needed if setup data already loaded via `useSetup`. |
|
||||
| Cost delta per candidate | Same reasoning as weight delta. A purchase decision is always the weight vs. cost tradeoff. | LOW | Same pattern as weight delta. Color-coded: green for savings/lighter, red for more expensive/heavier. |
|
||||
| Setup selector for impact preview | User needs to pick which setup to compute deltas against — not all setups contain the same category of item being replaced. | MEDIUM | Dropdown of setup names populated from `useSetups()`. When selected, loads setup via `useSetup(id)`. "No setup selected" state shows raw candidate values only, no delta. |
|
||||
| **User registration and authentication** | Cannot have multi-user without accounts. Every platform has sign-up/login. | HIGH | External auth provider integration (Authentik, Keycloak, or similar). Replaces current single-user cookie auth. All existing entities need userId FK. |
|
||||
| **User profiles (public)** | Every community platform has profiles. Users need identity to share and be discovered. | LOW | Minimal: display name, avatar URL, bio text, joined date. Public profile page lists user's public setups. No follower counts needed. |
|
||||
| **Setup visibility controls** | Users will not share setups if they cannot control what is public. Privacy is table stakes for any sharing platform. | LOW | Binary public/private toggle per setup. Default to private (opt-in sharing). Existing setups migrated as private. |
|
||||
| **Public setup detail pages** | Shared setup links must resolve to a readable page. If sharing is a feature, the shared thing must be viewable. | MEDIUM | Read-only view with item list, weight/cost totals, donut chart, creator attribution. No auth required for public setups. Extends existing setup detail view. |
|
||||
| **Global item database (searchable)** | Users expect to find gear by name rather than entering specs from scratch every time. LighterPack's weakness is fully manual data entry. | HIGH | Central product catalog with brand, model, category, manufacturer weight, MSRP, product URL, image. Users search and link rather than re-enter. Seed with 200-500 items in core categories to bootstrap. This is the foundational dependency for reviews, aggregation, and item detail pages. |
|
||||
| **Link personal items to global items** | Once a global DB exists, users expect to connect their gear to canonical entries for richer data. | MEDIUM | Optional FK from user items to global items. Enables aggregation (owner count, avg weight, reviews). Must handle items not yet in global DB gracefully. |
|
||||
| **Item detail page (aggregated)** | When browsing gear, clicking an item should show consolidated info: specs, who owns it, ratings. Standard on any product platform. | HIGH | Aggregated view combining: manufacturer specs from global DB, owner count, setup appearances, average ratings, crowd-reported weights. This is the integration hub for all platform features. |
|
||||
| **Structured reviews (ratings)** | Any product-oriented community needs evaluation. Users expect to rate gear and see what others think. | MEDIUM | Overall 1-5 star rating plus 3-5 dimension ratings (varies by product category). Attached to global items, not personal items. One review per user per global item. No freeform text per project constraint. |
|
||||
| **Discovery browse page** | Users expect a way to find interesting setups and gear beyond their own collection. Without this, multi-user adds no value. | MEDIUM | Not algorithmic for v2.0. Three sections: recent public setups, recently reviewed items, popular gear (most owned). Simple sorted lists with pagination. |
|
||||
| **Search global items** | Must be able to find products by name/brand in the global database. Powers linking, browsing, and review discovery. | MEDIUM | Full-text search on name, brand, category. Used in "link my item" flow, discovery browsing, and review lookup. Postgres full-text search or trigram index. |
|
||||
|
||||
### Differentiators (Competitive Advantage)
|
||||
|
||||
Features not found in LighterPack, GearGrams, or any other gear app. Directly serve the
|
||||
"decide between candidates" workflow that is unique to GearBox.
|
||||
Features that set GearBox apart from LighterPack, GearGrams, Trailspace, and MyGear. Aligned with core value: "help people make better gear decisions."
|
||||
|
||||
| Feature | Value Proposition | Complexity | Notes |
|
||||
|---------|-------------------|------------|-------|
|
||||
| Drag-to-rank ordering | Makes priority explicit without a numeric input. Ranking communicates "this is my current top pick." Maps to how users mentally stack-rank options during research. No competitor has this in the gear domain. | MEDIUM | `@dnd-kit/sortable` is the current standard (actively maintained; `react-beautiful-dnd` is abandoned as of 2025). Requires new `rank` integer column on `threadCandidates`. Persist order via PATCH endpoint. |
|
||||
| Per-candidate pros/cons fields | Freeform text capturing the reasoning behind ranking. LighterPack and GearGrams have notes per item but no structured decision rationale. Differentiates GearBox as a decision tool, not just a list tracker. | LOW | Two textarea fields per candidate. New `pros` and `cons` text columns on `threadCandidates`. Visible in comparison view rows and candidate edit panel. |
|
||||
| Impact preview with category-matched delta | Setup items have a category. The most meaningful delta is weight saved within the same category (e.g., comparing sleeping pads, subtract current sleeping pad weight from setup total). More actionable than comparing against the entire setup total. | MEDIUM | Use `candidate.categoryId` to find matching setup items and compute delta. Edge case: no item of that category in the setup → show "not in setup." Data already available from `getSetupWithItems`. |
|
||||
| **Crowd-verified specs** | LighterPack trusts user-entered data blindly. GearBox can show "manufacturer says 450g, 12 owners measured avg 478g." Real-world weight verification is unique and high-value for weight-conscious users. | MEDIUM | Aggregate weightGrams from all user items linked to a global item. Compare against manufacturer spec. Display on item detail page. Needs sufficient linked items to be meaningful (threshold: 3+ owners). |
|
||||
| **Review dimensions per product category** | Trailspace and OutdoorGearLab use editorial ratings with fixed dimensions. GearBox crowd-sources structured ratings with category-specific dimensions: a tent gets "weather protection, ventilation, setup ease" while a stove gets "boil time, fuel efficiency, packability." More relevant than one-size-fits-all. | MEDIUM | Define 3-5 rating dimensions per product category via admin config. Store dimension ratings alongside overall rating. Display as radar chart or bar chart on item detail page. |
|
||||
| **"X people own this" social proof** | Shows popularity and real adoption. No gear tracker does this because they lack a global item database. Simple count, powerful signal. | LOW | Count of users who linked a collection item to this global item. Displayed prominently on item detail page and in search results. Zero implementation complexity once linking exists. |
|
||||
| **Setup composition insights** | "This item appears in 47 bikepacking setups, commonly paired with Y and Z." Cross-setup analysis no competitor offers. Answers "what do people use this with?" | MEDIUM | Query across all public setups containing a given global item. Show co-occurrence patterns. Powerful but can be deferred to v2.x if query performance is a concern. |
|
||||
| **Setup impact preview with global items** | Already built for personal items. Extending to global items lets users preview "adding this from the store to my setup changes weight by X." Bridges research and collection management. | LOW | Already exists for personal items. Add "preview in my setup" button on global item detail pages. Reuse existing impact preview logic. |
|
||||
| **Planning threads with global item integration** | Research threads that pull in specs, reviews, and owner data from the global DB. Candidates link to global items for richer comparison than manual data entry. | MEDIUM | Add optional globalItemId to thread candidates. Auto-populate weight, price, image from global item. Show community ratings and owner count inline on candidates. |
|
||||
| **Real-world weight distribution** | Histogram showing "owners report weights between 440g-490g" for a product. Beats a single manufacturer number. Valuable for ultralight community. | LOW | Aggregate weightGrams from all linked items. Display min/max/avg. Histogram if 10+ data points. |
|
||||
| **Copy/fork public setups** | Use someone else's setup as a starting template. LighterPack has clunky CSV-based copying. One-click fork is much better UX. | LOW | Create new setup copying all items from a public setup. Items must exist in user's collection (or be linked to same global items). Clear UX for "items you do not own yet." |
|
||||
|
||||
### Anti-Features (Commonly Requested, Often Problematic)
|
||||
|
||||
| Feature | Why Requested | Why Problematic | Alternative |
|
||||
|---------|---------------|-----------------|-------------|
|
||||
| Custom comparison attributes | "I want to compare battery life, durability, color..." | PROJECT.md explicitly rejects this as a complexity trap. Custom attributes require schema generalization, dynamic rendering, and data entry friction for every candidate. | Notes field and pros/cons fields cover the remaining use cases. |
|
||||
| Score/rating calculation | Automatically rank candidates by computed score | Score algorithms require encoding the user's weight-vs-price preference — personalization complexity. Users distrust opaque scores. | Manual drag-to-rank expresses the user's own weighting without encoding it in an algorithm. |
|
||||
| Side-by-side comparison across threads | Compare candidates from different research threads | Candidates belong to different purchase decisions — mixing them is conceptually incoherent. Different categories are never apples-to-apples. | Thread remains the scope boundary. Cross-thread planning is what setups are for. |
|
||||
| Comparison permalink/share | Share a comparison view URL | GearBox is single-user, no auth for v1. Sharing requires auth, user management, public/private visibility. | Out of scope for v1 per PROJECT.md. Future feature. |
|
||||
| Classification-aware impact preview as MVP requirement | Show delta broken down by base/worn/consumable | While data is available, the classification breakdown adds significant UI complexity. The flat delta answers "will this make my setup lighter?" which is 90% of the use case. | Flat delta for MVP. Classification-aware breakdown as a follow-up enhancement (P2). |
|
||||
| **Freeform text reviews** | Users want to explain their experience in detail | Requires moderation, spam filtering, content policy, reporting infrastructure. PROJECT.md explicitly defers until moderation exists. | Structured ratings with predefined dimensions. Short predefined tags for pros/cons (e.g., "lightweight", "durable", "runs small"). |
|
||||
| **Comments on setups** | Social engagement, questions about gear choices | Moderation burden, notification system, spam, harassment risk. Deferred in PROJECT.md. | Link to user profile. Contact happens outside platform. |
|
||||
| **Follow users / activity feed** | Social graph, staying updated on people | Turns a gear tool into a social network. Notification infrastructure, feed ranking, engagement metrics, retention loops. Project decision: discovery-first, not social-first. | Discovery feed shows popular/recent content without requiring social connections. |
|
||||
| **Marketplace / buy-sell** | Users want to trade used gear | Payment processing, fraud prevention, disputes, shipping logistics, tax compliance. Massive liability. | Link to product URLs on global items. Users buy through retailers. |
|
||||
| **AI gear recommendations** | "What tent should I buy for bikepacking?" | Training data requirements, bias, liability for bad recommendations, hallucination risk. | Global item pages with ratings, owner counts, and setup co-occurrence do implicit recommendation. "People who own X also own Y." |
|
||||
| **Wiki-style open item editing** | Community wants to correct/enrich global item specs | Edit wars, vandalism, quality degradation, dispute resolution. PROJECT.md explicitly rules this out. | Structured contributions only: report measured weight, submit rating. Admin approval for spec corrections. Trusted contributor program later. |
|
||||
| **Price tracking / deal alerts** | Users want to know when gear goes on sale | Requires scraping retailer sites, fragile, legal gray area, maintenance burden. PROJECT.md rules this out. | Store product URL so users can check prices manually. |
|
||||
| **Real-time collaborative setups** | "Plan a group trip together" | WebSocket infrastructure, conflict resolution, permissions model, presence indicators. Massive complexity for niche use case. | Each user builds their own setup. Fork public setups as templates. |
|
||||
| **Gamification (badges, points, levels)** | Drive engagement and contributions | Incentivizes quantity over quality. Users game systems for points rather than providing genuine data. Creates toxic dynamics. | Soft social proof: "contributed X reviews" on profile. No points, no leaderboards. |
|
||||
| **Instagram-style infinite scroll feed** | Addictive browsing experience | Engagement-maximizing design conflicts with utility-focused tool. Users come to research decisions, not scroll endlessly. | Paginated, filterable discovery page. Browse with intent, not addiction. |
|
||||
|
||||
---
|
||||
|
||||
## Feature Dependencies
|
||||
|
||||
```
|
||||
[Side-by-side comparison view]
|
||||
└──requires──> [All candidate fields visible in UI]
|
||||
(weightGrams, priceCents, notes, productUrl already in schema)
|
||||
└──enhances──> [Pros/cons fields] (displayed as comparison rows)
|
||||
└──enhances──> [Drag-to-rank] (rank number shown as position in comparison columns)
|
||||
└──enhances──> [Impact preview] (delta displayed per-column inline)
|
||||
|
||||
[Impact preview (weight + cost delta)]
|
||||
└──requires──> [Setup selector] (user picks which setup to compute delta against)
|
||||
└──requires──> [Setup data client-side] (useSetup hook already exists, no new API)
|
||||
└──requires──> [Candidate weight/price data] (already in threadCandidates schema)
|
||||
|
||||
[Setup selector]
|
||||
└──requires──> [useSetups() hook] (already exists in src/client/hooks/useSetups.ts)
|
||||
└──requires──> [useSetup(id) hook] (already exists, loads items with classification)
|
||||
|
||||
[Drag-to-rank]
|
||||
└──requires──> [rank INTEGER column on threadCandidates] (new — schema migration)
|
||||
└──requires──> [PATCH /api/threads/:id/candidates/rank endpoint] (new API endpoint)
|
||||
└──enhances──> [Side-by-side comparison] (rank visible as position indicator)
|
||||
└──enhances──> [Card grid view] (rank badge on each CandidateCard)
|
||||
|
||||
[Pros/cons fields]
|
||||
└──requires──> [pros TEXT column on threadCandidates] (new — schema migration)
|
||||
└──requires──> [cons TEXT column on threadCandidates] (new — schema migration)
|
||||
└──requires──> [updateCandidateSchema extended] (add pros/cons to Zod schema)
|
||||
└──enhances──> [CandidateForm edit panel] (new textarea fields)
|
||||
└──enhances──> [Side-by-side comparison] (pros/cons rows in comparison table)
|
||||
[External Auth Provider]
|
||||
|
|
||||
v
|
||||
[Multi-User Data Model (userId FK on all entities)]
|
||||
|
|
||||
+---> [Postgres Migration] (concurrent access, auth provider needs Postgres)
|
||||
|
|
||||
+---> [User Profiles (public)]
|
||||
| |
|
||||
| +---> [Public Profile Pages]
|
||||
| | |
|
||||
| | +---> [Discovery Feed (browse users' public content)]
|
||||
| |
|
||||
| +---> [Setup Visibility Controls (public/private)]
|
||||
| |
|
||||
| +---> [Public Setup Detail Pages]
|
||||
| |
|
||||
| +---> [Copy/Fork Public Setups]
|
||||
|
|
||||
+---> [Global Item Database]
|
||||
|
|
||||
+---> [Search Global Items]
|
||||
|
|
||||
+---> [Link Personal Items to Global Items]
|
||||
| |
|
||||
| +---> [Owner Count ("X people own this")]
|
||||
| |
|
||||
| +---> [Crowd-Verified Specs (aggregated weight)]
|
||||
| |
|
||||
| +---> [Setup Appearances Count]
|
||||
| |
|
||||
| +---> [Real-World Weight Distribution]
|
||||
|
|
||||
+---> [Structured Reviews]
|
||||
| |
|
||||
| +---> [Review Dimensions per Category]
|
||||
| |
|
||||
| +---> [Average Ratings Display]
|
||||
|
|
||||
+---> [Item Detail Pages (aggregated hub)]
|
||||
| |
|
||||
| +---> [Setup Composition Insights]
|
||||
|
|
||||
+---> [Planning Thread Global Item Integration]
|
||||
|
|
||||
+---> [Candidate Auto-populate from Global DB]
|
||||
```
|
||||
|
||||
### Dependency Notes
|
||||
|
||||
- **Side-by-side comparison is independent of schema changes.** It can be built using
|
||||
existing candidate data. No migrations required. Delivers value immediately.
|
||||
- **Impact preview is independent of schema changes.** Uses existing `useSetups` and
|
||||
`useSetup` hooks client-side. Delta computation is pure math in the component.
|
||||
No new API endpoint needed for MVP.
|
||||
- **Drag-to-rank requires schema migration.** `rank` column must be added to
|
||||
`threadCandidates`. Default ordering on migration = `createdAt` ascending.
|
||||
- **Pros/cons requires schema migration.** Two nullable `text` columns on
|
||||
`threadCandidates`. Low risk — nullable, backwards compatible.
|
||||
- **Comparison view enhances everything.** Best delivered after rank and pros/cons
|
||||
schema work is done so the full table is useful from day one.
|
||||
- **Multi-user data model is the absolute foundation.** Every feature depends on userId ownership. Items, setups, threads, categories, reviews -- all need user scoping. This is the biggest single migration.
|
||||
- **Postgres migration is coupled with auth.** The external auth provider (Authentik, Keycloak) needs Postgres. Migrating the app DB at the same time avoids running two databases. Do these together.
|
||||
- **Global item database is the second foundation.** Reviews, item detail pages, owner counts, crowd-verified specs, and planning thread integration all depend on canonical global item records. Without this, multi-user is just "LighterPack with accounts."
|
||||
- **Structured reviews require global items.** Reviews attach to global items, not personal collection items. Otherwise reviews fragment across duplicate user-entered items with no way to aggregate.
|
||||
- **Item detail pages are the integration point.** They combine global item specs, aggregated user data, reviews, owner count, and setup appearances. Should be built after all data sources exist.
|
||||
- **Discovery feed requires profiles + public content.** Cannot browse without user identity and visibility controls producing public content to show.
|
||||
- **Linking is the bridge.** Personal items link to global items. This single FK enables owner count, crowd-verified specs, weight distribution, and setup appearances. Prioritize this flow.
|
||||
|
||||
---
|
||||
|
||||
## MVP Definition
|
||||
|
||||
### Launch With (v1.3 milestone)
|
||||
### Launch With (v2.0 Platform Foundation)
|
||||
|
||||
- [ ] **Side-by-side comparison view** — Core deliverable. Replace mental juggling of the card
|
||||
grid with a scannable table. No schema changes. Highest ROI, lowest risk.
|
||||
- [ ] **Impact preview: flat weight + cost delta per candidate** — Shows `+/- X g` and
|
||||
`+/- $Y` vs. the selected setup. Pure client-side math. No schema changes.
|
||||
- [ ] **Setup selector** — Dropdown of user's setups. Required for impact preview. One
|
||||
interaction: pick a setup, see deltas update.
|
||||
- [ ] **Drag-to-rank** — Requires `rank` column migration. `@dnd-kit/sortable` handles
|
||||
the drag UX. Persist via new PATCH endpoint.
|
||||
- [ ] **Pros/cons text fields** — Requires `pros` + `cons` column migration. Trivially low
|
||||
implementation complexity once schema is in place.
|
||||
- [ ] **External auth provider integration** -- Nothing works without multi-user identity
|
||||
- [ ] **Postgres migration** -- Required for concurrent access; auth provider dependency
|
||||
- [ ] **Multi-user data model** -- userId on items, setups, threads, categories; data isolation
|
||||
- [ ] **User profiles (minimal)** -- Display name, avatar, bio; public profile page
|
||||
- [ ] **Setup visibility controls** -- Public/private toggle, default private
|
||||
- [ ] **Public setup detail pages** -- Shareable read-only view with attribution
|
||||
- [ ] **Global item database with seed data** -- Schema, admin seeding, search
|
||||
- [ ] **Link personal items to global items** -- Association flow in collection UI
|
||||
- [ ] **Structured reviews** -- Overall rating + dimension ratings on global items
|
||||
- [ ] **Item detail pages** -- Aggregated specs, owner count, average ratings
|
||||
- [ ] **Discovery browse page** -- Recent public setups, recently reviewed, popular items
|
||||
|
||||
### Add After Validation (v1.x)
|
||||
### Add After Validation (v2.x)
|
||||
|
||||
- [ ] **Classification-aware impact preview** — Delta broken down by base/worn/consumable.
|
||||
Higher complexity UI. Add once flat delta is validated as useful.
|
||||
Trigger: user feedback requests "which classification does this affect?"
|
||||
- [ ] **Rank indicator on card grid** — Small "1st", "2nd" badge on CandidateCard.
|
||||
Trigger: users express confusion about which candidate is ranked first without entering
|
||||
comparison view.
|
||||
- [ ] **Comparison view on mobile** — Horizontal scroll works but is not ideal. Consider
|
||||
attribute-focus swipe view. Trigger: usage data shows mobile traffic on thread pages.
|
||||
- [ ] **Crowd-verified specs display** -- "Manufacturer: 450g, Community avg: 478g" (needs 3+ owners per item to be meaningful)
|
||||
- [ ] **Setup composition insights** -- "Commonly paired with" co-occurrence analysis
|
||||
- [ ] **Planning thread global item integration** -- Candidates auto-populate from global DB
|
||||
- [ ] **Popular gear rankings by category** -- Most owned, highest rated per category
|
||||
- [ ] **Copy/fork public setups** -- One-click template from public setups
|
||||
- [ ] **Review dimension customization** -- Admin configures rating dimensions per product category
|
||||
- [ ] **Real-world weight distribution** -- Histogram on item detail pages
|
||||
- [ ] **Global item suggestion workflow** -- Users propose new items for admin review
|
||||
|
||||
### Future Consideration (v2+)
|
||||
### Future Consideration (v3+)
|
||||
|
||||
- [ ] **Comparison permalink** — Requires auth/multi-user work first.
|
||||
- [ ] **Auto-fill from product URL** — Fragile scraping, rejected in PROJECT.md.
|
||||
- [ ] **Custom comparison attributes** — Explicitly rejected in PROJECT.md.
|
||||
- [ ] **Freeform reviews with moderation** -- After moderation infrastructure exists
|
||||
- [ ] **Comments on setups** -- After moderation infrastructure exists
|
||||
- [ ] **Follow users / activity feed** -- After discovery model is validated
|
||||
- [ ] **OAuth / social login** -- After external auth provider is stable
|
||||
- [ ] **Trusted contributor program** -- Verified users can edit global item specs
|
||||
|
||||
---
|
||||
|
||||
@@ -143,120 +181,122 @@ Features not found in LighterPack, GearGrams, or any other gear app. Directly se
|
||||
|
||||
| Feature | User Value | Implementation Cost | Priority |
|
||||
|---------|------------|---------------------|----------|
|
||||
| Side-by-side comparison view | HIGH | MEDIUM | P1 |
|
||||
| Setup impact preview (flat delta) | HIGH | LOW | P1 |
|
||||
| Setup selector for impact preview | HIGH | LOW | P1 |
|
||||
| Drag-to-rank ordering | MEDIUM | MEDIUM | P1 |
|
||||
| Pros/cons text fields | MEDIUM | LOW | P1 |
|
||||
| Classification-aware impact preview | MEDIUM | HIGH | P2 |
|
||||
| Rank indicator on card grid | LOW | LOW | P2 |
|
||||
| Mobile-optimized comparison view | LOW | MEDIUM | P3 |
|
||||
| External auth provider | HIGH | HIGH | P1 |
|
||||
| Postgres migration | HIGH | HIGH | P1 |
|
||||
| Multi-user data model (userId on entities) | HIGH | HIGH | P1 |
|
||||
| User profiles (basic) | HIGH | LOW | P1 |
|
||||
| Setup visibility controls | HIGH | LOW | P1 |
|
||||
| Public setup detail pages | HIGH | MEDIUM | P1 |
|
||||
| Global item database (schema + seed) | HIGH | HIGH | P1 |
|
||||
| Link personal items to global items | HIGH | MEDIUM | P1 |
|
||||
| Search global items | HIGH | MEDIUM | P1 |
|
||||
| Structured reviews | HIGH | MEDIUM | P1 |
|
||||
| Item detail pages (aggregated) | HIGH | HIGH | P1 |
|
||||
| Discovery browse page | MEDIUM | MEDIUM | P1 |
|
||||
| Crowd-verified specs | HIGH | LOW | P2 |
|
||||
| Setup composition insights | MEDIUM | MEDIUM | P2 |
|
||||
| Planning thread global DB integration | MEDIUM | MEDIUM | P2 |
|
||||
| Copy/fork public setups | MEDIUM | LOW | P2 |
|
||||
| Popular gear rankings | MEDIUM | LOW | P2 |
|
||||
| Freeform reviews + moderation | MEDIUM | HIGH | P3 |
|
||||
| Follow users | LOW | MEDIUM | P3 |
|
||||
| Setup comments | LOW | MEDIUM | P3 |
|
||||
|
||||
**Priority key:**
|
||||
- P1: Must have for this milestone launch
|
||||
- P2: Should have, add when possible
|
||||
- P3: Nice to have, future consideration
|
||||
- P1: Must have for v2.0 platform launch
|
||||
- P2: Should have, add in v2.x once core is validated
|
||||
- P3: Future consideration, requires new infrastructure (moderation, notifications)
|
||||
|
||||
---
|
||||
|
||||
## Competitor Feature Analysis
|
||||
|
||||
| Feature | LighterPack | GearGrams | OutPack | Our Approach |
|
||||
|---------|-------------|-----------|---------|--------------|
|
||||
| Side-by-side candidate comparison | None (list only) | None (library + trip list) | None | Inline comparison table on thread detail page, toggle from grid view |
|
||||
| Impact preview / weight delta | None (duplicate lists manually to compare) | None (no delta concept) | None | Per-candidate delta vs. selected setup, computed client-side |
|
||||
| Candidate ranking | None | None | None | Drag-to-rank with persisted `rank` column |
|
||||
| Pros/cons annotation | None (notes field only) | None (notes field only) | None | Dedicated `pros` and `cons` fields separate from general notes |
|
||||
| Status tracking | None | "wish list" item flag only | None | Already built in v1.2 (researching/ordered/arrived) |
|
||||
| Feature | LighterPack | GearGrams | Trailspace | MyGear | GearBox v2.0 |
|
||||
|---------|-------------|-----------|------------|--------|-------------|
|
||||
| Gear lists/setups | Yes, drag-and-drop | Yes, trip-based | No (review only) | Yes, "Locker" | Yes, named setups with classification |
|
||||
| Weight tracking | Base/worn/consumable | Carried/worn/consumable | No | Basic | Base/worn/consumable + unit conversion + donut charts |
|
||||
| User profiles | Minimal (no bio) | Minimal | Review history page | Full social profile | Display name, avatar, bio, public setups |
|
||||
| Sharing | Public link, embed code | Public link | N/A | Social feed posts | Public/private toggle, shareable URLs |
|
||||
| Global item database | No (all user-entered) | No | Yes (editorial catalog) | No | Yes, seeded + crowd-enriched with verified specs |
|
||||
| Structured reviews | No | No | Yes (summary/pros/cons + rating) | Basic star rating | Dimension ratings per product category |
|
||||
| Item aggregation | No | No | Editorial scores only | No | Owner count, avg weight, setup appearances, crowd specs |
|
||||
| Discovery/browse | No | No | Browse by category | AI-tagged social feed | Browse setups, items, popular gear (intent-driven, not feed) |
|
||||
| Purchase research | No | No | Price comparison links | No | Planning threads with candidates, ranking, impact preview |
|
||||
| Crowd-verified specs | No | No | No | No | Manufacturer vs. community-measured weight comparison |
|
||||
| Mobile app | No | Yes (iOS/Android) | No | Yes (iOS/Android) | No (responsive web, per project constraint) |
|
||||
|
||||
**Key insight:** No existing gear management tool has a comparison view, delta preview, or
|
||||
ranking system for candidates within a research thread. This is an unmet-need gap.
|
||||
The features are adapted from general product comparison UX (e-commerce) to the gear domain.
|
||||
### Competitive Positioning
|
||||
|
||||
GearBox occupies a unique niche: the only platform combining **gear management** (LighterPack's strength), **structured community reviews** (Trailspace's strength), and **crowd-verified specs** (nobody does this). The planning threads feature has no direct competitor equivalent in the gear domain.
|
||||
|
||||
**Key advantages over each competitor:**
|
||||
- **vs. LighterPack:** Global item database eliminates manual spec entry. Multi-user with profiles and sharing. Structured reviews provide community intelligence.
|
||||
- **vs. GearGrams:** Richer comparison tools (planning threads). Crowd-verified specs. Item detail pages with aggregated data.
|
||||
- **vs. Trailspace:** Not just reviews -- full gear management and setup composition. Users own and track their gear, not just review it. Crowd ratings, not editorial-only.
|
||||
- **vs. MyGear:** Not social-first (no engagement loops, no AI tagging gimmicks). Utility-focused: research decisions, verify specs, compare options. Hobby-agnostic data model.
|
||||
|
||||
**Accepted gaps:**
|
||||
- No mobile native app (web-first, responsive design sufficient per project constraints)
|
||||
- No social feed in the Instagram sense (intentional: discovery-first, not social-first)
|
||||
- No freeform text content (intentional: structured input only until moderation exists)
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes by Feature
|
||||
## Implementation Notes for Key Features
|
||||
|
||||
### Side-by-side Comparison View
|
||||
### Global Item Database Schema
|
||||
|
||||
- Rendered as a transposed table: rows = attribute labels, columns = candidates.
|
||||
- Rows: Image (thumbnail), Name, Weight, Price, Status, Notes, Link, Pros, Cons, Rank, Impact Delta (weight), Impact Delta (cost).
|
||||
- Sticky first column (attribute label) while candidate columns scroll horizontally for 3+.
|
||||
- Candidate images at reduced aspect ratio (square thumbnail ~80px).
|
||||
- Weight/price cells use existing `formatWeight` / `formatPrice` formatters with the user's preferred unit.
|
||||
- Status cell reuses existing `StatusBadge` component.
|
||||
- "Pick as winner" action available per column (reuses existing `openResolveDialog`).
|
||||
- Toggle between grid view (current) and table view. Preserve both modes. Default to grid;
|
||||
user activates comparison mode explicitly.
|
||||
- Comparison mode is a UI state only (Zustand or local component state) — no URL change needed.
|
||||
The global item table is distinct from user items. It represents canonical products:
|
||||
|
||||
### Impact Preview
|
||||
- `globalItems`: id, brand, model, name (display), categoryId, manufacturerWeightGrams, manufacturerPriceCents, productUrl, imageFilename, description, createdAt, updatedAt, createdByUserId
|
||||
- User items get optional `globalItemId` FK for linking
|
||||
- Admin-seeded initially; later users can suggest additions via a proposal workflow
|
||||
|
||||
- Setup selector: `<select>` or custom dropdown populated from `useSetups()`.
|
||||
- On selection: load setup via `useSetup(id)`. Compute delta per candidate:
|
||||
`candidate.weightGrams - matchingCategoryWeight` where `matchingCategoryWeight` is the
|
||||
sum of setup item weights in the same category as the thread.
|
||||
- Delta display: colored pill on each candidate column in comparison view:
|
||||
- Negative delta (lighter) = green, prefixed with "−"
|
||||
- Positive delta (heavier) = red, prefixed with "+"
|
||||
- Zero = neutral gray
|
||||
- Same pattern for cost delta.
|
||||
- "No setup selected" state = no delta row shown.
|
||||
- "Category not in setup" state = "not in setup" label instead of delta.
|
||||
- No new API endpoints required. All data is client-side once setups are loaded.
|
||||
### Structured Review Schema
|
||||
|
||||
### Drag-to-Rank
|
||||
- `reviews`: id, userId, globalItemId, overallRating (1-5), createdAt, updatedAt
|
||||
- `reviewDimensionRatings`: id, reviewId, dimensionId, rating (1-5)
|
||||
- `reviewDimensions`: id, categoryId, name (e.g., "durability", "packability"), sortOrder
|
||||
- Unique constraint: one review per user per global item
|
||||
- Dimensions are per-category, admin-defined
|
||||
|
||||
- `@dnd-kit/sortable` with `SortableContext` wrapping the candidate list.
|
||||
- `useSortable` hook per candidate with a drag handle (Lucide `grip-vertical` icon).
|
||||
- Drag handle visible always (not hover-only) so the affordance is clear.
|
||||
- On `onDragEnd`: recompute ranks using `arrayMove()`, call
|
||||
`PATCH /api/threads/:threadId/candidates/rank` with `{ orderedIds: number[] }`.
|
||||
- Server endpoint: bulk update `rank` for each candidate ID in the thread atomically.
|
||||
- `rank` column: `INTEGER` nullable. Null = unranked (treated as lowest rank). Default to
|
||||
`createdAt` order on first explicit rank save.
|
||||
- Rank number badge: displayed on each CandidateCard corner (small gray circle, "1", "2", "3").
|
||||
- Works in both grid view and comparison view.
|
||||
### Discovery Feed Approach
|
||||
|
||||
### Pros/Cons Fields
|
||||
Not a personalized algorithmic feed. Three content streams, each a simple sorted query:
|
||||
|
||||
- Two `textarea` inputs added to the existing `CandidateForm` (slide-out panel).
|
||||
- Labels: "Pros" and "Cons" — plain text, no icons.
|
||||
- Displayed below the existing Notes field in the form.
|
||||
- Extend `updateCandidateSchema` with `pros: z.string().optional()` and `cons: z.string().optional()`.
|
||||
- In comparison table: pros and cons rows display as plain text, line-wrapped.
|
||||
- In card grid: pros/cons not shown on card surface (too much density). Visible only in edit
|
||||
panel and comparison view.
|
||||
1. **Recent public setups** -- ORDER BY createdAt DESC, paginated
|
||||
2. **Recently reviewed items** -- Global items with recent reviews, ORDER BY latest review date
|
||||
3. **Popular gear** -- Global items ORDER BY linked owner count DESC
|
||||
|
||||
### Schema Changes Required
|
||||
No recommendation engine. No engagement scoring. Users browse with intent.
|
||||
|
||||
Two schema migrations needed for this milestone:
|
||||
### User Profile Data
|
||||
|
||||
```sql
|
||||
-- Migration 1: Candidate rank
|
||||
ALTER TABLE thread_candidates ADD COLUMN rank INTEGER;
|
||||
Minimal profile extending the auth provider's user record:
|
||||
|
||||
-- Migration 2: Candidate pros/cons
|
||||
ALTER TABLE thread_candidates ADD COLUMN pros TEXT;
|
||||
ALTER TABLE thread_candidates ADD COLUMN cons TEXT;
|
||||
```
|
||||
|
||||
Both columns are nullable and backwards compatible. Existing candidates get `NULL` values.
|
||||
UI treats `NULL` rank as unranked, `NULL` pros/cons as empty string.
|
||||
- Display name (from auth provider or custom)
|
||||
- Avatar URL (from auth provider or uploaded)
|
||||
- Bio (short text, 280 char limit)
|
||||
- Joined date
|
||||
- Public setups list (derived from setup visibility)
|
||||
- Review count (derived)
|
||||
- Collection size (count of items, public stat)
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- [Designing The Perfect Feature Comparison Table — Smashing Magazine](https://www.smashingmagazine.com/2017/08/designing-perfect-feature-comparison-table/) — table layout patterns, sticky headers, progressive disclosure (HIGH confidence)
|
||||
- [Comparison Tables for Products, Services, and Features — Nielsen Norman Group](https://www.nngroup.com/articles/comparison-tables/) — information architecture for comparison, anti-patterns (HIGH confidence)
|
||||
- [The Ultimate Drag-and-Drop Toolkit for React: @dnd-kit — BrightCoding (2025)](https://www.blog.brightcoding.dev/2025/08/21/the-ultimate-drag-and-drop-toolkit-for-react-a-deep-dive-into-dnd-kit/) — confirmed dnd-kit as current standard, react-beautiful-dnd abandoned (HIGH confidence)
|
||||
- [dnd-kit Sortable Docs](https://docs.dndkit.com/presets/sortable) — SortableContext, useSortable, arrayMove patterns (HIGH confidence)
|
||||
- [Ultralight: The Gear Tracking App I'm Leaving LighterPack For — TrailsMag](https://trailsmag.net/blogs/hiker-box/ultralight-the-gear-tracking-app-i-m-leaving-lighterpack-for) — LighterPack feature gap analysis (MEDIUM confidence)
|
||||
- [Comparing products: UX design best practices — Contentsquare](https://contentsquare.com/blog/comparing-products-design-practices-to-help-your-users-avoid-fragmented-comparison-7/) — fragmented comparison UX pitfalls (HIGH confidence)
|
||||
- [Drag and drop UI examples and UX tips — Eleken](https://www.eleken.co/blog-posts/drag-and-drop-ui) — drag affordance and visual feedback patterns (MEDIUM confidence)
|
||||
- GearBox codebase analysis (src/db/schema.ts, src/server/services/, src/client/hooks/) — confirmed existing data model, no rank/pros/cons columns present (HIGH confidence)
|
||||
- [LighterPack](https://lighterpack.com/) -- Gear list builder, community standard for ultralight hikers. Public sharing via link, no profiles or reviews.
|
||||
- [LighterPack tutorial (99Boulders)](https://www.99boulders.com/lighterpack-tutorial) -- Feature overview including sharing, linking, limitations.
|
||||
- [GearGrams](https://www.geargrams.com/) -- Trip-based gear list tracker with weight classification.
|
||||
- [Trailspace](https://www.trailspace.com/) -- User gear reviews with structured Summary/Pros/Cons format and Review Corps program.
|
||||
- [Trailspace Review Form](https://www.trailspace.com/blog/2012/02/29/new-gear-review-form.html) -- Details on structured review fields with category-specific suggestions.
|
||||
- [MyGear](https://mygear.world/) -- Social app for sports gear with Locker, feed, AI gear recognition, challenges.
|
||||
- [Outdoor Gear Lab](https://www.outdoorgearlab.com/) -- Professional structured gear reviews with side-by-side comparison methodology.
|
||||
- [Ultralight App](https://trailsmag.net/blogs/hiker-box/ultralight-the-gear-tracking-app-i-m-leaving-lighterpack-for) -- LighterPack alternative analysis showing community pain points.
|
||||
- [Ready Set Sim](https://www.readysetsim.com/) -- Sim racing gear profiles and build sharing (cross-domain reference for hobby-agnostic patterns).
|
||||
- [GetStream Social Feed Architecture](https://getstream.io/blog/social-media-feed/) -- Feed implementation patterns and anti-patterns.
|
||||
|
||||
---
|
||||
*Feature research for: GearBox v1.3 — candidate comparison, setup impact preview, candidate ranking*
|
||||
*Researched: 2026-03-16*
|
||||
*Feature research for: GearBox v2.0 Platform Foundation -- multi-user gear discovery platform*
|
||||
*Researched: 2026-04-03*
|
||||
|
||||
Reference in New Issue
Block a user