yukovsky.
Открыт к предложениям

Cozy World

Flutter-приложение, которое помогает паре быть ближе: счётчики важных дат, сообщение каждый день, карточки и история фото. Приложение написано вручную, без AI; Telegram-бот для контента сделан с помощью AI.

Зачем

Cozy World это небольшое общее пространство, которое помогает паре оставаться на связи каждый день. А ещё это доказательство, что я умею спроектировать и написать Flutter-приложение сам, без кода от AI.

Как это работает

На главном экране идут счётчики времени с важных для пары дат, и каждый день ждёт новое тёплое сообщение. Длинные записки лежат в карточках, которые переворачиваются и отмечаются прочитанными, а общие фото листаются как колода. Новые сообщения добавляются через Telegram-бота, обновлять приложение не нужно.

Что сделал я

Всё: идея, продуктовый дизайн, архитектура и код приложения, написанный вручную на Clean Architecture, GetX и GraphQL к Supabase. Telegram-бота, Supabase Edge Function на TypeScript и Deno, я сделал с помощью AI под своим руководством.

Статус

Приложение и бот работают вместе, оба открыты под MIT. Я продолжаю их развивать, последнее добавление: дневник питания с журналом состояния.

Роль
Автор и единственный разработчик
Период
2026 – сейчас
Статус
В работе
Стек
Flutter, Dart, GetX, Navigator 2.0, Ferry, GraphQL, Supabase, PostgreSQL, Lottie, TypeScript, Deno, Supabase Edge Functions, Telegram Bot API, GitHub Actions

Главное

  • Живые счётчики времени с важных для пары дат
  • Новое тёплое сообщение каждый день и категории с длинными записками
  • Карточки переворачиваются и отмечаются прочитанными, ничего не теряется
  • История фото, которую листаешь, как колоду воспоминаний
  • Новый контент приходит из Telegram-бота, а не с новым релизом
  • Flutter-приложение написано полностью вручную, без единой строчки кода от AI

Вместе

1362 дней 00:00:00

Telegram-бот

  1. 📅 Ежедневное сообщение
  2. Ближайший свободный день: завтра. Пришлите текст.
  3. Доброе утро! Кофе сегодня с меня ☕
  4. Сохранено. Календарь заполнен до завтра.
Пример содержимого. Иллюстрация процесса, не запись.
  • Главный экран Cozy World: приветствие, логотип с котиком и живые счётчики дней, часов, минут и секунд со дня знакомства и с тех пор, как появились «мы»Главный экран Cozy World: приветствие, логотип с котиком и живые счётчики дней, часов, минут и секунд со дня знакомства и с тех пор, как появились «мы»

    Главный экран: живые счётчики времени с важных для пары дат.

  • Дневник питания за день: иллюстрация пустого состояния и кнопка добавления приёма пищиДневник питания за день: иллюстрация пустого состояния и кнопка добавления приёма пищи

    Дневник питания в пустой день.

  • Форма нового приёма пищи: дата и время, кнопки добавить продукт, сканировать штрихкод, распознать по фото и добавить фотоФорма нового приёма пищи: дата и время, кнопки добавить продукт, сканировать штрихкод, распознать по фото и добавить фото

    Новый приём пищи: продукты вручную, по штрихкоду или по фото.

  • Форма приёма пищи, прокрученная до дневника состояния: место, уровень голода от 0 до 10, автоматические мысли, чувства и телесные реакцииФорма приёма пищи, прокрученная до дневника состояния: место, уровень голода от 0 до 10, автоматические мысли, чувства и телесные реакции

    В той же форме дневник состояния: голод от 0 до 10, мысли, чувства и телесные реакции.

1 / 4 Главный экран: живые счётчики времени с важных для пары дат.

Что это

Cozy World это маленькое общее пространство для двоих, чтобы каждый день оставаться на связи. Первый экран считает, сколько прошло с важных для пары дат, вплоть до часов, с небольшой анимацией сердечек. Каждый день ждёт новое тёплое сообщение. Записки подлиннее разложены по категориям: это карточки, которые переворачиваешь, читаешь и отмечаешь прочитанными, так что непрочитанные легко найти. На экране истории можно листать общие фотографии, как колоду карт.

Чтобы добавить сообщение, не нужно выпускать обновление приложения. Контент лежит в базе и управляется из Telegram-бота: написать сообщение на завтра можно за один разговор в чате.

Что я сделал

Небольшую систему из двух частей, обе с открытым кодом под MIT.

Flutter-приложение (репозиторий) написано полностью вручную: ни строчки кода, сгенерированного AI. Это показывает, что я могу сам, без AI, спроектировать и построить приложение, от архитектуры до последнего виджета. Основные экраны (счётчик, сообщение дня, категории с карточками, история фото) стоят на Clean Architecture со слоями данных, домена и представления. В приоритете Android, а собирается проект под все платформы Flutter.

