Appearance
Challenge System
Spec Source: Document 2 — Challenge System & Track Records (Sections 1--4) | Last Updated: Feb 2026
Overview
A challenge is the core content unit of DoCurious. Challenges are real-world activities that users discover, accept, complete offline, and then document through Track Records. They are not quizzes or digital tasks -- they represent tangible experiences like building a birdhouse, cooking a new recipe, volunteering at a park cleanup, or learning to play a song on guitar. Every challenge lives on the platform as a browsable listing that any user can find, start, and complete at their own pace.
The fundamental loop of DoCurious revolves around challenges: a user discovers a challenge (via the Explore page, a community feed, a gift, or a recommendation), accepts it (moving it to their active list), completes the activity in the real world, and then documents what they did by creating a Track Record. That Track Record is then submitted for verification by DoCurious staff, and upon approval the user earns XP, badges, and a permanent record of their accomplishment.
Challenges range from simple single-step activities (like "Try a cuisine you've never had") to multi-milestone guided experiences (like a 7-day sourdough bread project with distinct checkpoints). They can be free or paid, solo or group, indoor or outdoor, beginner or expert. The system is designed so that anyone -- from a 5-year-old doing a craft project with a parent, to an adult learning to weld -- can find something meaningful to try.
How It Works
Challenge Sources
STATUS: BUILT
The three challenge sources are fully modeled in the type system and mock API. Vendor, staff, and user sources are all supported in the data layer.
Challenges enter the platform through three paths:
| Source | Description | Moderation |
|---|---|---|
| Vendor-Created | Challenges created by approved vendor accounts. May involve purchasing kits, booking hosted experiences, or accessing digital guides. Vendors sell through their own external websites and purchase mechanisms. | DoCurious staff reviews the challenge listing before it goes live. |
| Staff-Created | Challenges created by DoCurious staff, sometimes in collaboration with outside experts. Can be free or paid. Used for platform-curated content, seasonal challenges, and editorial picks. | Internal review by the staff team. |
| User-Created | Any general user can create a challenge, but only after registering as a challenge provider (vendor) first. Challenges are created and listed through the vendor creation workflow. Can be free or paid. | Goes through the DoCurious staff review queue before becoming publicly visible. Not live until approved. |
Key rule: Only paid challenges (vendor-created with a cost) can be gifted. Free challenges can be shared or recommended, but not gifted. Both gifted and free challenges can be assigned by organizations (schools). See Gifting for the full gifting model.
Challenge Categories
STATUS: BUILT
The spec's 6 parent categories and 27 subcategories are fully defined in the type system (PARENT_CATEGORIES in challenge.types.ts), seeded in both the FE mock data and backend Prisma seed, and rendered in filter UIs. Category management is currently hardcoded -- the planned admin-configurable interface has not been built.
Categories and subcategories are managed by DoCurious staff. Currently, changes require code changes by the dev team. An admin-configurable category management interface (allowing staff to add, rename, reorder, or archive categories without code changes) is a planned platform feature.
A challenge can belong to one or more categories. Categories power the Explore page filtering, Best Fit recommendations, and the Journey Map gamification feature.
Full Category and Subcategory List
1. Create & Express
| Subcategory | Examples |
|---|---|
| Decorative Arts & Crafts | Drawing, painting, sculpting, photography, videography |
| DIY & Handicrafts | Wood/metal working, knitting, leatherwork, fly tying |
| Music, Dance, & Performance | Playing an instrument, singing, dancing, acting, circus arts |
| Writing & Storytelling | Poetry, fiction, journalism |
| Fashion & Costume Design | Sewing, garment design, prop making |
2. Build, Engineer, & Operate
| Subcategory | Examples |
|---|---|
| Construction & Repair | Carpentry, plumbing, electrical, home repair |
| STEM, Engineering, & Invention | Robotics, manufacturing, electronics, chemistry, prototyping |
| Aviation & Flight | Flying drones, piloting planes, building aircraft/kites |
| Watercraft | Operating canoes, rowboats, sailboats, power boats, boat building |
| Vehicles & Transportation | Driving & building bicycles, motorcycles, mechanics |
3. Move & Compete
| Subcategory | Examples |
|---|---|
| Sports & Fitness | Team sports, golf, running, weightlifting |
| Outdoor Adventure | Hiking, climbing, camping, orienteering, geocaching |
| Puzzles & Games | Escape rooms, board games, puzzles |
| Competitive Skills | Karate, fencing, archery, marksmanship, boxing |
| Equestrian & Animal Sports | Horseback riding, agility trials |
4. Connect & Serve
| Subcategory | Examples |
|---|---|
| Volunteering & Service Projects | Building for others, park cleanups, charity events |
| Teaching & Mentoring | Tutoring, leading workshops, guidance |
| Community Building | Event organizing, neighborhood projects, safety |
| Cultural Exchange | Customs, language practice, hosting exchanges |
5. Learn & Discover
| Subcategory | Examples |
|---|---|
| Academic & Knowledge Exploration | History, math, literature, science, languages, sign language |
| Nature & Environment | Birdwatching, identifying rocks/plants/animals, ecology |
| Self-Discovery & Reflection | Journaling, meditation, yoga, relationships |
| Practical Skills & Preparedness | Tying shoes, personal finance, changing tires, basic first aid, public speaking |
6. Care & Cultivate
| Subcategory | Examples |
|---|---|
| Animal Interaction | Farm animals, pets, training, caring for |
| Gardening & Horticulture | Care/growing of plants, landscaping |
| Cooking & Nutrition | Meal prep, baking, nutrition planning |
| Health & Wellness | Fitness, diet, sleep, mindfulness, mental health |
Functional Tags
STATUS: BUILT
Challenge tags are fully implemented in the type system and used for filtering in the explore/browse pages. Tags support categories including activity type, difficulty level, location, and custom vendor tags.
Functional tags are applied across all categories. They do not determine what a challenge is -- they describe how it works. A single challenge can have multiple tags from each group.
| Tag Group | Options |
|---|---|
| Delivery method | Hosted, Digitally Guided, Kit |
| Participation | Solo, Couple, Family, Group |
| Age audience | Kid-Oriented, Family, All Ages, Adult-Oriented |
| Cost | Free, Paid |
| Difficulty | Beginner, Intermediate, Advanced, Expert |
| Duration | Less than half day, Less than 1 day, Multi-day, Ongoing |
| Setting | Indoors, Outdoors, Either or Both |
| Seasonality | Seasonal, Year-round |
| Equipment | Needs Equipment, No Equipment Needed |
Age audience tooltip definitions:
- Kid-Oriented -- Designed for children to do on their own or with light adult help. Examples: beginner crafts, simple outdoor games, first-time skill challenges.
- Family -- Meant for parents, kids, and families to do together. Examples: building projects, family hikes, cooking together.
- All Ages -- Suitable for both kids and adults without feeling too childish or too advanced. Examples: gardening, basic photography, community service.
- Adult-Oriented -- Primarily for adults or older teens. These challenges may require advanced skills, tools, or higher patience levels, but contain no explicit content. Examples: welding or metalworking, driving or using machinery, fitness goals, advanced cooking.
Challenge Fields (Structure)
STATUS: BUILT
The Challenge interface in the type system is comprehensive, with 50+ fields covering all spec requirements. The mock API and store support the full field set.
Every challenge has these fields:
| Field | Required? | Notes |
|---|---|---|
| Title | Yes | Max 150 characters |
| Description | Yes | Rich text. What the challenge is and why it is worth doing. |
| Categories | Yes (at least 1) | Select from admin-configured category list. Multi-select. |
| Difficulty Level | Yes | Beginner, Intermediate, Advanced, or Expert |
| Estimated Duration | Yes | Approximate time to complete. Free-text (e.g., "2--3 hours," "1 weekend," "4 weeks"). |
| Age Range | Yes | Minimum and maximum recommended age |
| Solo / Group | Yes | Solo, Group, or Both |
| Cost | Yes | Free, or price/price range. If paid, vendor provides external purchase URL. |
| Fulfillment Type | Yes (if paid) | Kit (physical materials shipped), Hosted (in-person experience at a location), or Digitally Guided (online materials/access) |
| Cover Image | Yes | Primary image displayed on challenge cards |
| Gallery Images | No | Additional images for the challenge detail page |
| Milestones | No | Optional ordered steps. Challenges can have zero milestones (single completion state) or multiple. |
| Instructions / Guide | No | Detailed how-to guidance. May be gated behind acceptance for paid challenges. |
| Materials Needed | No | List of what the user needs before starting |
| Location Requirements | No | Indoor, Outdoor, Specific venue, or None. For hosted challenges, includes venue address. |
| External Purchase URL | Yes (if paid) | Link to vendor's own checkout page |
| Vendor ID | Yes | FK to vendor/provider account. All challenges are created by registered challenge providers. |
Milestones
STATUS: BUILT
Milestones are fully modeled in the type system (ChallengeMilestone interface) and supported in the mock API. The ChallengeDetail page renders milestone overviews.
Milestones are optional ordered steps within a challenge. They help users track incremental progress on longer or more complex challenges.
Zero milestones (simple challenges): The challenge has a single completion state. The user starts it, does the activity, then submits a Track Record. There is no intermediate progress tracking. This is appropriate for single-session activities like "Cook a meal from a cuisine you've never tried."
One or more milestones (structured challenges): Each milestone has a title, description, and order number. Users check off milestones as they progress. Each milestone can prompt a Track Record entry.
Milestone fields:
| Field | Required? | Constraints |
|---|---|---|
| Title | Yes | Max 100 characters |
| Description | No | Rich text |
| Order number | Yes | Integer, determines display sequence |
| Prompt text | No | Suggested Track Record entry for this milestone (e.g., "Share a photo of your design sketch") |
Example: A woodworking challenge might have milestones for "Design your piece," "Cut materials," "Assemble," and "Finish and seal."
Fulfillment Types
STATUS: BUILT
Fulfillment types are defined in the type system and rendered on challenge detail pages. The gift confirmation prompts per fulfillment type are implemented in the gifting flow.
For paid challenges, the fulfillment type determines how the user receives what they need to complete the challenge. This also affects the Gifting confirmation flow.
| Type | Description | Gift Confirmation Prompt |
|---|---|---|
| Kit | Physical materials shipped to the user. User needs to receive the kit before starting. | "Have you received your kit?" |
| Hosted | Real-time experience using a live venue and/or instructor, often at a specific location. User needs to book/confirm attendance. | "Have you confirmed your appointment or reservation information?" |
| Digitally Guided | Online materials, access codes, or digital guides. User needs to confirm access. | "Do you have access to the materials?" |
Challenge Creation Workflow
Vendor Challenge Creation
STATUS: BUILT
The CreateChallengeModal component and createChallenge store action are implemented. The mock API creates challenges in draft status and supports the submitForReview flow. However, several creation form fields are currently missing from the UI (fulfillment type, cost, location, solo/group, cover image upload, verification requirements, teacher tips, resource links).
The vendor creation workflow follows these steps:
- Vendor logs in and navigates to their vendor dashboard.
- Clicks "Create New Challenge."
- Fills in all required fields (see Challenge Fields above). Includes external purchase URL and fulfillment type since most vendor challenges are paid.
- Optionally adds milestones in order.
- Submits for review.
- Challenge enters the DoCurious staff review queue.
- Staff reviews for quality, safety, accuracy, and age-appropriateness.
- Staff approves -- challenge goes live. OR Staff rejects with feedback -- vendor can revise and resubmit.
User-to-Provider Registration
STATUS: BUILT
The "Become a Challenge Provider" flow is fully implemented in the frontend. Users can self-register as vendors through a complete UI flow with application submission and approval tracking.
General users cannot create challenges from their user account. To create challenges, any user must register as a challenge provider (vendor). Registration is open to everyone -- individuals, businesses, nonprofits, educators -- and challenges created by providers can be free or paid.
Registration flow:
- User navigates to "Become a Challenge Provider" (accessible from profile settings or Vendor Program page).
- Completes the provider application with required information.
- Application enters DoCurious staff review queue.
- Staff approves -- user gains provider role and access to the vendor dashboard. OR Staff rejects with feedback -- user can revise and resubmit.
Once approved, the user's account gains the vendor role in addition to their existing roles. They access the vendor dashboard through the context switcher. All challenge creation then follows the vendor workflow described above.
Staff Challenge Creation
STATUS: BUILT
Staff challenge creation and management is implemented through the admin ChallengeApprovalQueue and ChallengeManagement pages. Staff can create, review, approve, and manage challenges through the admin panel.
DoCurious staff can create challenges directly from the admin panel. These bypass the review queue (internal review only). Staff-created challenges can be free or paid.
Challenge Editing Rules
STATUS: BUILT
The updateChallenge API endpoint exists and enforces ownership checks. The ChallengeVersionHistory component is built. Locked-field enforcement is implemented: when editing an approved challenge via ?edit=<id>, title, category, difficulty, and price are read-only with lock icons. Edits to approved challenges are stored as pending revisions rather than modifying the live challenge directly. A banner informs vendors that edits will be submitted for review.
After a challenge is live, editing rules differ by role:
Vendors/Providers:
- Can submit edits to any field on their challenges
- All edits to live challenges are reviewed by DoCurious admins before going live (to prevent insertion of inappropriate content or ToS violations)
- The existing version remains live until the edit is approved or rejected
- As platform traffic increases, AI-based automated review for ToS violations will supplement manual admin review
- Price changes trigger a notification to any user who has the challenge in their Bucket List
Staff:
- Can edit any field on any challenge directly without going through the review queue
Version control: The platform uses an edit restriction model. Certain fields are locked once any user has started the challenge:
| Edit Type | Risk Level | Can Edit After Users Start? |
|---|---|---|
| Description, cover image, gallery images, instructions, tips | Low (cosmetic) | Yes -- in-progress users see a "This challenge was updated" banner |
| Milestones (structure, count, order) | High (structural) | No -- locked. Vendor must create a new challenge. |
| Difficulty level | High (structural) | No -- locked |
| Required materials/equipment | High (structural) | No -- locked |
| Verification criteria | High (structural) | No -- locked |
If a locked field needs to change, the vendor must create a new challenge. The original can be marked "superseded by [new challenge]" with a link. In-progress users can complete the original or switch to the new version.
Challenge Detail Page
STATUS: BUILT
The ChallengeDetail.tsx page (56.5KB) is the most substantial page component in the app. It renders a tabbed layout with challenge information, action buttons, and contextual UI based on user status.
When a user clicks on a challenge card, they arrive at the challenge detail page. This page uses a tabbed structure. The content sections below describe what appears on the page.
Tab 1: Challenge Details
The primary information tab visible to all users:
- Cover image and gallery images
- Title, description, and category badges
- Difficulty level, estimated duration, age range, solo/group indicator
- Cost (free or price) with external access/purchase links
- Accessories and add-on links (optional)
- Helpful resource links (optional)
- Fulfillment type badge (Kit / Hosted / Digitally Guided) for paid challenges
- Materials needed (if applicable)
- Location requirements (if applicable)
- Requires Travel indicator (Yes/No)
- Milestones overview (titles only, expandable for descriptions)
- Average review score (from post-challenge survey questions)
- Vendor/provider attribution
Contextual action buttons change based on the user's relationship with the challenge:
| User State | Available Actions |
|---|---|
| Not started | "Sign Up" to begin the challenge |
| Browsing | "Save for Consideration" bookmark icon (Interesting List) |
| Interested | "Save to Bucket List" bucket list icon |
| Viewing a paid challenge | "Gift This Challenge" (paid challenges only) |
| Any state | "Recommend" (share link to any user) |
| In progress | "Continue" button linking to the user's Track Record |
Tab 2: Track Record Gallery
STATUS: BUILT
The TrackRecordGallery component is integrated into ChallengeDetail.tsx as the Gallery tab. It is wired to useChallengeStore.galleryItems with fetchChallengeGallery called on tab activation. Mock gallery items are seeded per challenge.
A public gallery of approved Track Records from users who have completed this challenge. This is the social proof layer -- "here is what others have done."
- Layout: Masonry grid of Track Record cover images (or first entry image if no cover set)
- Featured section: Top 3--5 Track Records curated by DoCurious staff, shown in a highlighted row above the main grid
- Sorting options: Most Recent (default), Most Popular (by thumbs-up count), Featured First
- Pagination: 12 Track Records per page with "Load More" button (not infinite scroll)
- Visibility rule: Only Track Records where the owner has set sharing to "public" appear in the gallery. Private and community-only TRs are never shown here.
Tab 3: Challenge Discussions
STATUS: BUILT
The ChallengeDiscussion component is integrated into ChallengeDetail.tsx as the Discussion tab, wired to useChallengeStore.discussionPosts with full CRUD callbacks (onPost, onEdit, onDelete, onFlag). Mock discussion posts are seeded per challenge. The store supports create, edit, delete, and flag operations through the mock API.
Below the Track Record Gallery, a discussion feed allows any user to post about the challenge itself (not about a specific Track Record). This functions like a product review section:
- Any user who has started or completed the challenge can post
- Posts are threaded one level deep (top-level post with replies)
- Visible to all users viewing the challenge
- Moderated by DoCurious staff (flagging system)
- Vendors can respond to discussions on their own challenges (responses are visually distinguished)
See Communities for community-specific vs. universal discussions.
My Challenges
STATUS: BUILT
The MyChallenges.tsx page is fully implemented with tabbed navigation, the UserChallengeCard component, empty states, and store integration. Stats badges on tabs are wired to fetchMyChallengeStats.
The "My Challenges" section is accessible from the user's dashboard. It organizes a user's challenge lifecycle into tabs.
Tab Structure
| Tab | Contents | Visual Priority |
|---|---|---|
| Invitations | Challenges gifted, recommended, or assigned to the user that have not yet been accepted or declined. Includes gift message, gifter name, and confirmation prompt based on fulfillment type. | Most prominent (leftmost tab, badge count) |
| In Progress | Challenges the user has accepted/started but not yet submitted for verification. Shows milestone progress if applicable. | Second tab |
| In Review | Track Records submitted for DoCurious staff review. User sees submission date and status. | Third tab |
| Completed | Challenges with approved Track Records. Sorted by completion date, most recent first. | Fourth tab |
| Unverified | Track Records that exhausted all verification attempts. | Fifth tab (hidden if empty) |
Tab Behaviors
- Invitations badge: Numeric badge on the Invitations tab showing count of pending invitations. Also reflected on the dashboard notification area.
- In Progress cards: Each card shows challenge title, cover image, progress bar (if milestones exist), time since started, and a "Continue" button that opens the Track Record editor.
- Empty states: Each tab has a friendly empty state message. Invitations: "No pending invitations." In Progress: "Ready to start something new? Explore challenges." Completed: "Your completed challenges will appear here."
Multiple Completions
STATUS: BUILT
Multiple completions are supported in the data model and API. The completionNumber field on UserChallenge tracks which attempt each record represents. The startChallenge API correctly increments the completion count.
Users can complete the same challenge multiple times. Each completion generates a separate Track Record. On the Completed tab, challenges with multiple completions show a count badge (e.g., "x3") and expand to show all Track Records when clicked. The completion_number field (1, 2, 3...) tracks which attempt each Track Record represents.
Challenge Lifecycle
STATUS: BUILT
The full state machine is implemented in the type system (UserChallengeStatus) with 9 states, and the store/API support all transitions: start, accept, decline, abandon. Verification-related transitions (submit, verify, reject, unverify) are modeled but depend on Track Record submission which is separately tracked.
State Machine
A challenge progresses through these states from the user's perspective:
Discovered --> Bookmarked (Interesting List) --> Bucket Listed --> Accepted / In Progress
|
Invited (gift/assign) ----+
|
v
Submitted for Verification
/ \
Verified / \ Rejected (with feedback)
(Completed) (can revise, up to 3 attempts)
|
v
Unverified
(exhausted all attempts)| State | Description |
|---|---|
| Discovered | User sees challenge on Explore page, in a community feed, or via a recommendation link. No state change yet. |
| Bookmarked (Interesting List) | User clicks the bookmark icon. Challenge saved to Interesting list for later consideration. No commitment. |
| Bucket Listed | User moves challenge from Interesting list (or directly adds) to Bucket List. Signal of intent. |
| Invited | Another user gifts, recommends, or assigns this challenge. Appears in the Invitations tab. For gifted challenges, recipient must confirm receipt of materials before the challenge moves to In Progress. |
| Accepted / In Progress | User starts the challenge. A Track Record is created in draft state. Milestone tracking begins if applicable. |
| Submitted for Verification | User submits their Track Record for review. Moves to the In Review tab. |
| Verified / Completed | DoCurious staff approves the Track Record. Challenge moves to Completed tab. XP and badges awarded. |
| Rejected (with feedback) | Staff rejects the Track Record with a reason. User can revise and resubmit. Counts as one verification attempt. |
| Unverified | Track Record has exhausted maximum verification attempts (default: 3). Moves to Unverified tab. |
Abandonment
A user can abandon a challenge at any time while In Progress:
- Challenge is removed from the In Progress tab
- Draft Track Record is preserved (not deleted) but marked as abandoned
- User can restart the same challenge later, creating a new Track Record
- For Dealer's Choice challenges, abandonment carries XP penalties (see Explore for Dealer's Choice mechanics)
Roles & Permissions
| Action | General User | Student | Parent | Teacher | School Admin | Vendor | Platform Admin |
|---|---|---|---|---|---|---|---|
| Browse/discover challenges | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Start a challenge | Yes | Yes | Via child | Yes | Yes | Yes | Yes |
| Create a challenge | Must register as vendor first | No | Must register as vendor | Must register as vendor | Must register as vendor | Yes | Yes |
| Edit own challenges | N/A | N/A | N/A | N/A | N/A | Yes (edits reviewed) | Yes (direct) |
| Edit any challenge | No | No | No | No | No | No | Yes |
| Gift a paid challenge | Yes | Age-restricted | Yes | Yes | Yes (via school flow) | Yes | Yes |
| Assign challenges | No | No | No | Yes (to classes) | Yes (school-wide) | No | Yes |
| Review challenges (approval queue) | No | No | No | No | No | No | Yes |
| Review Track Records | No | No | No | No | No | No | Yes (staff) |
| Feature Track Records | No | No | No | No | No | No | Yes (staff) |
| Respond to challenge discussions | On own challenges only via vendor role | Yes | Yes | Yes | Yes | Yes (own challenges) | Yes |
Constraints & Limits
| Constraint | Value | Rationale |
|---|---|---|
| Title length | Max 150 characters | Fits in card layouts and search results |
| Description | Rich text, no hard limit | Must be at least 100 characters for vendor challenges to pass quality review |
| Categories per challenge | 1 or more (no max) | Allows cross-category discovery |
| Milestones per challenge | 0--10 | 0 = simple challenge; 3--10 for structured challenges per quality rubric |
| Milestone title length | Max 100 characters | Fits in progress UI |
| Milestone prompt text | Max 500 characters | Guides Track Record entries |
| Gallery images | Up to 4 total (including cover) | Keeps detail page focused |
| Cover image minimum resolution | 1200 x 800 pixels | Landscape orientation preferred (16:9 or 3:2) |
| Verification attempts per Track Record | 3 (system-wide default) | Prevents indefinite resubmission while giving fair chances |
| Track Record storage limit | 100MB per TR | Warning at 80%, uploads blocked at 100% |
| Image upload size | Approx. 2MB after auto-resize to 1200px max dimension | Balances quality with storage |
| Document upload size | 25MB per document | PDF, DOC accepted |
| Video/Audio | Links only (YouTube, Vimeo, SoundCloud, Spotify) | No direct upload -- avoids storage/transcoding costs |
| Track Record review SLA | 72-hour target turnaround | Staff performance metric |
| Challenge review target | 3 business days | First 3 challenges from new vendors receive extra scrutiny |
| Comment edit window | 15 minutes after posting | Balances typo fixes with content integrity |
| Comment rate limit | 10 per user per entry per 24h; 20 per user per day globally | Anti-spam protection |
| Featured Track Records per challenge | 3--5 maximum | Keeps the featured row concise |
| Track Record Gallery pagination | 12 per page, "Load More" button | Not infinite scroll |
Design Decisions
Why Users Must Register as Vendors to Create Challenges
The spec explicitly requires that general users cannot create challenges from their user account. Instead, they must register as a challenge provider. This decision ensures:
- Quality control -- All challenge creators go through an approval process
- Accountability -- Provider accounts have additional identity verification
- Consistency -- All challenges follow the same creation and review workflow regardless of who made them
- Business alignment -- Provider registration is a conversion funnel for the platform
Why Only Staff Review Track Records (Not Vendors)
Only DoCurious staff review Track Records, even for vendor-created challenges. Vendors do not review TRs for their own challenges. This decision ensures consistency and trust in the verification process. It may be revisited in the future.
Why Structural Fields Lock After First Start
Once any user has started a challenge, structural fields (milestones, difficulty, materials, verification criteria) are locked. This prevents a scenario where a user is mid-progress and the challenge fundamentally changes under them. Cosmetic edits (description, images, instructions) are still allowed and trigger a notification banner.
Why Multiple Completions Are Allowed
Users can complete the same challenge multiple times, each generating a separate Track Record. This supports real skill progression (e.g., baking bread multiple times and improving), seasonal challenges (same hike in different seasons), and group repetition (doing it solo, then with family).
Why Video and Audio Are Links-Only
Track Records accept video and audio only as external links (YouTube, Vimeo, SoundCloud, Spotify), not direct uploads. This avoids the significant infrastructure cost of video/audio hosting, transcoding, and storage while still allowing rich multimedia documentation.
XP Calculation
STATUS: BUILT
The XP calculation formula is fully implemented in the frontend with all multiplier factors (difficulty, duration, venue/travel, cost, fudge factor). The complete formula is applied to all challenge completions with historical accuracy.
The spec defines a detailed points formula:
Points per challenge = ((Base Value + Difficulty Factor) + Duration in Hours
+ Venue/Travel Factor + Cost Factor) x Fudge Factor| Variable | Value |
|---|---|
| Base Value | 22 |
| Difficulty Factor: Beginner | 1.00 |
| Difficulty Factor: Intermediate | 2.00 |
| Difficulty Factor: Advanced | 4.00 |
| Difficulty Factor: Expert | 5.50 |
| Duration in Hours | Actual duration in hours |
| Venue/Travel Factor | 4.00 if hosted or requires travel; 0 otherwise |
| Cost Factor | Log10(1 + Cost in dollars) x 5 |
| Fudge Factor | Default 1.00; adjustable per challenge by admins |
Important rules:
- Once points are awarded for a completed challenge, they do not change even if the formula or factors change later
- Multiple completions of the same challenge award 50% of the base XP (diminishing returns)
- Dealer's Choice completions receive a multiplier (1.5x--2x based on category novelty)
- Dealer's Choice abandonment carries a symmetric negative XP penalty
- A Points Administration Control Panel is planned to allow staff to adjust all variables
Technical Implementation
Key Files
| Layer | File | Size | Purpose |
|---|---|---|---|
| Types | src/types/challenge.types.ts | 24.4KB | All challenge, user-challenge, track record, milestone, discussion, and filter types |
| Store | src/store/useChallengeStore.ts | 11.7KB | Zustand store with browse, filter, my-challenges, vendor, and CRUD actions |
| Mock API | src/api/challenge.api.ts | 16.5KB | localStorage-backed mock service with full CRUD, filtering, pagination |
| Real API | src/api/challenge.real.api.ts | 4.1KB | Backend HTTP client (partially stubbed -- stats and status map endpoints not yet available) |
| Detail Page | src/pages/challenges/ChallengeDetail.tsx | 56.5KB | Full tabbed detail view with contextual actions |
| My Challenges | src/pages/challenges/MyChallenges.tsx | -- | Tabbed user-challenge dashboard |
| Submit | src/pages/challenges/SubmitChallenge.tsx | -- | Challenge submission form |
| Group | src/pages/challenges/GroupChallenge.tsx | -- | Group challenge coordination |
| Gift Redemption | src/pages/challenges/GiftRedemption.tsx | -- | Gift acceptance flow |
| Track Record | src/pages/challenges/TrackRecord.tsx | -- | Track Record editor/viewer |
| Card | src/components/challenge/ChallengeCard.tsx | -- | Reusable challenge card for grids and lists |
| Grid | src/components/challenge/ChallengeGrid.tsx | -- | Filterable challenge grid layout |
| Discussion | src/components/challenge/ChallengeDiscussion.tsx | -- | Threaded discussion component |
| Create Modal | src/components/challenge/CreateChallengeModal.tsx | -- | Vendor challenge creation form |
| User Card | src/components/challenge/UserChallengeCard.tsx | -- | My Challenges tab card with progress |
| Version History | src/components/challenge/ChallengeVersionHistory.tsx | -- | Edit history display (placeholder data) |
| Welcome Modal | src/components/challenge/ChallengeWelcomeModal.tsx | -- | First-time challenge onboarding |
Store Actions
The useChallengeStore exposes these actions:
| Action | Description |
|---|---|
fetchChallenges(page?) | Load browsable challenges with current filters and sort |
fetchCategories() | Load all active categories for filter UIs |
fetchFeaturedChallenges() | Load editorially featured challenges |
fetchChallengeById(id) | Load a single challenge for the detail page |
fetchMyChallenges(tab?) | Load user's challenges filtered by the active tab |
fetchMyChallengeStats() | Load counts per tab for badge display |
fetchMyChallengeStatusMap() | Load a map of challengeId to user's status (for card state) |
setFilters(filters) | Update filter criteria and re-fetch |
setSortBy(sortBy) | Update sort order and re-fetch |
setCurrentTab(tab) | Switch My Challenges tab and re-fetch |
startChallenge(challengeId) | Begin a challenge (creates UserChallenge in "in_progress") |
acceptInvitation(id) | Accept a gifted/assigned challenge |
declineInvitation(id) | Decline a gifted/assigned challenge |
abandonChallenge(id) | Abandon an in-progress challenge |
createChallenge(data) | Create a new challenge (vendor flow) |
submitForReview(id) | Submit a draft challenge for staff review |
Known Implementation Gaps
These items are specified in the spec but not yet built or partially built:
- Challenge creation form fields -- Missing fulfillment type, cost, location, solo/group, cover image upload, verification requirements, teacher tips, and resource links in the UI
- Milestone minimum -- Current UI enforces a minimum of 2 milestones; spec allows 0+
- Full XP calculation formula -- Spec defines 6 multiplier factors; codebase uses simplified base values
- Track Record Gallery integration -- Component exists but is not wired into ChallengeDetail as a tab
- Challenge Discussion integration -- Component exists but is not wired into ChallengeDetail as a tab
- Interesting List / Bucket List separation -- Currently merged into a single "Saved List"
- Category management admin UI -- Categories require code changes to modify
- User-to-provider registration flow -- Not yet implemented
- Locked field enforcement -- No check preventing structural edits on challenges with active users
- Challenge difficulty label mismatch -- SubmitChallenge.tsx uses "Easy/Medium/Hard/Expert" instead of spec's "Beginner/Intermediate/Advanced/Expert"
- Admin category management UI -- Categories are hardcoded; planned admin interface for staff to add/rename/reorder categories has not been built
Related Features
- Track Records -- The documentation artifact created when completing a challenge
- Gifting -- How paid challenges are gifted between users (Doc 3)
- Explore -- How challenges are discovered, filtered, and recommended (Doc 4)
- Communities -- Challenge discussions within community contexts (Doc 5)
- School Administration -- How schools assign challenges to classes and students (Doc 6)
- Gamification -- XP, badges, levels, and Journey Map (Doc 8)
- Vendor Portal -- Vendor onboarding and dashboard (Doc 20)