JOYOS LAB v1.2

Mockup Review

All phases ready for review - 2026-06-21

Phases 23 - 35 (Phase 25 skipped) 13 product surfaces Cream + obsidian + gold + teal theme
Learning Lab Surfaces 6 surfaces

Phase 24 · Complete  🔒 Locked — Current Lead

Front-Door Fork Route

Diagonal duotone split screen at /start. Teal Learning Lab wedge vs. gold Creator Studio wedge with animated seam and J-monogram seal.

Entry concept locked 2026-06-21 — Fork Door — Diagonal Duotone is the chosen entry concept. It is the Current Lead in the entry-concepts gallery (joyos-lab-revamp.pages.dev). Open questions below remain for implementation detail; the visual direction is decided.

Spec highlights

  • Route /start renders Fork A; no sidebar, no shell chrome
  • Teal panel navigates to /learn; gold panel to /studio
  • Seam hairline and seal position are JS-driven per frame
  • prefers-reduced-motion disables all ambient animation
  • Mobile: steeper seam for portrait; tap to expand then navigate

Open questions

  • What happens when a signed-in user hits /start? Redirect to /app or show the fork anyway?
  • Does the fork chooser replace the current landing page, or only appear at /start?
  • Should returning members see their last-chosen side animate first?

Phase 31 (browse) · New

Learning Lab Browse + Filter + Search

Full-width image-heavy catalog view with type filter chips, category pills, keyword search, and results grid. No sidebar.

Spec highlights

  • No sidebar on any Learning Lab route (full-width, image-heavy)
  • Filter chips are multi-select; active filters show a count badge
  • Search filters STDB offers table on title and description client-side
  • Empty state: "No results for [query]" with clear-filter CTA
  • Anonymous users can browse without signing in

Open questions

  • Should search results be ranked by recency, rating, or purchase count, or alphabetical by default?
  • Is there a "Featured" or "New" badge on offer cards?
  • Should the offer detail page show related offers below the reviews section?

Phase 31 (detail) · New

Offer Detail Page

Full route at /learn/offers/slug with cover image, creator info, type-specific content preview, Buy Now CTA, and reviews below the fold.

Spec highlights

  • Offer detail is a full route /learn/offers/slug, not a modal
  • Buy Now CTA checks entitlement first; shows "Access in My Library" if owned
  • Type-specific preview: video teaser, file name, calendar embed, week overview
  • Signed-out users see a sign-in prompt on clicking Buy Now
  • Aggregate star rating bar and review cards displayed below the fold

Open questions

  • Should a free-tier user see the offer detail and price, or is pricing gated?
  • Is there a preview/teaser that anonymous users can access before purchasing?
  • Should the offer detail page show creator archetype alignment as a trust signal?

Phase 30 (library) · New

My Library

Image-heavy grid of owned offers with per-type access buttons. Includes the post-checkout "Finalizing..." polling state and empty library state.

Spec highlights

  • Library reads from STDB entitlements table filtered by user_identity
  • "Finalizing..." card subscribes to entitlements table, auto-dismisses when row appears
  • Empty state: "You have not purchased anything yet" with browse CTA
  • Returning buyer sees same fulfillment screen without re-purchasing
  • Refunded offers: decision needed (badge or hide entirely)

Open questions

  • Should the Library show refunded offers with a badge or hide them entirely?
  • Is there a download count limit for digital products?
  • Should experiment kit enrollment happen automatically on purchase or require a click?

Phase 30 (fulfillment) · New

Per-Type Fulfillment Screens

Four distinct fulfillment views behind the entitlement gate: video player, download button, Cal.com booking embed, and experiment kit enrollment.

Spec highlights

  • Each offer type renders a different fulfillment component determined by offer.type
  • Download links minted by /api/get-download-link (short TTL, signed, single-use)
  • Experiment kit link passes program_id as query param to pre-select the experiment
  • Masterclass: signed Cloudflare Stream video player, full-screen on mobile
  • Coaching: Cal.com booking embed plus upcoming appointments list

