Overview

Member app documentation

NAOS Fitness turns coach-measured benchmark assessments into a ranked season game. This is the engineering reference for the member app: the model it follows, every screen in it, the events it emits, and the decisions NAOS still owes us.

Source of truth

The clickable prototype. Layout, copy and states in these pages describe what it does; fixture values are illustrative.

Scope

Member app, V1. The coach and admin portal appears only where the app depends on it.

Open items

Every pending NAOS decision carries our recommendation, marked Our call. Build against it and keep the seam visible.

Problem

Today assessment results live in a coach's spreadsheet: a member is told a number, forgets it, and has no reason to come back for the next assessment. The gym has a competitive esports brand and no competitive product.

Goals

  • Make the assessment worth returning for. Rank only moves on re-assessment, so the assessment is the app's core event and the only thing that changes the hero number.
  • Give the between-assessment weeks something live. Gym visits are the only moving part between assessments; each approved tap-in pays XP and counts toward badges, never rank.
  • Make standing legible at a glance. Tier, placement total, distance to next tier, season position — in that order, on Home.
  • Make a member want to post it. The achievement card is a deliberate share artifact.

Non-goals for V1

In-app payment or plan purchase (membership is bought and linked at the front desk), booking and scheduling, wearables and auto-tracking, team boards, weight-class segmentation, divisions I–IV, and the coach/admin portal itself.

Success signals

Re-assessment rate per season, average approved visits per member per week, and leaderboard opens per member per week. These need instrumenting but no analytics spec is in scope for V1.

Overview

Product model

Three progression tracks. They never merge, and every other rule follows from that.

TrackAnswersSourceMovesResets
Fitness RankHow good are youPlacement total from a coach assessmentOnly on official assessment; can go downPer season
Account LevelHow long have you been hereXP from participationAny time XP is awardedNever
AchievementsWhat have you doneBadges from visits, streaks, tiers and seasonsOn unlockNever

Rules that keep them separate

  • XP never scales with score or position. The moment it does, Level becomes a second skill signal and the model collapses.
  • Level never shares a container with Fitness Rank. Rank owns the Home hero card; Level lives as a ring around the avatar.
  • One full-screen celebration, and it belongs to rank-up. Ordinary level-ups get a toast; milestone levels (10, 20, 30) get their own moment.
  • Nothing else attaches to XP. No unlocks, no gating, no rewards.

The engagement gap, stated plainly

Rank, personal bests and the radar are all static between assessments, because they come from coach measurement. Tap-ins are the only live thing in those weeks, and they carry the whole loop alone. Do not hide this — it is the product's real shape.

Overview

Personas

PersonaContextNeeds from V1
Rhea · ranked memberAssessed, mid-season, trains three times a week. Competitive, reads numbers fast, screenshots her rank.A Home hero that answers "where am I", a season board, a quick tap-in at the door, a share card.
New sign-upDownloaded the app and created an account; may not be a gym member yet. No scores.Sign up → gamertag → welcome with no friction, a clear "link your membership" next step, then an honest empty state with the appointment as hero once linked.
Coach MikaPortal user, never opens the app.Nothing in-app — but every rank change originates with her.
Gym adminLinks app accounts to memberships, approves tap-ins, books slots, closes seasons, resets gamertags.Same: the app is downstream of admin actions.
Overview

Flows

First run — self-service sign-up

Splash → Get started → Create account → Set password → Choose gamertag → Welcome → Home (not yet a member)

Anyone can create an account with full name, email, date of birth and sex. Gamertag is required and gets a full screen — it is the member's first act of ownership. The account can browse but cannot be ranked until the gym links it to a membership.

Joining the gym

Home "Link your membership" → front desk links by email (portal) → Push "Membership linked" → admin books slot → Push "Assessment scheduled" → Home (unassessed)

The front desk finds the account by email, checks the date of birth and sex the member entered (both drive scoring bands), and attaches the membership. Both lock in the app from that moment. Tap-ins and leaderboard entry unlock at the same time.

