Интерактивный путь изучения своей собаки — без перегруза. Документ объясняет простым языком, из каких экранов состоит фича, как они работают и что нужно, чтобы их собрать. Все скриншоты — сгенерированные ч/б прототипы.
Пользователь не «проходит курсы» и не «заполняет разделы». Он шаг за шагом изучает свою собаку, и каждое новое знание сразу превращается в действие внутри приложения: сохранить вес, добавить вакцину, начать курс, записать наблюдение.
В исходной концепции всё это показано как одна большая карта, которую можно таскать и масштабировать. На телефоне так делать не стоит: гигантская карта красива на слайде, но в руке она превращается в мелкие кнопки и вопрос «где я?». Duolingo прошёл этот путь и отказался от свободного дерева навыков в пользу простой вертикальной дорожки — прохождение выросло.
Карта — это данные, а не экран. Граф блоков с зависимостями лежит в JSON. А интерфейс показывает его тремя «окнами» разной подробности: одна карточка «что делать сейчас» → дорожка ветки → обзор всей карты.
Главный экран. Одна рекомендованная карточка, ноль выбора. Сюда пользователь возвращается каждый день.
Вкладка Journey. Три ветки, внутри каждой — вертикальный путь из блоков. Обычный скролл, крупные кнопки.
Вся карта одним взглядом, только для просмотра. Даёт ощущение масштаба пути — как и хотела команда.
Решение команды «карта видна целиком, включая будущие блоки» сохраняется: будущие блоки видны серыми на дорожке, а весь маршрут — на обзорной карте.
Каждый экран: что видит пользователь → как это работает → из чего собирать. Компоненты названы стандартными средствами SwiftUI — почти всё здесь нативное, без самописной графики. Важно: в блоках нет квизов — вместо них шаг «проверь на своей собаке», три варианта которого показаны на экранах 06–06в.
Одну большую карточку «Recommended now»: какой блок пройти и почему он важен именно для его собаки. Ниже — «Продолжить», если бросил блок на середине, и три тонких полоски прогресса веток.
ScrollView + VStack, карточки — обычные RoundedRectangle. Данные: поле recommended_block_id из манифеста карты.
Общий прогресс («6 из 21») и три ветки: Health & body, Mind & behavior, Breed & lifestyle. На рекомендованной ветке — метка «Recommended». Внизу — ссылка «View full map».
List или VStack из трёх NavigationLink. Прогресс считается из статусов блоков, ничего отдельно хранить не нужно.
Вертикальный путь из круглых узлов, как в Duolingo. Пройденные — закрашены с галочкой. Текущий — крупнее, с меткой «Now». Будущие — серые пунктирные с замочком, но с видимыми названиями: масштаб пути понятен заранее.
ScrollView + LazyVStack, соединительная линия — простая Shape между узлами. Никакого канваса, зума и физики. Это обычный список с красивыми ячейками — VoiceOver и Dynamic Type работают бесплатно.
Ровно три строки: что узнает → почему это важно именно для его собаки → какое действие сделает. И кнопка «Start · 4 min» с честной оценкой времени.
.sheet + presentationDetents([.medium]). Самый дешёвый экран документа.
3–5 карточек по 2–3 предложения, листаются свайпом. Одна мысль — одна карточка. Наверху точки прогресса, всегда виден выход.
TabView со стилем .page. Контент — из CMS/JSON, картинки — простые line-иллюстрации.
Квиз проверяет память («что ты запомнил про собак вообще») и в приложении уже приелся. Вместо него — шаг «Проверь на своей»: пользователь применяет только что изученное к собственной собаке одним тапом или жестом. Понимание проверяется применением, «неправильно» не существует, а каждый ответ становится датированной записью в профиле — растёт та самая «глубина профиля» из концепции. В блоке по-прежнему ровно одно взаимодействие: нагрузка не выросла, наоборот — работает узнавание, а не припоминание.
3–4 крупные картинки-эталона из только что изученной теории (силуэты кондиции тела, оттенки дёсен, состояние шерсти) и один вопрос: «Что больше похоже на Q сейчас?» Один тап — готово.
3–4 переиспользуемых шаблона (карточки-эталоны, живая шкала-слайдер) на весь контент. Выбор пишется в профиль как observation с датой.
Одну карточку-инструкцию («Зажмите лакомство в кулаке — что сделает Q?», «Потрогайте уши — тёплые или горячие?») и три крупные кнопки-исхода. Любой исход раскрывает интерпретацию: «что это говорит о вашей собаке».
Карточка + три кнопки, отложенный пуш через UNUserNotificationCenter. Исход пишется в профиль как поведенческий маркер с датой.
Один слайдер: «Сколько секунд Q выдержит команду "ждать"?» После ответа раскрывается ориентир для породы и возраста, и кнопка «Проверим?» ведёт прямо в действие блока.
Slider + карточка-раскрытие. Прогноз и факт пишутся парой в профиль.
Нативную форму той функции, про которую только что была теория: сохранить вес, добавить вакцину, загрузить фото. Одно короткое пояснение, крупное поле, одна кнопка.
Существующие формы + обёртка «шаг блока». Флаг завершения действия пишется в статус блока.
Галочку, список «что изменилось» (курс начат, вес добавлен в историю) и один следующий открывшийся блок с кнопкой «Continue».
Простой экран + UNUserNotificationCenter для отложенного пуша. Лёгкая хаптика .success, без конфетти-шоу.
Карточки-инсайты по метрикам его собаки: «Bond 55 — Q проверяет, где вы, на прогулке: хорошая ориентация на человека». В конце — «Recommended first» и кнопка «Show my path».
Те же карточки-страницы, что и теория (TabView). Контент — один вызов LLM на регистрацию, хранится с профилем.
Всю карту одним взглядом: три линии веток, закрашенное пройденное, метка «Now», чекпоинт, где ветки сходятся. Подпись «6 of 21 completed».
Один Canvas-рендер по заранее посчитанным координатам из манифеста. Строится за вечер, потому что интерактив минимальный.
Ровно четыре состояния, как в концепции. Состояние не хранится — оно вычисляется из прогресса и зависимостей.
Каждый блок — законченный мини-сценарий на 3–5 минут. Шесть шагов концепции складываются в пять экранов.
Манифест генерируется один раз при регистрации собаки (возраст, порода, метрики портрета) и дальше не перестраивается — меняются только статусы. Это в точности решение команды «карта стабильна».
{
"dog_id": "q-123",
"age_range": "puppy_4_8m",
"recommended_block_id": "impulse-control",
"branches": [
{
"id": "mind",
"title": "Mind & behavior",
"blocks": [
{
"id": "impulse-control",
"title": "Impulse control",
"needs": ["behavior-basics"], // что пройти сначала
"theory": "cms://impulse-101", // карточки теории
"check": {
"type": "predict", // или self_screen, hands_on
"content": "cms://impulse-predict",
"fallback": "self_screen" // если собака не рядом
},
"action": {
"type": "start_course", // или save_weight, add_vaccine...
"course_id": "impulse-course",
"auto_complete_if": "course_started" // правило авто-зачёта
},
"personal_note": "Impulse Control 22 — самая слабая метрика Q"
}
]
}
]
}
Статус блока приложение считает само: completed = теория + проверка «на своей» + действие; locked = не все needs закрыты; recommended = совпал с recommended_block_id; иначе available.
Шесть показателей из концепции, переведённые в конкретные события аналитики.
| Событие | Что измеряет | Показатель из концепции |
|---|---|---|
| journey_opened | Открыл карту / вкладку Journey | Начало пути |
| ai_interpretation_completed | Дочитал AI-расшифровку до конца | Начало пути |
| block_started / block_completed | Начал и завершил блок целиком | Обучение |
| check_completed (type) | Сделал проверку «на своей» (самоскрининг / руками / прогноз); для прогноза пишется дельта ожидание/факт | Обучение + Глубина профиля |
| action_completed (type, first_time) | Сделал действие; first_time — впервые воспользовался функцией через Journey | Изучение функций |
| course_started_from_journey | Начал курс после объяснения проблемы | Практика |
| profile_records_added | Сколько данных о собаке появилось через карту | Глубина профиля |
| journey_return_d7 | Вернулся к карте в течение недели | Возврат |
Пользователь понимает, почему ему предлагают следующий шаг, открывает функции в правильном контексте и постепенно собирает полноценную историю своей собаки. Если действия не делаются (только чтение) — фича не работает, сколько бы блоков ни проходили.