Open questions

  • Should video fulfillment support progress tracking (resume playback position)?
  • Can buyers share access to a coaching session with a partner or colleague?
  • What happens to coaching session fulfillment if the creator cancels their Connect account?

Phase 34 · New

Ratings and Reviews

Buyers rate and review purchases; aggregate star bar and review cards appear on the offer detail page. Write form visible only to entitlement holders.

Spec highlights

  • Review write form appears inline on the offer detail page, not in a modal
  • Entitlement check is performed server-side by the submit_review reducer
  • Each buyer can submit one review per offer; re-submit replaces the first
  • Reviews stored in STDB reviews table: slug, identity, rating, body, created_at
  • Aggregate rating computed client-side from all reviews rows matching the slug subscription

Open questions

  • Should reviews be moderated (admin approval) or instant publish?
  • Can creators respond to reviews with a public reply below the review card?
  • Should a "Leave a review" prompt appear in My Library right after purchase?
Creator Studio Surfaces 5 surfaces

Phase 26 · Complete

Stripe Connect Onboarding

Creator completes Connect Express before selling. Shows not-started, 3-step progress, pending, and enabled states inside Creator Studio sidebar.

Spec highlights

  • Server mints Stripe Connect account link (/api/connect-onboard) and redirects to Stripe Express
  • On return, CF Function reads charges_enabled and writes to STDB
  • Publish button is disabled (not hidden) when charges_enabled is false
  • Re-entry into pending state re-fetches account status; no client polling
  • Mobile: stepper becomes stacked vertical flow with step counter

Open questions

  • Can creators draft offers while Connect is pending, or is the whole composer locked?
  • Does the creator get an email from JoyOS or directly from Stripe when their account is enabled?
  • What does the Studio surface show if a Connect account is later restricted or deactivated?

Phase 29 · Extended

Offer Composer - All Four Types

Per-type composer variants (masterclass, digital product, coaching, experiment kit) plus draft and published state transitions and the Connect-gate interstitial.

Spec highlights

  • Offer type selected at start of composition flow; cannot be changed after saving
  • Publish button checks charges_enabled on client; if false, opens Connect gate modal
  • Draft offers stored in STDB offers table with status: 'draft'
  • File uploads go to R2 (or MinIO fallback) via /api/upload-offer-asset presigned URL
  • Conversational AI flow generates the draft; creator refines in structured form

Open questions

  • Can a creator have multiple offers of the same type, or one per type?
  • Should the AI-guided flow be skippable so creators can go straight to the structured form?
  • How does the creator set price: fixed input or Stripe Products price selector?

Phase 33 · Extended

Creator Studio Dashboard

Established creator sees earnings summary and offer performance. Free user hits a welcome screen with "Start Selling" CTA leading to Connect onboarding.

Spec highlights

  • Router guard checks user.connectStatus and renders welcome or dashboard accordingly
  • Sidebar is the 240px nav rail from studio-b.html locked direction
  • Earnings summary cached in KV per creator for 5 minutes (Stripe Connect balance + transfers)
  • Offer performance table reads from STDB offer_stats table
  • Mobile: sidebar collapses to bottom tab bar; cards become horizontal scroll row

Open questions

  • Can a creator use Studio features (like scheduling) before Connect is enabled?
  • How granular is the earnings breakdown: total only, or per-offer and per-month with a chart?
  • Can a creator deactivate their seller account and return to a pure learner experience?

Phase 28 · New

Refunds and Payouts

Buyer initiates a refund which revokes entitlement. Creator reaches payout dashboard via a server-minted Stripe Express deep link.

