Invert the data flow on attendance: the swimmer marks themselves attending (or not), the coach confirms. The coach's job at the pool becomes review + tap Start, not mark-everyone. Switching the onus onto the swimmer removes the highest-friction step from the coach's path to the live stopwatch.
Verbatim user direction (2026-07-02): "the swimmer pick what
training sessions thay are planning to addend (from the swimmer
account). all the coach has to do is confirm. this switches the
owness onto the swimmer to mark their attendance rather than the
coach."
Three properties, in order of leverage:
resource in the system.** Every tap the coach spends on the screen is a tap NOT spent watching technique, watching swimmers come in, watching the clock. Reducing coach screen-taps is the highest-leverage UX change available.
before practice starts.** Asking the coach to know — and encode — this information is asking the wrong person. The swimmer is the source of truth on attendance intent.
start timing for N swimmers. Removing the N taps also removes the cognitive load of remembering who's present.
The swimmer opens their Swimmer Home → sees the upcoming week (Mon-Sun) → for each scheduled session, taps "I'm in" or "Can't make it." This writes to a future swimmer_attendance_intent table (separate from session_roster, which keeps its tight "locked" semantics). The coach's Today view sees the swimmer intents in real-time (via Supabase Realtime or polling).
Why this is a separate table, not a status column on session_roster: session_roster is write-once at session start. The "intent" is multi-state (planned → confirmed → attended → absent) and can be edited multiple times. Mixing them invites the same bug surface that recorded_times.intensity + workout_sets.intensity_label already creates (two truth sources, drift between them).
At the start of practice, the coach sees the session-day roster on Today view as a single non-intrusive row badge: "8 of 12 swimmers marked attending." Tapping the row opens an inline editor (popover, NOT sheet) that lets the coach add/remove without leaving Today. One tap to start timing.
Verbatim user direction (2026-07-02): "the UI mentions that 8
swimmers are mark as attendeding, non intrusive (unlike the
dedicated popup) and allows the coach to edit the attendee
list by tapping it."
The coach only has to mark attendance ONCE per workout, not once per lap per set. The reason: all swimmers in the roster will complete the whole set. If a swimmer leaves mid-set, the coach doesn't pause timing to update attendance — the swimmer's recorded_times rows simply don't get assigned at the end (or get marked attended=false). The roster is a START state, not a CONTINUOUS state.
Verbatim user direction (2026-07-02): "the attendance should
only have to be marked once per workout. this is intuitive, as
all the swimmers will complete the whole set."
This collapses the model significantly. We don't need per-session attendance events; we need a single "who is in today" snapshot at session start.
The user explicitly named the design constraint:
Verbatim user direction (2026-07-02): "people that have been
coaching for 20 years shouldn't be made to feel out of place
— hence the intuitive nature we want for the app."
A 20-year coach's muscle memory is: see who's on deck, start the clock. The app's job is to support that workflow, not introduce a new one. Concrete implications:
Open the app, see today. This is how a 20-year coach expects the app to feel.
an empty list. Coach doesn't have to "remember" who's on the squad — the app remembers.
intent" button. No "roster locked" toast. The coach sees swimmers → confirms one-tap → starts.
full-screen sheet. The coach's eyes stay near the pool.
pre-practice work moves to the swimmer account, which the swimmer opens on their own time (the night before, during the drive to practice, etc.).
This idea slots into the same invisible-data-pipeline principle as the T6/T7 Welford trigger (auto-update of calibration stats on every recorded_times insert — no coach data entry) and the PB auto-detect (a swim faster than the swimmer's existing PB becomes the new PB on save — no manual PB entry). All three together:
| Action | Coach does | System does |
|---|---|---|
| Mark attendance | Confirms row badge (1 tap) | Swimmer marked via their app |
| Save a lap | Taps LAP | Welford updates calibration stats |
| Update PB | (nothing) | New PB detected from training data |
The coach's only data-entry responsibility becomes marking the set the swimmers are about to do. Everything else auto-populates or auto-fills.
swimmer_attendance_intent asingle boolean (in/out) or a 4-state (planned → confirmed → attended → absent)? Single boolean is the ponytail answer; ship that, add states if needed.
At "Lock Roster" button? The simpler the trigger, the fewer bug surfaces.
swimmer says "I'm in," the coach sees the list and removes them (injured today, etc.). The intent should NOT be deleted — it should be overridden by the coach's roster. Future sessions need to see the original intent.
the coach changes their attendance? Probably not for the simple version; coach is the authority.
effortlessness," the design principle this brainstorm extends
press / animation vocabulary that should apply to the confirmation popover (tap-into-row should feel different from tap-to-start)
motion channel for the confirmation experience (no text copy, just a haptic + animation)
downstream of the auto-populated data; the analytics surface consumes calibration stats that the T6/T7 trigger populates
on how what we've just dicussed fits into the vision, then start planning the implemention for an intuitive and seemless UX. people that have been coaching for 20 years shouldn't be made to feel out of place—hence the intuitive nature we want for the app."
Published and managed by TARS, an AI co-author built on Nathan's gbrain.