First assessment — peak 1

Push "Placement results posted" → Placement results → Rank reveal → Home (assessed)

The notification is the entry point, not something to find in the app. Results count up the five scores, draw the radar, land the total, overlay the coach's season target, and add the flat 500 XP.

Between assessments — the attendance loop

Arrive at the gym → Game on tab "Tap in" (or Home card) → pending → front desk approves in the portal → Push "Visit logged" → +100 XP → level-up toast when a threshold is crossed

One approved visit per day. A declined request shows the reason; the front desk can add a missed visit in the portal. There is no member-side dispute flow.

Reassessment — moving placement mid-season

Game on "Request reassessment" (or Placement results "Reassess") → pick stats → Pending → admin books the slot in the portal → Push "Reassessment booked" → Booked → coach runs it → Push "Placement results posted" → Placement results

Open only while a season is running and only after the member's first placement. One request at a time, at least 4 days after the last assessment, and requests close 3 days before the season ends. The member picks one to five stats; new scores replace the old even if lower, the total, tier and season position recompute, and it pays the flat 500 XP. A pending request can be cancelled in the app; a booked slot cannot ("Can't make it? Tell the front desk"). A missed slot stays on the card as Missed until the front desk or coach cancels it in the portal — only then can the member request again.

Compare and share — peak 2

Leaderboard → Competitor profile → Comparison → Achievement card → native share sheet

Season close

Push "Season ending" → Season → (close) → Push "Final standings" → Season (closed) → Season history

Reference

Screen specs

Thirty screens, grouped by tab. The tab bar (Home · Game on · Board · Me) shows on signed-in screens only. Device frame is 402 × 874.

First run — no tab bar

Splash

Splash

Purpose. App-launch screen. NF mark, wordmark, loading sliver.

Behaviour. Animates in over ~1.8s, then auto-advances to Get started (signed out) or Home (session restored). No controls, no back.

Edge. If a session restore fails, fall through to Get started rather than holding the splash.

Get started

Get started

Purpose. Entry fork. Tagline, primary "Create account", secondary "Log in".

Behaviour. Footnote sets the expectation up front: anyone can sign up; ranking starts once the front desk links the membership.

Create account

Create account

Purpose. Full name, email, date of birth and sex. This is the identity the front desk checks when linking a membership.

Behaviour. Continue enables once the name has two or more characters, the email is valid, the member is 13 or older, and a sex is picked. Sex offers Female and Male only, matching the scoring bands.

Edge. Under the minimum age: inline "You need to be 13 or older to sign up." and Continue stays disabled. Minimum age is 13.

Edge. Email already registered: "An account already uses that email. Log in or reset your password." One account per email.

Set password

Set password

Purpose. Password and confirm with a strength meter.

Behaviour. Continue stays disabled until both match and the minimum strength is met; the rule is stated up front, never only on failure.

Choose gamertag

Choose gamertag

Purpose. Required. The name that appears on every board.

Rules. 3–16 characters, letters, numbers and underscore; unique database-wide (not per gym); live availability check as the member types, never submit-then-fail; re-checked on save.

Edge. Taken tag shows a taken state inline and blocks Continue. Admins can reset a gamertag from the portal.

Welcome

Welcome

Purpose. Confirms the account is live and sets the next step: link the membership at the front desk with the account email; the gym then books the first assessment.

Behaviour. Single CTA into Home. The Iron badge is shown as unranked, not as a score.

Log in

Log in

Purpose. Email and password, link to reset.

Edge. Wrong credentials return one combined message; never disclose whether an email exists.

Reset password

Reset password

Purpose. Email entry → send link → success confirmation → back to Log in.

Edge. Success copy is identical whether or not the email is known.

Membership lapsed

Membership lapsed

Purpose. Full block when membership ends. Rank badge and gamertag dimmed so it reads as paused, not deleted.

Behaviour. No tab bar, no back out, no payment path — renewal happens at the gym. Log out is the only action. Reachable from any screen when the membership flag flips.

