Готов · июль 2026 г.
Pulse
Метрики основателя из нескольких сервисов на одном экране

- 256
- Тесты
- 5
- Интеграции
Задача
Основатели каждое утро смотрят одни и те же числа, разбросанные по десятку вкладок: Stripe — выручка, GitHub — звёзды, npm — загрузки. Pulse собирает их на один экран. Оформление — простая часть. Настоящая работа началась раньше: числа должны быть корректными, дешёвыми для чтения и безопасными для повторной синхронизации, так, чтобы ничего не задваивалось.
Как это работает
Pulse брокерит OAuth через сервис подключений, поэтому база никогда не хранит сырой токен провайдера — только id подключения и немного метаданных. Через этот слой подключаются пять провайдеров: Stripe, Gumroad, GitHub, npm и Twitter. Данные сегодня тянутся у трёх: у Stripe, GitHub и npm, за которыми стоят нормализатор и расписание. Stripe опрашивается каждые пятнадцать минут (выручка и MRR), GitHub раз в час (звёзды), npm раз в сутки (загрузки).
Набор плановых задач с единой воронкой записи (крон, бэкафилл и ручное обновление) веерно расходится по подключениям и пишет один преагрегированный дневной снапшот на метрику. Запись идемпотентна: уникальный ключ по пользователю, провайдеру, метрике и дате плюс upsert означают, что повторный прогон дня никогда не задваивает — даже через полуночную границу часового пояса.
Деньги хранятся целыми в минимальных единицах и никогда не суммируются между валютами. Дашборд делит метрики на потоки, которые складываются (выручка, загрузки), и уровни, у которых берётся последнее значение (MRR, звёзды), и показывает дельту к предыдущему окну.
Таблица управляется сервером. Страница получает одну страницу строк и оконный итог за один round-trip, поэтому на загрузке нет клиентского водопада, а query-клиент подгружается только когда открываешь строку с деталями.

Дашборд на проде. У каждой KPI-карточки своя дельта к предыдущему окну, а в донате один Stripe: из подключённых источников выручка есть только у него.

Тот же экран в тёмной теме. Палитра задана в oklch, и автоматический аудит помечает такой контраст как incomplete вместо провала, поэтому пары на поверхности я проверил вычислением отношения.
Что вышло
Четыре KPI-карточки, area-chart выручки, донат по провайдерам и постраничная таблица метрик — в слое тем, где светлая и тёмная спроектированы, а не вывернуты одна из другой, с акцентом, который хранится для каждого пользователя и применяется без вспышки. 256 юнит-тестов покрывают логику агрегации и загрузки, сверху ещё восемнадцать браузерных сценариев. На продовой сборке дашборд держит мобильный perf-скор 92-94, доступность 100 и нулевой сдвиг layout.

По клику на строку рядом со снапшотом виден последний прогон синхронизации этого провайдера, вплоть до числа затронутых строк.
Демо
По живой ссылке вход одной кнопкой, письмо ждать не нужно. Аккаунт у всех посетителей общий, поэтому демо специально read-only: кнопки кликаются, но на запись прилетает уведомление вместо результата. Причина в подключениях. Без гейта гость привязал бы свой настоящий Stripe к общему демо-пользователю, и следующий, кто откроет страницу, читал бы чужую выручку. Гейт стоит на server actions и завязан на отдельный env-флаг, а не на почту аккаунта, чтобы локальная разработка и браузерные тесты продолжали работать с тем же пользователем. Тему и акцент это не касается: они лежат в куке, у каждого свои.
Чему я научился
Зелёные юнит-тесты против замоканного сервиса не доказывали ничего о реальном контракте. Подключение одного живого соединения вскрыло допущение об авторизации, которое моки тихо поощряли, и заставило добавить серверную перепроверку владельца. Второй урок дошёл не сразу: идемпотентный upsert безопасен ровно настолько, насколько полна питающая его выборка. Непостраничная выборка с последующей перезаписью тихо занижала выручку, и ни одна фикстура с чистыми круглыми числами этого не ловила.
Как это работает
От провайдера до дашборда.
Путь, который проходит каждое число, — три стадии, каждая опирается на предыдущую.
Подключение провайдеров
Stripe, GitHub и npm подключаются через OAuth-брокер, поэтому база хранит только id подключения — никогда сырой токен.
Ежедневный снапшот
Плановая задача читает полную постраничную историю и делает upsert одного снапшота на метрику в день. Уникальный ключ по пользователю, провайдеру, метрике и дате не даёт задвоить при повторной синхронизации.
Один экран
Четыре KPI-карточки, area-график выручки, донат по провайдерам и постраничная таблица — в слое тем, где светлая и тёмная спроектированы обе.