---
title: "S16 Home · Home"
description: "Contract, a board per state (first-time, normal, in-progress, completed, streak-risk, offline, no-quest, topic-empty, loading, error, empty), tokens and strings."
source: "design/hifi/S16/screen.md"
---

> Part of [Brand and design](/design/llms.txt). Every page: [llms.txt](/llms.txt).

# Hi-fi: S16 Home · Home

> Generated by `botgumi-design index` from `../../screens.json`. Edit that file, not this page.

Stage: **hifi** · Key: `home/home` · Data-binding map: [bindings.md](/design/hifi/s16/bindings/index.md)

Drawn in the gallery: [Home](/design/gallery/index.html#g-home). Each board is the committed HTML in `screens/`, drawn on the example data in `docs/api/examples/`.

## Contract

- **first-time**: First home after the paywall: streak 0, Lv.1 with diagnostic XP, quest = plan day 1, focus from the diagnostic.
- **normal**: Returning user, quest not started. Steps reflect the real stage (read = current, nothing pre-checked). Quest article is in a practice language.
- **in-progress**: today_quest.status = in_progress: read & retell done, compress current; CTA resumes the session.
- **completed**: Quest done today: result summary (needs CCR-2), streak flame filled, free practice offered.
- **streak-risk**: After 20:00 local with today not done (streak.at_risk): gentle card, mentions the freeze, no guilt copy.
- **offline**: No network: cached /v1/home with timestamp; training still starts (article cached, upload queued).
- **no-quest**: today_quest = null (CCR-1): no eligible article today → send to library.
- **topic-empty**: Quick-pick topic with no articles → explicit empty state, never a mismatched article.
- **loading**: Skeleton mirrors the real layout so nothing jumps; shown only on cold start with no cache.
- **error**: GET /v1/home failed with a retryable error and no cache available.

Flows: F1 First launch → diagnostic → paywall → first real session, F2 Daily quest, F4 Resume after the app was killed.

Reads and calls:

- `GET /v1/home (Accept-Language)`
- `GET /v1/config (cached 5 min)`

Local state:

- `local:cache.home (offline read cache)`
- `local:home.selectedTopic`

## Boards

One row per state. A state without boards of its own says what shows it.

| State | Board | Example data |
|---|---|---|
| first-time | [zh-Hans](/design/gallery/home/home--first-time.html) · [en](/design/gallery/home/home--first-time.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| normal | [zh-Hans](/design/gallery/home/home--normal.html) · [en](/design/gallery/home/home--normal.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| in-progress | [zh-Hans](/design/gallery/home/home--in-progress.html) · [en](/design/gallery/home/home--in-progress.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| completed | [zh-Hans](/design/gallery/home/home--completed.html) · [en](/design/gallery/home/home--completed.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| streak-risk | [zh-Hans](/design/gallery/home/home--streak-risk.html) · [en](/design/gallery/home/home--streak-risk.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| offline | [zh-Hans](/design/gallery/home/home--offline.html) · [en](/design/gallery/home/home--offline.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| no-quest | [zh-Hans](/design/gallery/home/home--no-quest.html) · [en](/design/gallery/home/home--no-quest.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| topic-empty | [zh-Hans](/design/gallery/home/home--topic-empty.html) · [en](/design/gallery/home/home--topic-empty.en.html) | home.json ([zh-Hans](/design/examples/zh-Hans/home.json) · [en](/design/examples/en/home.json)) |
| loading | [zh-Hans](/design/gallery/home/home--loading.html) · [en](/design/gallery/home/home--loading.en.html) |  |
| error | [zh-Hans](/design/gallery/home/home--error.html) · [en](/design/gallery/home/home--error.en.html) |  |
| empty | [no board of its own](/design/hifi/s16/bindings/index.md#states): From [states.md](/design/states/index.md) (Home): [home--no-quest](/design/gallery/home/home--no-quest.html) (CCR-1); [home--topic-empty](/design/gallery/home/home--topic-empty.html); first-time = [home--first-time](/design/gallery/home/home--first-time.html) |  |

### The boards

Each state as drawn (393 × 852), one board per locale. Open a board on its own for its spec panel.

**first-time**

[S16 first-time · zh-Hans](/design/gallery/home/home--first-time.html) [S16 first-time · en](/design/gallery/home/home--first-time.en.html)

**normal**

[S16 normal · zh-Hans](/design/gallery/home/home--normal.html) [S16 normal · en](/design/gallery/home/home--normal.en.html)

**in-progress**

[S16 in-progress · zh-Hans](/design/gallery/home/home--in-progress.html) [S16 in-progress · en](/design/gallery/home/home--in-progress.en.html)

**completed**

[S16 completed · zh-Hans](/design/gallery/home/home--completed.html) [S16 completed · en](/design/gallery/home/home--completed.en.html)

**streak-risk**

[S16 streak-risk · zh-Hans](/design/gallery/home/home--streak-risk.html) [S16 streak-risk · en](/design/gallery/home/home--streak-risk.en.html)

**offline**

[S16 offline · zh-Hans](/design/gallery/home/home--offline.html) [S16 offline · en](/design/gallery/home/home--offline.en.html)

**no-quest**

[S16 no-quest · zh-Hans](/design/gallery/home/home--no-quest.html) [S16 no-quest · en](/design/gallery/home/home--no-quest.en.html)

**topic-empty**

[S16 topic-empty · zh-Hans](/design/gallery/home/home--topic-empty.html) [S16 topic-empty · en](/design/gallery/home/home--topic-empty.en.html)

**loading**

[S16 loading · zh-Hans](/design/gallery/home/home--loading.html) [S16 loading · en](/design/gallery/home/home--loading.en.html)

**error**

[S16 error · zh-Hans](/design/gallery/home/home--error.html) [S16 error · en](/design/gallery/home/home--error.en.html)

## Tokens used

By path in `../../system/tokens.source.json`.

| Token | Where |
|---|---|
| `color.accentPrimary` | `.btn--primary` |
| `color.accentPrimaryPressed` | `.btn--primary` |
| `color.bgCanvas` | `.btn--light`, `.device`, `.screen`, `.tabbar` |
| `color.bgInverse` | `.banner--offline`, `.brand-mark`, `.chip`, `.level-badge` … |
| `color.bgInverseRaised` | `.focus-chip`, `.path`, `.skel`, `inline` |
| `color.bgSunken` | `.btn`, `.is-zero`, `.skel`, `.state-illo` … |
| `color.bgSurface` | `.btn--secondary`, `.card`, `.chip`, `.focus-chip` |
| `color.lineHairline` | `.btn--secondary`, `.btn--sm`, `.card--flat`, `.chip` … |
| `color.lineStrong` | `.btn--secondary` |
| `color.reward` | `.done`, `.dot`, `.focus-chip`, `.level-badge` … |
| `color.statusWarning` | `.at-risk`, `.streak-pill` |
| `color.textDisabled` | `.btn` |
| `color.textOnAccent` | `.btn--primary` |
| `color.textOnInverse` | `.banner--offline`, `.brand-mark`, `.chip`, `.current` … |
| `color.textOnInverseSecondary` | `.c-on-inverse-2`, `.chip`, `.path-dot`, `.path-label` |
| `color.textOnReward` | `.level-badge`, `.tag--reward`, `.xp-badge` |
| `color.textPrimary` | `.btn--light`, `.btn--secondary`, `.chip`, `.device` … |
| `color.textSecondary` | `.c-secondary`, `.state-illo`, `.tag` |
| `color.textTertiary` | `.c-tertiary`, `.chev`, `.chip`, `.is-zero` … |
| `color.topicAmber` | `inline` |
| `color.topicAmberSoft` | `.streak-pill` |
| `color.topicCoral` | `.topic-coral` |
| `color.topicViolet` | `.dot`, `.focus-chip` |
| `radius.button` | `.btn` |
| `radius.card` | `.card` |
| `radius.lg` | `.quest` |
| `radius.md` | `.card--md` |
| `radius.pill` | `.banner--offline`, `.btn--sm`, `.chip`, `.focus-chip` … |
| `radius.sm` | `.banner`, `.topic-tile` |
| `radius.xs` | `.tag` |
| `space.gutter` | `.chip-row`, `.pad`, `.section-head` |
| `space.s3` | `.section-head` |
| `space.s5` | `.card` |
| `space.s6` | `.has-tabbar`, `.screen` |
| `space.safeBottom` | `.has-tabbar`, `.screen`, `.tabbar` |
| `space.safeTop` | `.device`, `.screen` |
| `space.section` | `.section-head` |
| `space.sizeCtaHeight` | `.btn`, `.screen` |
| `space.sizeTabbarHeight` | `.has-tabbar`, `.screen`, `.tabbar` |
| `typography.caption1` | `.t-caption` |
| `typography.footnote` | `.t-footnote` |
| `typography.headline` | `.t-headline` |
| `typography.largeTitle` | `.t-large-title` |
| `typography.subheadline` | `.t-subhead` |
| `typography.title3` | `.t-title3` |

## Strings

`app.name`, `band.clear`, `common.continue`, `common.difficulty`, `common.error_code_retryable`, `common.read_minutes`, `common.retry`, `common.seconds_shorter`, `common.see_all`, `common.today`, `common.xp_plus`, `complete.stat.xp.replayed`, `complete.xp.level`, `growth.title`, `home.error.body`, `home.error.title`, `home.greeting.format`, `home.level.a11y`, `home.level.progress.a11y`, `home.level.xp`, `home.loading.a11y`, `home.offline`, `home.picks.empty.body`, `home.picks.empty.cta`, `home.picks.empty.title`, `home.picks.title`, `home.picks.topics.a11y`, `home.quest.cta.resume.compress`, `home.quest.cta.start`, `home.quest.done.more`, `home.quest.done.tag`, `home.quest.done.xp`, `home.quest.empty.body`, `home.quest.empty.cta`, `home.quest.empty.title`, `home.quest.focus.diagnostic`, `home.quest.focus.last`, `home.quest.label`, `home.quest.path.a11y`, `home.quest.plan_day`, `home.risk.body.freeze`, `home.risk.title`, `home.streak.a11y.done`, `home.streak.a11y.todo`, `micro.conclusion_first`, `notif.daily.title`, `notif.risk.body.freeze`, `paywall.calendar.legend.today`, `paywall.calendar.streak3`, `paywall.projection.score`, `paywall.restored.cta`, `processing.unreliable.reason_label`, `read.nav`, `read.tag.daily`, `record.nav.round1`, `resume.cta`, `tab.growth`, `tab.home`, `tab.library`, `tab.nav.a11y`

## Notes for the app tracks

Motion, haptics, Dynamic Type and VoiceOver: [engagement.md](/design/engagement/index.md), [tokens.md](/design/tokens/index.md) §6–7 and
[ios-handoff.md](/design/ios-handoff/index.md). Open a board with `?theme=dark&dt=1.35&binds=1` to see dark mode, the largest
tested type size and every bound element.

Tracking-plan events: no tracking plan page exists yet; ADR-001 D12 names the events.

Tokens with no group in `system/tokens.source.json` yet (they stay in [tokens.css](/design/tokens.css)): `--dt`, `--elevation-1`, `--elevation-2`, `--font-family-numeric`, `--font-family-reading`, `--font-family-text`, `--font-weight-bold`, `--font-weight-heavy`, `--font-weight-medium`, `--font-weight-regular`, `--font-weight-semibold`, `--motion-duration-celebrate`, `--motion-duration-fast`, `--motion-duration-instant`, `--motion-ease-emphasized`, `--motion-ease-standard`, `--type-tracking-tight`.
