Handoff — feature-workspace restructure + group/onboarding/feed fixes
Product / feature change (one line)
The artefact was restructured into per-feature workspaces (screens now live under challenges/, components stay in one shared pool) and repo bindings were re-pointed at the app's new src/features/* layout; on top of that, three new UI states shipped — Feed just-joined (mid-week joiner catch-up), Leaderboard early ("Yet to play"), and a redesigned GroupSummary state flag — plus an onboarding group-confirm cover hero and icon wiring on the streak/workout cards.
Component changes
- Feed (
components/Feed/Feed.{html,js,css}) — NEW statejust-joined: the view a member sees when they join a group mid-week. Shows only the join story — pre-join history collapsed behind an expand-history disclosure, a catch-up digest pinned atop the stream, and a MemberJoined crew-intro card under Today; "I'm caught up" dismisses the digest and reveals full history. New model additions to bind:MemberJoined { name, reactions[] }(data-field="memberJoined.name") andCatchUpDigest extends FeedItem { points, target, medalCount, gameCount, leader }(digest.medalCount/digest.gameCount/digest.leader.*, reusinggroup.points/group.target). Render rule (server-side):just-joinedrenders whenmember.joinedAt > week.startedAt && !member.welcomed. ACTIONS:expand-history→ unfolds pre-join items dimmed in place ("Show previous group activity");dismiss-digest→markMemberWelcomed()mutation (proposed) fired by "I'm caught up". data-repo: existing Feed/Chat panel → becomes<Feed state={…}/>. (commit 569e578) - Leaderboard (
components/Leaderboard/Leaderboard.{html,js}) — NEW stateearly: the crew right after a challenge kicks off — a member or two have scored, everyone else renders "Yet to play" (dim dot for rank, no medals/points) instead of dead "—" rows. Model semantics: a pending member ispoints == null(andrank == null). Full crew stays listed, no "+N more" collapse; display-only. data-repo re-pointed:src/components/family-challenge/family-challenge-component.tsx→src/features/family-challenge/components/family-challenge-component.tsx. Becomes<MemberLeaderboard state={…}/>. (early state: 16b8602) - GroupSummary (
components/GroupSummary/GroupSummary.{html,js,css}) — the state flag (goal-reached / last-day / week-reset) was redesigned from a plain emoji-prefixed text line into a tint + hairline pill with a leading mask icon set perdata-statein CSS (check · flag · flame). Emoji removed from all state copy; the label is state-derived presentation copy (nodata-field) written into.group-summary__flag-textso the icon slot survives. Also: the unread-updates noun is now singular/plural-formatted in the component (update/updates). No new bound fields. data-repo:new→<GroupSummary state={…}/>. (flag: 16b8602 · noun: 569e578) - OnboardingFlow (
components/OnboardingFlow/OnboardingFlow.{html,js,css}) — thegroup-confirmstep gained a cover hero (name + tagline + cover art + circular profile — the "on-cover overlaid" hero fromexplorations/group-confirm-cover-hero.html). New model field to bind:Group.profileUrl(data-field="group.profileUrl", circular avatar), joininggroup.tagline/group.coverUrlwhich now also flow into the confirm hero. Picked-group carry-over now threadsdata-group-profilethrough the pick→confirm handoff. Metadata source:common/group-themes.json. (commit 569e578) - TrainingHistory (
components/TrainingHistory/TrainingHistory.{html,js}) — wired the calendar glyphs: streak cells now render/assets/icons/flame.svg+ connecting streak-lines, today's cell adds/assets/icons/arrow-up.svg, and the header gained a leadingtraining-history.svgicon + trailingchevron-right.svg. No model change (stillStreakCalendar). data-repo re-pointed:src/components/streaks/training-history-card.tsx→src/features/streaks/components/training-history-card.tsx. (16b8602) - WorkoutCard (
components/WorkoutCard/WorkoutCard.{html,css}) — wired ring + pill glyphs: centre mode icon (mode-classic.svg,data-field="workout.mode"→ repoWorkoutModeIcon[mode]), per-pill game icons (data-field="slot.gameSlug") and check-mark played badges. No model change. (16b8602) - MemberProfileCard — path canonicalization only (asset/template URLs → root-absolute); no behavior or model change.
Page changes
- Feature-workspace restructure (
00996b4) — all four Challenges screens + the v1 reference moved from repo root intochallenges/(challenges/{home,challenges,awards,game-result}.{html,js,css},challenges-v1.html); components stay in the single sharedcomponents/pool. The old rootgallery.{html,js,css}split intocore/gallery.js(generic renderer) +challenges/gallery.{html,js,css}(the feature CATALOG). Newroot.htmlhub links the feature(s). These land in the app's Challenges routes unchanged — the shell is still reference-only. - Root-absolute path canonicalization (
09c9b58) — everytemplateUrl/cssUrl/assetsrc/url()across components and screens converted from relative (./components/…,assets/…) to root-absolute (/components/…,/assets/…) so pages resolve from any depth. Mechanical; no integration impact beyond confirming absolute asset paths.
Registration
challenges/gallery.jsCATALOG catalogues the pool for the challenges feature (incl. the new Feedjust-joinedand Leaderboardearlystates);core/gallery.jsis the shared renderer (bootGallery(CATALOG)). Old rootgallery.jsdeleted.
Motion
- Feed "I'm caught up" curtain reveal (
components/Feed/Feed.jsrunCurtain(),common/motion.js) — dismissing the catch-up digest plays a two-beat choreography: digest + history-toggle fade/shrink out, then a Silk-style veil wipe with a "Catching you up… n / N" progress pill rides down the now-position:relativepre-join block, ending on "Caught up to today" as full history dissolves in. Self-cancelling (guards onel.dataset.state === 'just-joined'every await). Fail-safe: the class swap alone is the final state, so it degrades to the revealed history when motion can't load;common/motion.jsloadMotion()resolves null underprefers-reduced-motion/ CDN failure → jump to final state. FM equivalent:<AnimatePresence>exit on digest + toggle, then amotion.divveil with variants (see README porting table). (569e578)
Integration notes / open questions for the dev
- New repo bindings to confirm: Leaderboard →
src/features/family-challenge/components/family-challenge-component.tsx; TrainingHistory →src/features/streaks/components/training-history-card.tsx. These assume the app has moved to thesrc/features/*feature-folder layout — verify those paths exist before wiring; if the app is still onsrc/components/*, use the old paths. - Backend still proposed, not built:
markMemberWelcomed()(dismiss-digest),groupWeekSummary → CatchUpDigest, and themember.welcomed/member.joinedAtserver flags for the Feedjust-joinedgate are all proposed contracts — seechallenges/spec.json. Group.profileUrlis a new field on the group metadata model (onboarding confirm hero) — bind alongsidecoverUrl/tagline.