Telegram-бот (репозиторий) это инструмент для контента за приложением. В отличие от приложения, его я делал с помощью AI под своим руководством. Он работает как Supabase Edge Function на TypeScript и Deno, управление через инлайн-кнопки:

  • Сообщение дня: вводишь текст, бот предлагает ближайший свободный день, выбираешь тип (текст, видео или аудио) и подтверждаешь.
  • Сообщение в категорию: выбираешь категорию или создаёшь новую и добавляешь текст.
  • Редактирование и удаление: постраничные списки сообщений дня или категорий, новые сверху, с фильтром непрочитанных категорий.
  • Очистка: предпросмотр прошедших сообщений дня, выгрузка их в чат и удаление.
  • Проверка дат: есть ли сообщение на сегодня и завтра и до какого дня заполнен календарь.

Обе части работают с одной базой Supabase Postgres. Бот пишет сообщения, приложение читает их через GraphQL и записывает обратно только отметку о прочтении.

  • Главный экран Cozy World: приветствие, логотип с котиком и живые счётчики дней, часов, минут и секунд со дня знакомства и с тех пор, как появились «мы»Главный экран Cozy World: приветствие, логотип с котиком и живые счётчики дней, часов, минут и секунд со дня знакомства и с тех пор, как появились «мы»

    Главный экран: живые счётчики времени с важных для пары дат.

  • Дневник питания за день: иллюстрация пустого состояния и кнопка добавления приёма пищиДневник питания за день: иллюстрация пустого состояния и кнопка добавления приёма пищи

    Дневник питания в пустой день.

  • Форма нового приёма пищи: дата и время, кнопки добавить продукт, сканировать штрихкод, распознать по фото и добавить фотоФорма нового приёма пищи: дата и время, кнопки добавить продукт, сканировать штрихкод, распознать по фото и добавить фото

    Новый приём пищи: продукты вручную, по штрихкоду или по фото.

  • Форма приёма пищи, прокрученная до дневника состояния: место, уровень голода от 0 до 10, автоматические мысли, чувства и телесные реакцииФорма приёма пищи, прокрученная до дневника состояния: место, уровень голода от 0 до 10, автоматические мысли, чувства и телесные реакции

    В той же форме дневник состояния: голод от 0 до 10, мысли, чувства и телесные реакции.

1 / 4 Главный экран: живые счётчики времени с важных для пары дат.

Технические решения

  • Clean Architecture вручную. Сценарии вроде «получить сообщение дня» и «изменить статус прочтения», интерфейсы репозиториев в доменном слое и регистрация зависимостей по слоям: данные, домен, представление. Строки, даты и ассеты вынесены в отдельные локальные пакеты, разделённые на API и реализацию.
  • GraphQL к Supabase через Ferry со сгенерированными типизированными запросами (build_runner, ferry_generator) к pg_graphql.
  • Свежие данные без лишних запросов. Небольшой механизм «грязного состояния» помечает списки категорий устаревшими после смены статуса прочтения, и перезагружаются только они.
  • GetX для состояния и внедрения зависимостей, Navigator 2.0 (Router API) со своим парсером маршрутов и делегатом, страницей 404 и выходом по двойному «назад».
  • Конфиг и секреты из --dart-define с запасным вариантом через flutter_secure_storage, локальное состояние в get_storage. CI проверяет каждый pull request и ищет утёкшие секреты.
  • Бот как конечный автомат. Сценарий и шаг каждого чата хранятся в JSON в таблице сессий Postgres, поэтому serverless-функция между обновлениями Telegram ничего не держит в памяти.
  • Защищённый вебхук. Функция принимает только POST-запросы с секретным заголовком Telegram, остальные отклоняет.
  • Учёт ведёт база. Триггер синхронизирует список категорий с таблицей сообщений, и ни приложению, ни боту не нужно поддерживать его самим.
  • Доставка. У бота есть тесты на Deno, и GitHub Actions прогоняет их перед деплоем функции в Supabase.

Результат

Приложение и бот работают вместе, и я продолжаю их развивать: в приложении теперь есть и дневник питания с дневником состояния. Скриншоты сняты с отладочной сборки в симуляторе iOS. Само приложение только на русском и только в светлой теме; английская и тёмная версии отрисованы из локальной копии с переведёнными строками и тёмной темой на цветах самого приложения, только для этих скриншотов.

Моя роль

Всё: идея, продуктовый дизайн, архитектура и код приложения, написанный вручную. Бот стал осознанным шагом в незнакомый стек (TypeScript, Deno, serverless), его я делал с помощью AI под своим руководством.

CV.pdf