Spec highlights

  • Refund initiated via /api/request-refund which calls Stripe Refunds API and reverses destination charge
  • On successful Stripe refund, CF Function calls revoke_entitlement reducer
  • Creator payout summary data comes from Stripe Connect balance endpoint, cached in KV 5 min
  • Admin order management panel at /app/admin/orders behind isAdmin gate
  • Refunds only allowed within the configured window (default 30 days)

Open questions

  • Should partial refunds be supported, or is it always a full refund?
  • Does the creator receive a notification when a buyer requests a refund?
  • Is there a dispute or appeal flow for creators who disagree with a refund request?

Phase 35 · New

Physical Products

Creator composes a physical offer. Buyer checks out with a shipping address step. Creator marks shipped with a tracking number. Buyer tracks order status in My Library.

Spec highlights

  • Physical offer type adds requires_shipping: true flag in STDB offers table
  • Checkout detects requires_shipping and inserts the address step before Stripe Payment Element
  • Shipping address stored in STDB orders table alongside Stripe Checkout session ID
  • Creator order management at /studio/orders; visible only to creators with active offers
  • Tracking number update triggers a notifications row for the buyer

Open questions

  • Should JoyOS integrate with a shipping label service (EasyPost, Shippo) or leave it to creators?
  • Is there a maximum quantity per order, or can buyers purchase multiple units?
  • How does inventory management work: auto-unavailable at zero, or manual creator control?
Shared and Admin Surfaces 4 surfaces

Phase 23 · Complete

Free-Tier + Access Boundary

Public free signup without leaking paid /app/* content. Gate modal shows which tier unlocks content and links to /app/settings for upgrade.

Spec highlights

  • Free accounts created at Joy Seeker tier; no credit card required
  • Gate modal must show WHICH tier unlocks the content, not just "upgrade"
  • TierGate component wraps every paid-only route
  • Stripe checkout NOT triggered by free signup; only by explicit Upgrade action
  • Gate state persists via STDB users.tier row, not localStorage

Open questions

  • Should a free Joy Seeker see a blurred preview of paid content or a hard gate?
  • Does free signup require email verification before the account is active?
  • Should the gate modal appear as an overlay or navigate to a full upgrade page?

Phase 27 · Complete

Checkout + Entitlements

Buyer purchases an offer through a 3-step flow ending at Stripe-hosted checkout. Post-purchase polling grants entitlement and unlocks the content in My Library.

Spec highlights

  • Checkout session created server-side with destination_charge and application_fee_amount
  • Success redirect URL is /app/library?new=offer_id to highlight the new purchase
  • Entitlement polling checks STDB entitlements table via WebSocket subscription
  • Polling times out at 30 seconds with a "refresh" fallback
  • Stripe Checkout opens in the same tab so the success redirect lands correctly

Open questions

  • How long should the "Finalizing..." polling state wait before showing the timeout fallback?
  • Should buyers receive a JoyOS receipt email in addition to Stripe's built-in receipt?
  • When a buyer already owns an offer, should "Buy Now" change to "Access" or be hidden?

Phase 32 · New

Featured Shelves and Recommendations

Admin curates horizontal offer shelves with drag-to-reorder. Members see archetype-personalized recommendation rows on the Learning Lab home.

Spec highlights

  • Shelves stored in STDB shelves table with sort_order; drag-reorder writes new order
  • Platform fee stored in KV as config:platform_fee_pct (encrypted); default 15%
  • Recommendation logic reads joy_assessments.conversation for archetypeScores
  • Admin shelf manager at /app/admin/shelves behind isAdmin gate
  • Horizontal scroll rows use scroll-snap-type: x mandatory for mobile swipe

Open questions

  • How many shelves can the admin create? Is there a maximum?
  • Should archetype recs pull from any shelf or only from a designated "Recs" shelf?
  • Can creators submit their offer to be featured, or is curation purely admin-driven?

Note · Phase 25 Skipped

Marketplace Schema Migration

Pure backend. Publishes all new marketplace tables atomically via CI. No user-facing surface. No mockup needed or appropriate.