Home and season

Home

Home

Purpose. The standing, answered in one screen.

Elements. Greeting row with avatar level ring; Fitness Rank card (badge, tier, placement total, distance to next tier, season position); season row with week and days left; attribute strip of five axis scores; today's tap-in card with an inline "Tap in"; activity feed.

Behaviour. Rank card opens the Rank ladder; season row opens Season; any axis opens Attribute detail; the level ring opens Level history. Distance-to-next-tier is the progress metric, never a bar out of 45.

Edge. Not yet a member: "Link your membership" card is the hero, showing the account email; no tap-in card. Unassessed member: empty radar outline, Iron badge with no total, appointment card promoted to hero. At NAOS Legends: progress bar drops and the card reads tier · position.

Assessment detail

Assessment detail

Purpose. Read-only appointment set by the admin: coach, date, time, location, what to bring.

Behaviour. Secondary action requests a change, which notifies the coach. No booking, no calendar, no slot picking in V1.

Placement results

Placement results

Purpose. Peak 1. The coach's assessment, revealed.

Elements. Five attribute scores, radar animating in, placement total, resulting tier, the coach's season target as a dashed overlay with a one-line caption, and the +500 XP counting up.

Behaviour. Entered from the push notification; hands off to the rank reveal when the tier changes. Re-placements show movement against the previous assessment, including downward. While a season is running and no request is open, an "Improved since? · Reassess" row sits below the CTA and opens the reassessment picker.

Request reassessment

Request reassessment

Purpose. Pick which stats to re-run. Member ticks one to five attributes; current scores shown beside each. Opened from Game on or Placement results; it sits under the Game on tab.

Rules. Live season only, after the first placement, one request at a time, 4-day cooldown from the last assessment, closed in the last 3 days of the season. New scores replace the old, even if lower; total, tier and position recompute; +500 XP. Rank reveal fires only if the tier changes.

Behaviour. CTA reads "Request reassessment · n" (or "Request full reassessment" at five). Sends to the admin request queue and returns to Game on with the card in Pending.

Rank reveal

Rank reveal

Purpose. The one full-screen celebration in the product.

Behaviour. Fires on first placement and on any re-placement that changes tier. Tier name, medal, placement total, single continue CTA. Ordinary level-ups get a toast instead; milestone levels (10/20/30) get their own full-screen moment.

Rank ladder

Rank ladder

Purpose. The whole climb: every tier, its threshold, and a "you are here" marker.

Behaviour. The only place the full 0–45 scale is shown. Above the top threshold the exact total is shown uncapped.

Season

Season

Purpose. The season in one place: theme, dates, progress, the member's movement, and the top of the board.

Elements. Hero card with countdown; state notice (open / ending soon / closed); four stat tiles (rank movement, XP this season, visits this season, your position); top standings with a link to the full board; last season's final top 20 (top 5 shown, plus the member's row if they placed, "Show all 20" expands); Season history of closed seasons.

Behaviour. Season history lives here and only here — Profile links to it rather than repeating it.

Placement history

Placement history

Purpose. Progress over time: every assessment with date, per-attribute scores, total and tier, and the movement between them.

Edge. One assessment only: show it with no movement column rather than a comparison of one.

Attribute detail

Attribute detail

Purpose. What produced the axis score: the underlying exercises, raw results with units, the 1–9 score each produced, personal best and date.

Behaviour. Reached by tapping any radar axis or strip tile. For Strength, all four lifts are listed with the best-scoring one marked as counting.

Game on

Game on

Game on

Purpose. Everything the member asks the gym for: today's tap-in and reassessment requests. Below them: this week (Mon–Sun), total visits, weekly streak, next visit milestone, recent visits.

Tap in. "Tap in" sends a request to the front desk queue: none → pending (cancellable) → approved (+100 XP) or declined (reason shown). One approved visit per day; the button is gone once today is settled.

