Skip to content

Coach conversations

A coach conversation is a scripted chat the Coach plays in the Coach tab. It's an ordered list of chat items — messages, reply choices, and cards that launch sessions, sounds, or actions. This is the most structured content type, so this page is the longest.

Follow The authoring model for parent/translations, status, slugs, and validation.

Coach tab conversation view

Parent fields

Field What it means
Slug Stable id, e.g. welcome, morning_default.
Opening module Optional coach module spliced in at the start (e.g. a greeting).
Closing module Optional coach module spliced in at the end (e.g. an optional check-in prompt).

Translation fields

Field What it means
Items The ordered chat script — a list of items, each with a type. This is the bulk of the work; the item types are below.
Push copy A short notification line associated with the conversation. (Currently not used at send time — push bodies live in the Coach Schedule — but the field is still authored.)

The item types

Each item in Items has a type that decides what it renders as. Items you don't recognise are ignored by the app, but the save-time check (coach-content-validate) will reject malformed known items.

Messages

  • received_bubble — a message from the Coach. Fields: text (and an optional leading_space for extra spacing above).
  • sent_bubble — a message shown as if from the user. Field: text.

Letting the user choose: reply chips + branching

  • reply_chip_row — a row of tappable reply chips. Needs an id and a list of chips, each with a label and either a navigation target or an action (see actions below). A chip can carry a tag (a short keyword stored when the user taps it) and is_last_step.
  • tag_matchconditional branching. It has a source (the id of an earlier reply_chip_row) and branches — a map from the chip's tag to a sub-list of items. The Coach plays the branch matching what the user picked. The source must reference a reply_chip_row that appears earlier in the same list — the save check enforces this so a branch can't dangle.

Cards that launch content

These are the cards that connect a conversation to the rest of the app.

session_card — launch a Library session

Always needs session_id (the session's template kind, e.g. audioGuided). Then one of two forms:

  • Reference form (preferred) — supply session_slug and omit the title. The app pulls the title, image, and duration from the session itself, so the card always matches the live session. Author this whenever the card points at a real session.
  • Literal form — supply an authored title (and optionally duration). Use this only when there's no backing session row to resolve from.

The save check verifies the session_slug resolves to a real session. A card with neither a title nor a slug is rejected.

sound_card — launch a sound or album

Needs ref_kind and ref:

  • Album: ref_kind: album, ref = the album slug (e.g. ocean). Renders as the album with an "N sounds" count.
  • Track: ref_kind: track, ref = the track's id. Renders as the single track with its duration.

The save check verifies the album slug / track exists and is published. (There's no "literal" sound card — for a plain promo, use a teaser_card with a navigate:/sounds/... link instead.)

teaser_card — a promo / call-to-action

A visual card with a title, subtitle, and an icon, plus exactly one of:

  • a navigation target (a route), or
  • an action (see actions below).

Icons (pick from this set): self_improvement, air, headphones, lightbulb_outline, nightlight_round, psychology, insights_outlined.

The first check-in card is a teaser_card with action: check-in:open. That action opens the check-in sheet in place, and the card automatically shows a "Done" badge and stops responding to taps once the user has completed a check-in (by any route). Use icon: insights_outlined (the Progress icon) for it.

Structural items

  • day_divider — a labelled divider (e.g. "Day 1").
  • week_strip — the week indicator strip.
  • collapsed_days_link — a "show earlier days" link with a target.

Actions and navigation targets (closed sets)

Where an item takes an action, the allowed values are:

  • complete — marks the step/conversation complete.
  • noop — does nothing (placeholder).
  • check-in:open — opens the check-in sheet (the first-check-in CTA).
  • navigate:<route> — navigates to a route (see below).

Where an item takes a navigation route (target, or inside navigate:<route>), it must be one of the known routes — the save check rejects anything else, so a typo can't ship a dead link:

  • Tab roots: /coach, /library, /sounds, /progress, /profile
  • Progress detail: /progress/detail/{sleep,feeling,awareness,activity}
  • Profile sub-pages: /profile/{notifications,appearance,account,privacy,about}
  • A session: /sessions/<template-kind>
  • A sound album: /sounds/album/<album-slug> (album must exist)
  • A single track: /sounds/track/<track-id>
  • A Library category: /library/<category>

What blocks a save

  • A session_card whose session_slug doesn't resolve to a real session.
  • A sound_card whose album slug / track doesn't exist or isn't published.
  • A teaser_card/chip with a navigate: route outside the known set.
  • A teaser_card with both (or neither) target and action.
  • A tag_match whose source doesn't match an earlier reply_chip_row id.
  • Any malformed item (missing required fields for its type).

Where it shows up

The Coach tab plays the conversation top to bottom: messages appear, reply chips wait for a tap, branches resolve from the user's earlier choices, and cards render as tappable tiles that launch the session/sound or run the action. The opening/closing modules are spliced in around the items, and the schedule decides which conversation plays when.

See also