V1 Web PWA · Surface walkthrough

Achievements · Arete · OSHUN

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections3 minread

On this page

Context. surface customer · domain arete · route /domains/arete/gamification · auth signed-in · source apps/oshun/web/src/app/domains/arete/gamification/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md

Purpose#

Internal /domains/arete/* alternate surface for gamification: XP & level / badges / quests / challenges / leaderboard / levels. This is a Duolingo- style achievement layer. Notably, V1/features.md positions Arete as humane (rest days, no streak punishment) — verify whether this surface contradicts that ethos. Backed by fixture constants (XP_SYSTEM, LEVELS, badges, quests, etc.).

Entry points#

  • Direct URL / bookmark — yes (signed-in)
  • No link from /arete polished surface — verify; the polished Arete hub is intentionally not gamified

Layout regions#

page.tsx is a 'use client' page: SR-only "Achievements · Arete · OSHUN" heading + <AreteGamification />. Component at apps/oshun/web/src/components/domains/arete/AreteGamification.tsx.

  • Container: max-width: 900px; padding: 24px
  • Header: (Trophy and related icons imported; verify which renders at the top)
  • Tab bar (6 tabs):
    • xp — XP & Level (Zap icon)
    • badges — Badges (Medal icon)
    • quests — Quests (Swords icon)
    • challenges — Challenges (Target icon)
    • leaderboard — Leaderboard (Trophy icon)
    • levels — Levels (Crown icon)
  • Content area (per active tab):
    • xp<XPView /> — current level, XP progress within level (xpInLevel / (xpInLevel + xpNeeded)) with LEVELS.find(...)
    • badges<BadgesView /> — badges by tier (TIER_COLORS: bronze #CD7F32 / silver #C0C0C0 / gold #FFD700 / platinum #E5E4E2) and category (CATEGORY_LABELS: habits, goals, journal, wellness, social, milestones, seasonal)
    • quests<QuestsView />
    • challenges<ChallengesView />
    • leaderboard<LeaderboardView />
    • levels<LevelsView />

States#

  • Loading — N/A: client component with sync fixture
  • XP level rendered — current xp.currentLevel looked up against LEVELS; progress bar computed from xpInLevel / (xpInLevel + xpNeeded)
  • Level cap (no xpNeeded)progressPercent === 100 when xpNeeded <= 0
  • Badge unlocked vs. lockedgm-badge-unlock keyframe defined; verify which view triggers it
  • Tab switching — instant
  • Error (recoverable) — relies on app-level error boundary
  • Offline — purely client; identical offline
  • Gated — N/A
  • Standalone PWA — no shell chrome around the page

Interactions#

Tab bar (6 tabs)#

  • XP & Level / Badges / Quests / Challenges / Leaderboard / Levels (buttons)
    • Function: setActiveTab(tab.id)
    • Telemetry: none
  • Header CTA — component is exported as AreteGamification({ onClose: _onClose }); the _onClose is underscore-prefixed (intentionally unused). Verify whether a parent passes this prop in any other context (likely a modal use)

Per-tab interactions (XP / Badges / Quests / Challenges /#

Leaderboard / Levels)

  • Deep interactions exist within each tab view but require a deeper read than the per-page walkthrough budget allows. Itemize when individually walking those views.

Data & contracts#

  • Reads: import-time XP_SYSTEM, LEVELS, and other fixture symbols from @/lib/arete/arete-extended-simulation. No BFF.
  • Writes: none — local state only
  • Realtime: none
  • Caching: client bundle only
  • Auth/role check: app-level middleware

Cross-references#

  • Domain hub: arete.md
  • Component source: apps/oshun/web/src/components/domains/arete/AreteGamification.tsx
  • Simulation data: apps/oshun/web/src/lib/arete/arete-extended-simulation.ts
  • Types: apps/oshun/web/src/lib/arete/arete-extended-types.ts (BadgeTier, BadgeCategory, etc.)
  • Tension to flag with V1/features.md: the polished Arete surfaces lean hard on humane / non-punishing (see arete-streak.md, arete-recovery.md). This achievements layer imports Crown / Trophy / Swords iconography and "Leaderboard" tab — document whether the tones reconcile.

Open questions / known gaps#

  • Conflict-with-features question: the gamification surface exists, but V1/features.md positions Arete coaching as humane — clarify whether /domains/arete/gamification ships in V1 or is internal-only
  • No shared chrome with /arete polished surface
  • No persistence of XP / badges (client-only state)
  • onClose prop is accepted but unused (underscore-prefixed) — verify whether a parent context expects to close this view as a modal
  • Per-tab interactions (badge claim, quest accept, leaderboard scroll, etc.) need a deeper walk to enumerate