Reassessment card. Locked before the first placement ("After first placement") and between seasons; locked during the 4-day cooldown ("Available Sun 27 Sep") and in the last 3 days of a season ("Requests closed"). Otherwise "Retest your stats" with "Request reassessment". After sending: Pending with the picked stats and Cancel request. Once the admin books it: Booked with date, time and coach, no cancel — "Can't make it? Tell the front desk." If the slot is missed: Missed, and the member cannot request again until the front desk or coach cancels it.

Counters. Approved visits only. This week fills a box per approved day and reads "n of 3 to keep the streak" until three. Weekly streak counts consecutive Mon–Sun weeks with three or more approved visits; it breaks only when a week closes short. Visits is all time. The milestone bar tracks the next visit badge (10 → 50 → 100) and hides after 100.

Edge. Not yet a member: locked "Members only" state linking to Membership. Missing visits are added by the front desk in the portal; the member has no dispute flow.

Game on, tap-in approved Game on, reassessment pending Game on, reassessment booked Game on, not yet a member

Board

Leaderboard

Leaderboard

Elements. Board selector (dropdown, Overall pinned first, per-exercise boards grouped by attribute), Season and Sex filters, count line, ranked rows: position, name per display setting, avatar with level ring, rank badge, ranking value. The member's row is highlighted and pinned into view.

Rules. Fewer than 2 entries hides the board. Sex defaults to All on Overall (bands are sex-specific); on per-exercise boards All is allowed but labelled as a mixed board.

Edge. Closed seasons show as a record: no movement indicators, no live position. Non-members can browse boards but never appear on them.

Competitor profile

Competitor profile

Purpose. Opened from any leaderboard row: name per their display setting, level ring, rank badge, season position, placement total and radar.

Behaviour. Primary action is "Compare with you". No contact, no follow, no messaging in V1.

Comparison

Comparison

Purpose. Two radars overlaid plus a per-attribute head-to-head delta and the totals.

Achievement card

Achievement card

Purpose. Peak 2, and the product's only outbound artifact: medal, tier headline, name, gamertag, season, placement total, level and radar snapshot with a brand lockup.

Behaviour. CTA opens the native share sheet. Card renders at a fixed aspect so the exported image is predictable.

Me

Profile

Profile

Elements. Avatar with level ring, gamertag, full name, Fitness Rank card, XP bar and level, radar with current and target, badge grid, settings list, log out, app version.

Behaviour. Settings list links to Edit profile, Membership, Season history (on the Season screen), Activity, About and legal, and Delete account.

Edit profile

Edit profile

Purpose. Avatar, gamertag (same live uniqueness component as first run), and the leaderboard name toggle.

Rules. Full name, date of birth and sex are read-only — labelled "Confirmed when you join" before linking, "Held by the gym" after — with a line pointing to the gym — sex is load-bearing for scoring. The name toggle is a display preference, not privacy, and should be described to NAOS as such.

Membership

Membership

Purpose. Plan, price, status, renewal date and the benefit list. No payment method and no billing actions — renewal happens at the gym.

Edge. Not yet a member: status "Not linked" and four "How to link" steps including the account email. This screen is the target of every locked state.

Activity

Activity

Purpose. The full in-app feed: assessments, rank changes, visits, level-ups, season events, each deep-linking to its target.

Edge. Unassessed members see one entry, account created — not an empty screen.

Level history

Level history

Purpose. Every XP award with source, amount and date, plus the current level and distance to the next.

Behaviour. Reached from the avatar ring anywhere it appears. Flat curve: 1,000 XP per level, forever.

About and legal

About and legal

Purpose. About, Contact, FAQ, Privacy Policy, Terms.

Dependency. Privacy Policy and Terms also need hosted public URLs for store submission.

Delete account

Delete account

Purpose. Required by both stores. Explains what deletion means when the gym holds the membership: app access ends, assessment records are retained by the gym.

Behaviour. Explicit confirmation step; the request is queued for the gym rather than executed client-side.

Not built yet

Notification settings — per-category toggles — is a V1 requirement and is not drawn. It belongs in the Me settings list between Membership and Activity. Level-up toast and level milestone exist as fired moments, not standalone screens.

