— The stack

Coach messaging unread counts: a state contract across client app and portal

Design viewer-scoped unread state for coach messaging, with late-arrival, offline-read and cross-surface reconciliation examples.

4 min readUpdated 2026-11-05By AptixLabs studio
Ordered messages: Stable server positions; Client cursor: Client-specific read state; Coach cursor: Independent viewer state; Badges: Derive by declared scopeAptixLabs · 2026-11-05

Original explanatory diagram using synthetic or proposed states; not a product screenshot. View full-size diagram

Unread messaging needs a viewer-specific state contract. Define which messages are beyond that viewer’s durable read position, then derive conversation and application badges consistently. Opening a thread, sending a message, receiving a push and marking a message read are different events. A local counter alone cannot preserve those meanings across devices.

Prerequisites are conversation membership, stable message ordering, a read-position representation and server-side access rules. The client and coach are different viewers even in the same conversation. One person reading a message should not clear the other person’s unread state.

Choose a durable read position

A proposed model can retain a server-issued sequence or another ordered cursor for each viewer and conversation. Use an ordering that the server can evaluate consistently, not a device wall clock that may differ between participants. Handle deleted or hidden messages under an explicit policy so the cursor remains interpretable.

Illustrative conversation trace
EventClient read positionCoach read position
Messages through 10 visible108
Coach opens and reads through 101010
Message 11 arrives for coach1010; one unread if eligible
Late acknowledgement through 9 arrives10Must not move backward from 10

This is a proposed sequence-based contract, not an executed product result. A read acknowledgement can advance monotonically to the greatest accepted position under the chosen model. If a thread is merely selected but not visible, decide whether that action meets the product’s definition of read.

Separate sent, delivered and read

A send response can mean the server accepted a message. Transport delivery can mean a destination received it. Read means the application’s defined viewing condition was met. Do not display read receipts from a push ticket or remove an unread badge because the sender successfully submitted text.

The reviewed UltraFit360 portal selects a conversation, calls markRead and totals conversation unread_count values. That source shows UI intent and badge derivation. It does not establish a durable cursor, cross-device propagation guarantee or a passed offline-read test. Trace the backend state before describing consistency as realtime.

Derive badges from one accepted model

Conversation badges, the messages tab and the overall application badge may have different scopes. Specify whether the top-level number counts unread messages, unread conversations or several notification types. A total labelled unread should not accidentally combine two counters for the same logical event.

GLF.Connect’s first-party support note describes separate message-tab, group and conversation counters. It illustrates why placement and scope matter to users, but it does not specify this application’s storage or synchronization architecture.

GLF.Connect: messaging counter placement and scope

Reconcile late events and access changes

After an offline read, persist the pending acknowledgement under the original account and conversation. On reconnect, reconcile with the server’s accepted position. A stale event should not restore a badge for messages already read, while a genuinely new message after that position should still appear unread.

Reassignment and revoked membership require a separate access transition. Clear or restrict cached conversation data under the product policy and reject unauthorized new reads. A read cursor does not grant conversation access. Account switching must not reuse another viewer’s badge cache.

Acceptance should cover two devices for one viewer, coach and client independently, a new message during thread viewing, late acknowledgement and membership removal. No messaging API or demo workspace was exercised here. Because no exact fictional UI state was verified, the researched screenshot becomes a viewer-position diagram, with synthetic message numbers clearly identified.

Pagination needs a viewing rule too. A client that loads the latest page should not mark older unseen messages read unless that is the documented conversation policy. Decide whether reading a later position implies all earlier eligible messages are read, and make that behavior consistent across web and mobile. Include a long fictional thread in acceptance so a badge result cannot pass only because every message fits on one screen. Keep group membership and per-viewer visibility in the same evaluation.

Realtime sync firestore

Building ultrafit360

Open the live UltraFit360 Coach portal

Bring one client-to-coach workflow, current data contract and acceptance constraint to discuss a bounded fitness product build or integration pilot.

Explore health fitness app development

How should unread counts stay consistent across a client app and coach portal?

Define unread against each viewer’s durable conversation position, then reconcile badges from that state rather than decrementing unrelated local counters.

Should a late read acknowledgement move a cursor backward?

Under a monotonic read-position model, no. Reconcile it with the greatest accepted position and preserve genuinely newer messages.

Need help with health & fitness app development?

Tell us about your product, existing stack and the problem you need to solve. We can discuss integration scope, implementation tradeoffs and a practical first milestone.

Start a conversation