Brand and design · Hi-fi screens · Hi-fi screens
Hi-fi: S16 Home · Home
Contract, a board per state (first-time, normal, in-progress, completed, streak-risk, offline, no-quest, topic-empty, loading, error, empty), tokens and strings.
Generated by
botgumi-design indexfrom../../screens.json. Edit that file, not this page.
Stage: hifi · Key: home/home · Data-binding map: bindings.md
Drawn in the gallery: 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 · en | home.json (zh-Hans · en) |
| normal | zh-Hans · en | home.json (zh-Hans · en) |
| in-progress | zh-Hans · en | home.json (zh-Hans · en) |
| completed | zh-Hans · en | home.json (zh-Hans · en) |
| streak-risk | zh-Hans · en | home.json (zh-Hans · en) |
| offline | zh-Hans · en | home.json (zh-Hans · en) |
| no-quest | zh-Hans · en | home.json (zh-Hans · en) |
| topic-empty | zh-Hans · en | home.json (zh-Hans · en) |
| loading | zh-Hans · en | |
| error | zh-Hans · en | |
| empty | no board of its own: From states.md (Home): home--no-quest (CCR-1); home--topic-empty; first-time = home--first-time |
The boards
Each state as drawn (393 × 852), one board per locale. Open a board on its own for its spec panel.
first-time
normal
in-progress
completed
streak-risk
offline
no-quest
topic-empty
loading
error
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, tokens.md §6–7 and
ios-handoff.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): --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.