Reference

States

Member states

Six coherent states drive every screen, reachable from the demo panel. This is the QA matrix.

Not yet a memberUnassessedFirst placementAfter visitsAfter re-placementLegends
RankIron, unrankedIron, unrankedSilverSilverGoldNAOS Legends
Total11111741
Attributes3/2/2/2/23/2/2/2/24/3/3/4/39/8/8/8/8
Level · XP1 · 01 · 01 · 5002 · 1,1003 · 2,10012 · 11,400
PositionNot on boardsUnranked#14#14#9 (jump)#3, position mode
Visits · streak2 · 0 wk3 · 1 wk6 · 2 wk14 · 4 wk112 · 13 wk
UnlockedBrowse onlyEverything; appointment is heroEverything
Home, not yet a member Game on locked Membership not linked

Invariants. Attribute scores drive the radar, the total and the tier together. The leaderboard recomputes positions from totals rather than hard-coding them. Personal bests and attribute detail derive from the same results as the radar. A visit never changes rank.

Season states

StateWhat changes
Day oneWeek 1, full countdown, "Season open" notice, standings empty state, season XP and movement at zero. Every member is unranked again: Home shows the unranked card and empty radar, with "Ranks reset every season" copy.
LiveWeek n of m with days left, live standings, movement indicators.
Ending soonWarning-toned notice, countdown at two days. Reassessment requests are closed for the last 3 days.
ClosedProgress complete, standings locked, reassessment requests locked until the next season, final position stated, Ginto-toned notice, board CTA becomes "View final standings", season moves into Season history.
Season live Season closed Home on day one, rank reset

Season copy never states a future date — the app has no source for one.

Other states to build

  • Leaderboard density. Full, sparse (2–4 ranked with an honest count line), hidden (fewer than 2 entries).
  • Tap-in states. Not tapped in, pending, approved, declined — all four reachable from the demo panel.
  • Reassessment states. Locked (no placement, season closed, requests closed), cooldown, available, pending, booked, missed — reachable from the demo panel's Reassessment and Season controls.
  • Rank down. Results show the movement; no celebration fires and the copy stays factual.
  • Membership lapsed. Blocks every screen; log out is the only exit.
  • Offline and stale. Last-known state with a quiet stale marker; never a blocking spinner on Home.
  • Dead deep link. Land on the nearest parent screen with a one-line explanation.
Reference

Scoring and XP

Five attributes — Strength, Power, Endurance, Mobility, Conditioning — each scored 1–9 against sex-specific bands, then summed. Range 5–45. The total sets the tier. Iron is the pre-assessment state, so no assessed member lands in Iron.

TierLabelMinTierLabelMin
IronNewbie0DiamondExceptional25
BronzeNovice5MasterPro-level30
SilverFair10Grand MasterElite35
GoldExperienced15NAOS LegendsLegendary40
PlatinumAdvanced20

Nine tiers, not eight. Nine medals exist, so Grand Master fills the 35 band. If NAOS confirms eight, delete Grand Master and reset the top band to 35.

Display rules. Home shows distance to the next tier plus the raw total with no denominator. The ladder is the only place the full scale appears. At the top tier the app switches to position mode: no progress bar, tier · season position, uncapped total on the ladder.

XP economy

SourceXPRule
Gym visit100Front desk approves the member's tap-in. Max one per day.
Assessment completed500Flat, whether the member went up a tier or down one. Includes member-requested reassessments, partial or full.
Season completed1,000Flat, for any member with at least one assessment that season.
Personal best set150Per exercise.

Flat curve: 1,000 XP per level, forever. Level is derived from the XP ledger, never stored. All of these numbers need balancing against real training volume before launch.

Reference

Data model

