Все работы

[ Личный мобильный продукт ]

TapyTap

Мобильный трекер привычек на Expo и React Native с бэкендом на Supabase — статистика, календарь и журнал заметок.

Роль
Mobile Developer
Команда
Соло
Период
2025 — настоящее время
Статус
In development
Приложение
  • React Native
  • Expo SDK 57
  • TypeScript
  • Reanimated
Состояние
  • Zustand
Бэкенд
  • Supabase
Главный экран TapyTap на iPhone: список привычек с категориями, сериями и отметками за день

Контекст

TapyTap — мой первый мобильный продукт. Основную часть я написал в июне 2025: привычки с категориями и напоминаниями, отметки выполнения, серии, календарь с тепловой картой, статистика, журнал заметок, архив, светлая и тёмная темы. Начинал на Firebase, через месяц перенёс аккаунты и данные в Supabase.

В октябре 2026 я вернулся к проекту, чтобы показать его здесь, и сначала прочитал код как чужой. Кейс о том, что нашлось и что я с этим сделал.

Моя роль

Единственный разработчик: продуктовые решения, интерфейс на React Native, состояние на Zustand, схема и правила доступа в Supabase.

Второй проход в октябре 2026 я делал вместе с ИИ-агентом: ставил задачи, разбирал его находки и проверял каждое исправление на iPhone.

Решение 1 / один источник данных

За год в приложении сложилось два слоя данных. Большинство экранов работало через стор на Zustand, а добавление и редактирование привычки и сортировка категорий — через старый модуль с собственным кэшем в AsyncStorage. Часть функций существовала в двух копиях, и записей через стор старый кэш не видел.

Из-за этого жили три ошибки. Редактирование стирало напоминания: экран добавления хранил их объектом, экран редактирования ждал массив и сохранял пустой список. Новая единица измерения у количественной привычки не сохранялась. Без сети форма новой привычки показывала уже удалённую категорию, а после смены аккаунта на том же телефоне — категории предыдущего пользователя.

Теперь все экраны пишут через один стор, кэш удалён вместе со старым модулем. Код стал короче на 461 строку.

Редактирование количественной привычки «Бегать утром»: тип, описание, цель серии, единица измерения
Нижняя часть той же формы: категории и напоминание в 09:20 по понедельникам, средам и пятницам
Редактирование привычки после перехода на один стор. Напоминание, заданное при создании, на месте; раньше этот экран сохранял пустой список.

Решение 2 / доступ к данным решает база

Ключ клиента Supabase публичный по замыслу: он зашит в каждую сборку и лежит в открытой истории репозитория. Значит, данные защищают только правила RLS в самой базе. У таблицы связей между привычками и категориями они пропускали любого вошедшего пользователя — он мог читать, удалять и создавать чужие связи.

Новые правила проверяют владельца через привычку, а при создании связи — ещё и владельца категории. Миграцию я проверил на локальной копии базы скриптом с двумя аккаунтами: из 14 сценариев со старыми правилами падали 6, с новыми проходят все.

Решение 3 / схема живёт в репозитории

Схема существовала только в облачном проекте Supabase. Я снял её в миграцию, и исправление доступа ушло на прод второй миграцией поверх неё. Заодно приложение переехало с Expo SDK 54 на 57, а из зависимостей ушли Firebase, оставшийся после переезда, и ещё две библиотеки, которые нигде не импортировались.

Результат / проверка

  • 15 экранов: привычки, календарь, статистика, журнал, архив, сортировка категорий и привычек;
  • Expo SDK 57 и React Native 0.86, tsc --noEmit без ошибок, expo-doctor — 21 из 21;
  • ручной прогон на iPhone в Expo Go: создание и редактирование привычек, сортировка, отметки, статистика и календарь;
  • правила доступа проверены 14 сценариями на двух аккаунтах.
Календарь привычки «Бегать утром» за октябрь 2026 и тепловая карта за полгода
Экран статистики: карта активности, продуктивность за неделю и месяц, список привычек с сериями
Статистика одной привычки: текущая серия, всего выполнено, прогресс за две недели
Журнал заметок, сгруппированных по месяцам и привязанных к привычкам
Календарь, статистика и журнал в тёмной теме, данные тестового аккаунта.

Ограничения

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