С 22 мая по 3 июня один разработчик перевёл шесть лет персональных спортивных данных из разрозненных Excel-таблиц в полноценное десктопное приложение. Проект прошёл через смену архитектуры, 79 миграций базы данных и несколько раундов оптимизации производительности.

История началась не с кода, а со спорта. С 2020 года автор фиксировал тренировки сначала в заметках телефона, потом в бумажной тетради, затем в Excel. Постепенно туда переехали питание, вес, процент жира, замеры тела и аналитика прогресса. К весне 2026 года таблиц стало столько, что обслуживание системы учёта само по себе превратилось в задачу. Период вынужденного простоя дал время попробовать объединить всё в одну систему.

СлойТехнологияРоль
ОболочкаElectronЗапуск приложения, управление backend, упаковка в exe
ИнтерфейсFrontend (веб)Страницы, графики, формы, клиентский кэш
BackendFastAPIREST API, бизнес-логика, импорт, аналитика
Хранилище личных данныхSQLite (workouts.db)Тренировки, вес, питание, токены, настройки
Хранилище справочниковSQLite (shared.db)Продукты, упражнения, велосипедные коэффициенты
СинхронизацияYandex Disk APIТранспортный слой между устройствами
Импорт тренировокPolar AccessLinkПульс, спортивная статистика

Первая попытка — Streamlit — продержалась несколько часов. Фреймворк пересчитывает весь интерфейс при каждом взаимодействии пользователя: для прототипа это терпимо, но тысячи записей тренировок, питания и замеров делали приложение непригодным для ежедневного использования. 24 мая было принято решение переписать проект с нуля.

Новая архитектура устроена как миниатюрная клиент-серверная система, работающая полностью локально. Electron запускает оболочку и упаковывает приложение в exe-файл. Фронтенд отвечает за интерфейс, графики и клиентский кэш. FastAPI-backend обрабатывает REST API, бизнес-логику и аналитику. Данные хранятся в двух SQLite-базах: workouts.db содержит личные записи, OAuth-токены и настройки, shared.db — справочники упражнений, продуктов и велосипедных коэффициентов. Backend подключает shared.db через механизм ATTACH, не смешивая личные данные с публичными справочниками. Внешние сервисы — Yandex Disk API для синхронизации между устройствами и Polar AccessLink для импорта тренировок — подключаются только когда нужны.

Разделение баз решило практическую проблему: личные данные не попадают в публичный репозиторий, а справочники поставляются вместе с установщиком. Схема данных прошла 79 миграций — последние были уже не про добавление колонок, а про архитектурный порядок: перенос пользовательских рационов из shared.db в workouts.db, выделение канонического справочника силовых упражнений, разделение упражнений на strength и stretching.

По мере роста функциональности появились проблемы производительности. Самый показательный случай — экран кардио-тренировок. Backend получал список тренировок, а затем для каждой отдельно запрашивал HR-статистику из таблицы пульса. Классическая проблема N+1: один экран порождал десятки дополнительных запросов к SQLite. Решение — batch-запросы: backend получает список workout_id и одним запросом забирает агрегаты avg_hr и max_hr сразу по всем нужным тренировкам. Главный экран, который раньше открывался через несколько параллельных запросов за весом, тренировками, питанием и аналитикой, получил агрегированный endpoint GET /api/dashboard/home. Тяжёлые блоки загружаются отдельно и только по необходимости. Дополнительно добавлены индексы по user_id, датам и workout_id — для локального приложения с большой историей это критично, поскольку SQLite без индексов сканирует всю таблицу целиком.

Интеграция с Polar AccessLink оказалась нетривиальной. Данные приходят в сыром JSON, который нужно разобрать, привязать к типу тренировки и сохранить временной ряд пульса в таблицу workout_heart_rate. Отдельная сложность — пульсовые сэмплы: поле sample-type не всегда надёжно размечено в разных payload. Парсер проверяет не только тип, но и содержимое: если значения попадают в диапазон 25–240 bpm, они обрабатываются как HR-ряд. Это даёт график пульса по времени для каждой кардио-тренировки.

Проект показывает, как ИИ-инструменты разработки изменили порог входа в создание полноценных десктопных приложений: автор прямо указывает, что купил подписку на такой инструмент на второй день работы. Стек Electron плюс FastAPI плюс SQLite — не новый, но для персонального локального приложения он даёт предсказуемую производительность, полный контроль над данными и возможность работать без интернета.