EntityKey fieldsNotes
Memberid, fullName, gamertag, sex, dob, email, joinedAt, coachId, membershipStatus, displayNamePref, avatarUrlSelf-created with fullName, email, dob and sex. membershipStatus: none · active · lapsed; dob and sex are checked by the gym at linking and locked in app from then on (dobVerifiedAt). Gamertag unique database-wide.
Assessmentid, memberId, coachId, date, scores[5], total, tier, targetScores[5], notes, scope, requestIdPortal-written. Immutable once published; corrections create a new record. scope: full or a list of attributes; unscoped attributes carry over from the previous assessment.
AssessmentRequestid, memberId, seasonId, type, attributes[], status, requestedAt, slotAt, coachId, assessmentIdtype: reassessment · change. status: pending · booked · missed · cancelled · done. One open (pending, booked or missed) per member; a new one needs 4 days since the last assessment and more than 3 days left in the season. Only the portal can cancel a booked or missed request.
ExerciseResultid, assessmentId, exerciseId, attribute, rawValue, unit, score1to9, isPersonalBestFeeds attribute detail and per-exercise boards.
Seasonid, number, theme, startDate, endDate, weeks, statusupcoming · live · closed. Closing is a portal action.
SeasonEntryseasonId, memberId, total, position, tier, movementPosition derived at read time, not stored as truth mid-season.
TapInid, memberId, requestedAt, status, reviewedBy, reviewedAt, declineReason, sourcestatus: pending · approved · declined. source: member request or front-desk entry. Unique approved per member per day; approval writes the XpEvent.
XpEventid, memberId, source, amount, date, refIdAppend-only ledger; level derived.
Badgeid, memberId, badgeType, earnedAt, refIdPermanent; never revoked on a rank drop.
NotificationPrefmemberId, category, enabledOne row per push category.
Reference

Notifications matrix

Every notification has a matching activity entry; not every activity entry sends a notification. All types are on by default.

Push and in-app

NotificationTriggerDeep-link targetFull-screen
Placement results postedCoach submits an assessmentPlacement results, reveal animation intactHands off to reveal
Rank upNew total lands a higher tierRank reveal celebrationYes
Level upXP crosses a 1,000 XP thresholdLevel historyNo — toast
Level milestoneLevel 10, 20, 30 reachedLevel milestone celebrationYes
Visit loggedFront desk approves a tap-in (+100 XP)Game onNo
Tap-in not approvedFront desk declines a tap-inGame onNo
Membership linkedFront desk links the account to a membershipHomeNo
Assessment scheduledAdmin sets or changes the slotAssessment detailNo
Reassessment bookedAdmin books a requested reassessmentGame on (Booked)No
Season endingCountdown milestone, two days outSeasonNo
Season final standingsSeason closes, standings lockSeason (closed)No

Transactional email

EmailTriggerContains
Verify emailMember creates an accountOne-tap verification link
Password resetMember requests a resetReset link, 30-minute expiry
Appointment scheduledAdmin sets the assessment slotDate, time, coach

Rules

  • The two peaks arrive as notifications. Placement results and rank up are met in the notification tray, not found in the app; a tap lands on the moment, never on Home.
  • Rank notifications come only from an official coach assessment. No visit, XP award or leaderboard movement produces one.
  • One full-screen celebration per event. Rank up and level milestones take the screen; ordinary level-ups are a toast.
  • Achievements never notify on their own. A badge rides along with the event that unlocked it.

Open with NAOS

Whether a rank down notifies at all or is only visible in-app; quiet hours or batching for season countdowns; whether a declined tap-in carries the front desk's reason. Our call: no push on a rank down (the member meets it inside the app, framed factually), batch countdowns to one morning send, and carry the decline reason — a declined claim without a reason generates a front-desk conversation.

Reference

Activity feed

One event stream, read at two depths. Home · Activity shows the latest four entries with no unread state and no times — it reads as a record. The Activity screen (app bar icon, or Me → Activity) is the full feed with unread markers and timestamps. Tapping any entry deep-links to the screen that owns it.

EntryRecorded whenDeep-link targetNotified
Account createdMember signs up in the appEmail only
Membership linkedFront desk links the accountMembershipYes
Reassessment requestedMember sends a reassessment requestGame onNo
Reassessment bookedAdmin books the requested slotGame onYes
Assessment scheduledAdmin sets or changes the slotAssessment detailYes
Assessment completedCoach submits the assessment (+500 XP)Placement resultsYes
Fitness Rank setFirst placement lands a tierRank revealYes
Rank upA re-assessment lands a higher tierRank revealYes
Rank downA re-assessment lands a lower tierPlacement resultsOur call: no push
Personal best setA result beats a stored best (+150 XP)Attribute detailNo
Visit loggedFront desk approves a tap-in (+100 XP)Game onYes
Tap-in not approvedFront desk declines a tap-inGame onYes
Level reachedXP crosses a 1,000 XP thresholdLevel historyYes
Level milestoneLevel 10, 20, 30 reachedLevel milestoneYes
Achievement unlockedA badge trigger firesProfile badge gridRides with its event
Season endingCountdown milestoneSeasonYes
Season closedSeason ends, standings lock (+1,000 XP)SeasonYes

Rules

  • Entries are immutable. Activity is a log — a rank that went down stays in the record.
  • Announcements about the member count as activity. "Assessment scheduled" is set by the gym and still belongs in the feed.
  • XP-bearing entries state the amount ("+100 XP"); rank entries state the placement total.
  • Unread lives on the Activity screen only. Home stays clean.
  • No filtering or search. Four-week seasons keep the feed short.
Reference

Achievements

Permanent and discrete: once unlocked they never expire and never reset with the season. A badge awards a place on the Profile grid and nothing else — never rank, never an attribute score, never a board position. Locked badges stay visible with their name, so the grid is a goal surface. Visit badges use the flag icon and streak badges the flame; both carry their number in a corner pill (10 · 50 · 100, 4W · 8W · 12W) so tiers of the same badge read apart.

In the prototype

BadgeTriggerSource of truthRepeatable
First placementFirst official coach assessment is postedAssessmentNo
10 · 50 · 100 visitsApproved visits reach the milestone, all timeTapInNo
4 · 8 · 12 week streakThree approved visits a week, that many weeks runningTapInNo — longest streak kept
Gold tierPlacement total reaches the Gold band (15+)AssessmentNo — highest tier kept
Season podiumFinish a season in the overall top threeSeason closeOnce per season

Tier badges

One badge per tier reached, unlocked when an assessment first lands the member in that band — nine tiers, nine possible badges. Awarded on the highest tier ever reached, so a member who drops from Gold to Silver keeps the Gold badge. Iron is the pre-assessment state and is not awarded.

Proposed additions

BadgeTriggerNeeds
Balanced buildEvery attribute at 5 or above in one assessmentAssessment scores only
Target hitReach the coach's season target on every axisCoach-set target
Strength specialistStrength axis at 7 or aboveAssessment scores only
ComebackImprove the total after a re-assessment that went downPlacement history
Season regularVisit in every week of a seasonTapIn
ReferralA referred member completes a first assessmentAdmin action in the portal

Rules

  • Awarded by the system, never by a coach tapping "grant". Every trigger resolves from data the product already holds.
  • No XP is attached to a badge. XP comes from participation events and is listed in Level history.
  • Unlocks are notified as part of the event that caused them, never as a separate push.

Open with NAOS

One badge per tier (nine) or a single badge showing the highest tier reached; whether Season podium shows a repeat count; which proposed additions survive. Our call: nine tier badges — the grid is the goal surface and nine filled slots read better than one mutable badge — with a repeat count on Season podium.

Delivery

Portal dependencies

The coach and admin portal is a separate spec, but the member app cannot ship without these writes — none of which the app performs itself.

Portal actionWhat breaks without it
Find an app account by email, check dob and sex, and link it to a membershipSign-ups stay browse-only forever: no assessment, tap-ins or board entry.
Reassessment request queue: book a slot, reschedule, cancel a booked or missed requestRequests sit in Pending forever; a missed slot blocks the member from requesting again.
Publish an assessment (scores, total, season target)Rank never moves; radar, ladder, history and both peaks stay empty.
Schedule or change an assessment slotAppointment card and the unassessed Home hero have no content.
Tap-in queue: approve or decline, and add a missed visitNo visit XP at all — Level stalls and the between-assessment loop is dead.
Open and close a seasonNo season states, no final standings, no history, no season XP.
Reset a gamertagNo remedy for an abusive or mistaken tag.
Update membership statusThe lapsed block never fires.
Delivery

Open decisions

NAOS owns these. Each carries the recommendation the prototype already assumes.

DecisionOur callWhere it bites
Exercise list: workbook nine, or the agreed elevenShip the workbook nine; adding later needs no schema change.Per-exercise boards, attribute detail rows
Body fat: scored, and visible to whomRecord it, show member and coach, exclude from the total and public boards.Total range, thresholds, board count
Explosiveness combination ruleBest of the two exercises, matching how Strength resolves.Attribute detail for Power
3RM → 1RM estimationCoach enters 3RM, the system estimates.Attribute detail for Strength
Between-band resultsRound down — a band is earned, not approached.Fixture scores only
Divisions I–IVDrop for V1, keep the component API.Rank badge, ladder, Home card
ChallengesDecided: removed from V1. Replaced by attendance XP: member requests, front desk approves, +100 XP, one a day.Tab bar, Home, XP economy, badges
Season length and carry-overDecided: every rank resets at season start. The last season's final top 20 is shown on the Season screen as a record. Four-week length still assumed.Season, history, season XP, Home on day one
Reassessment requestsDecided: live season only, after the first placement, any one to five stats, one open request, 4-day cooldown, closed in the last 3 days, +500 XP. Booked slots are cancelled only by the gym; a missed slot must be cancelled by the front desk or coach before a new request. Replaces the one-time first-placement retest.Game on, Placement results, coach workload
Attendance namingDecided: tab is "Game on", the daily action is "Tap in", a request is a tap-in.Tab bar, notifications, copy
Eight tiers or nineNine — nine medals exist and Grand Master fills the 35 band.Ladder, thresholds, badge art
Registration modelDecided: self-service sign-up; front desk links membership by email. No in-app payment.First run, Membership, store review

Risks

  • The engagement gap. Visits are the only live loop. If the front desk is slow to approve, the app is quiet for weeks at a time.
  • Approval queue at peak hours. Every visit needs a front-desk tap. At 6–8 AM this is the busiest queue in the gym; batch approve in the portal is a must.
  • Thin boards at launch. One gym, many boards, two filter dimensions. The two-entry rule and the count line are the mitigation.
  • Front-desk workload is the real dependency. Under-staffed approval makes the member app look broken.
  • Reassessment load. A 4-day cooldown allows up to about six requests per member per season. Coach capacity, not the rule, will be the limit; watch the queue in the first season.
  • The name toggle is not privacy. On a small member base the top of a board is identifiable regardless — say so out loud.
  • Numbers are unbalanced. Thresholds, XP per level and rewards are illustrative until measured.
Delivery

Build hygiene

Demo panel

Demo panel

Prototype-only control surface: jump to screen, member state, season state, fire a moment, fire a notification, leaderboard density, tap-in today, reassessment state, display-name toggle, membership status, reset. Shake to open, with a deliberately off-brand magenta handle as the visible fallback.

It ships in App Distribution and TestFlight builds and must be strippable: one folder, one mount point behind a build-time flag, no inbound imports, state changes only through real app actions. Acceptance test: deleting the folder and the single mount line leaves a working app.

App version display

Profile renders Version 1.0.0 · Build 24. The build suffix is for dev, staging and tester builds only — production must render the version alone (Version 1.0.0). The string is built in one place in the profile view model; strip the suffix there behind the same release flag that strips the demo panel.

Platform pass

The system is iOS-derived. Android needs its own treatment for the back button, share sheet, system font fallback and navigation transitions. Do not assume pixel parity.