Как я перестал делать ещё один график Kp и собрал Гелиошторм
Когда говорят о магнитных бурях, разговор обычно быстро скатывается в одну из двух крайностей. Либо перед вами таблица с индексами, в которой обычному человеку ничего не понятно. Либо заголовок в духе «Землю накроет мощнейшая буря, готовьтесь страдать».
Мне не нравился ни один вариант.
Поэтому я сделал Гелиошторм — русскоязычный сервис, который следит за геомагнитной активностью, показывает прогноз по городам и пытается перевести сухие данные в нормальный человеческий ответ: что происходит сейчас, будет ли буря и стоит ли сегодня внимательнее отнестись к самочувствию.
Первый рабочий контур я собрал за несколько дней. Но довольно быстро выяснилось, что подключить API NOAA и нарисовать график — самая простая часть задачи. Сложнее было понять, зачем человеку возвращаться на сайт, когда никакой бури нет. А её большую часть времени действительно нет.
В этой статье расскажу, как проект вырос из очередного Kp-трекера в сервис про ежедневное самочувствие, какие решения пришлось переделать и где я специально не стал изображать научную точность.
С чего всё началось
До Гелиошторма я делал HantaWiki — мониторинг открытых источников по хантавирусу. От него осталась рабочая инфраструктура: Next.js-приложение, PostgreSQL, карта, web-push, генерация страниц и небольшой Python-пайплайн.
Когда появилась идея сервиса про космическую погоду, я не стал героически начинать с пустого репозитория. Взял проверенный каркас, выкинул предметную логику HantaWiki и заменил её новым пайплайном.
Это сильно ускорило старт. Уже в первый заход появились:
загрузка актуального Kp и прогноза NOAA;
база измерений и событий;
детектор магнитных бурь;
главная с текущей обстановкой;
архив по дням и месяцам;
страницы городов;
карта и прогноз на ближайшие дни.
Такой подход не очень романтично выглядит в рассказах про запуск стартапа, зато он практичный. Если карта, пуши и деплой уже однажды заработали, нет смысла заново доказывать себе, что я умею их собирать. Лучше потратить время на то, чем новый продукт действительно отличается.
На тот момент я думал, что отличие очевидно: западные сервисы в основном помогают охотиться за северным сиянием, а я сделаю понятный монитор магнитных бурь для русскоязычной аудитории.
Через пару дней стало ясно, что этого мало.
Проблема первого MVP: он был нужен только во время бури
Первая версия отвечала на стандартные вопросы:
какой Kp сейчас;
ожидается ли буря;
что будет сегодня и завтра;
где активность ощущается сильнее;
какие бури происходили раньше.
Всё это полезно, когда Солнце действительно решило устроить событие. Но в спокойный день пользователь открывает сайт, видит Kp 2 и закрывает вкладку. Завтра у него нет причины возвращаться: скорее всего, там снова будет Kp 2 или 3.
Для информационного проекта это нормальная модель. Для продукта, которым хочется пользоваться регулярно, — слабая.
Тогда я сформулировал проблему проще: люди приходят не за индексом Kp. Они приходят с вопросом «почему мне сегодня плохо?» или «не будет ли завтра хуже?».
Ответ «Kp равен 5,67» для большинства людей бесполезен. Сначала надо объяснить, что Kp — это планетарный индекс геомагнитной активности по шкале от 0 до 9. Значения от 5 соответствуют магнитной буре уровня G1, от 6 — G2 и так далее. Потом всё равно останется главный вопрос: что человеку делать с этой цифрой?
Вот здесь проект и начал меняться.
Поворот от магнитных бурь к ежедневному самочувствию
Магнитная активность — не единственный природный фактор, на который жалуются метеочувствительные люди. Гораздо чаще меняются атмосферное давление и температура. Они же дают сервису ежедневный сценарий, которого не хватает чистому трекеру бурь.
Я добавил индекс природной нагрузки от 0 до 10. Он рассчитывается из трёх факторов:
текущего геомагнитного фона относительно порога выбранного города;
изменения атмосферного давления за последние сутки;
ожидаемого перепада температуры.
Для разных состояний веса различаются. В профиле «Мигрень» сильнее учитывается давление, в профиле «Суставы» — смена погоды, в профиле «Сердце» выше вес геомагнитного фона и давления. Есть также общий профиль.
Важно: это не медицинская модель и не попытка поставить диагноз по браузеру. Это продуктовая эвристика — понятный ориентир, который собирает несколько разрозненных показателей на одном экране. Небольшие обычные колебания не повышают балл, а при отсутствии части данных сервис показывает полноту оценки. Формула открыто показана пользователю, а рядом всегда есть оговорка, что при плохом самочувствии нужно обращаться к врачу.
Число считает обычный код. Нейросеть используется только для короткого текстового пояснения. Если AI недоступен, сервис показывает совет, собранный по правилам. Я сознательно не отдавал модели сам расчёт: красивый текст может быть вероятностным, итоговая цифра — нет.
Это был первый момент, когда проект стал похож не на тематический сайт, а на продукт. У него появился ежедневный вопрос, на который можно отвечать даже при спокойном Солнце.
Город важнее планеты
Kp — планетарный индекс, но пользователь живёт не «на планете вообще», а в Минске, Москве, Мурманске или Сочи.
Для городов я храню координаты, геомагнитную широту и порог, начиная с которого активность имеет практический смысл для конкретного региона. Одна и та же геомагнитная обстановка по-разному выглядит для северного и южного города. Это особенно важно для карты и оценки вероятности увидеть сияние.
Город можно выбрать вручную или определить по геолокации. После этого сервис подставляет местную погоду из Open-Meteo, показывает изменение давления и строит персональный индекс уже для выбранного региона.
С инженерной точки зрения это простая склейка двух источников: NOAA отвечает за космическую погоду, Open-Meteo — за обычную. С продуктовой точки зрения именно эта склейка превращает абстрактный глобальный показатель в локальный сценарий.
Пользователю не обязательно знать, откуда пришли данные и как соединяются таблицы. Ему важнее увидеть: «В моём городе давление упало на 9 гПа за сутки, магнитный фон спокойный, основной фактор сегодня — погода».
Я хотел проверить не общую теорию, а личную закономерность
У разговоров о метеозависимости есть неприятная особенность: почти любой единичный случай можно объяснить задним числом. Заболела голова — значит, была буря. Не было бури — значит, давление. Давление стабильное — значит, резкая смена погоды.
Поэтому следующим шагом стал ежедневный чек-ин.
Пользователь отмечает самочувствие по шкале от «плохо» до «отлично» и при желании выбирает симптомы: голова, давление, усталость, плохой сон, суставы или раздражительность. Запись связывается с индексом и факторами этого дня.
История хранится без обязательной регистрации, по идентификатору устройства. На странице видны последние отметки и серия дней подряд. Когда данных становится достаточно, сервис сравнивает среднее самочувствие в дни с высоким индексом и в спокойные дни.
Это пока простая корреляция, а не исследование. Но она честнее универсального утверждения «магнитные бури влияют на всех». Для одного человека закономерность может проявиться, для другого — нет. В перспективе ценность проекта именно в этом: не убедить пользователя в метеозависимости, а помочь ему накопить собственные наблюдения.
«Пульс города» появился из той же логики
Из чек-инов вырос ещё один экран — агрегированное самочувствие города.
Если люди оставляют отметки, можно показать, сколько из них сегодня жалуются на головную боль, усталость или сон, а сколько не отмечают никаких симптомов. Получается небольшой «пульс» в духе народных отметок в погодных приложениях.
Здесь есть очевидная проблема холодного старта. Пока пользователей мало, блок честно пишет, что сегодня ещё никто не отметился. Я не подставляю демонстрационные проценты и не создаю видимость сообщества.
Но сама механика кажется мне перспективной. Официальные данные рассказывают, что происходит с магнитным полем и погодой. Пользовательские отметки показывают, совпадает ли это с ощущениями людей здесь и сейчас.
Со временем такой слой может стать полезнее очередной статьи «как буря влияет на организм», потому что он отвечает на более конкретный вопрос: «Другие люди рядом сегодня тоже это чувствуют или дело, скорее всего, не в погоде?»
Пуши: прогноз и факт нельзя смешивать
Уведомления о бурях оказались отдельной продуктовой задачей.
Самый простой вариант — отправлять пуш, как только прогноз пересекает порог. Но прогноз может измениться, а буря — не начаться. Если несколько раз предупредить человека о событии, которого не было, он перестанет доверять сервису или просто отключит уведомления.
Поэтому в Гелиошторме два разных типа сообщений.
Первое — предварительное. Оно приходит один раз, если NOAA ожидает бурю уровня G2 или выше в ближайшие 72 часа. Такое уведомление не считается срочным.
Второе — подтверждённое. Оно отправляется, когда реальные измерения показывают, что буря началась. Только активная сильная буря уровня G3 и выше может обойти режим «не беспокоить».
Прогнозные и реальные значения хранятся отдельно. Детектор регулярно пересобирает события, переводит их между статусами «прогноз», «идёт» и «завершена», но не должен повторно отправлять один и тот же пуш. Для этого отметка о предварительном уведомлении записывается прямо в метаданные события.
Однажды NOAA отдал повреждённый JSON именно рядом с началом активности, и поллер пропустил обновление. После этого я добавил несколько попыток загрузки с задержкой. Это мелкая техническая деталь, но она хорошо показывает реальную цену надежности: пользователь не заметит сто успешных запусков cron, зато заметит один пропущенный шторм.
Почему бури появились в календаре
Пуши требуют разрешения, а сайт легко забыть. Поэтому я искал канал, который останется с пользователем без установки отдельного приложения.
Так появилась подписка на календарь.
Гелиошторм отдает обычный iCal-фид. Его можно один раз подключить к Google, Apple или Яндекс Календарю. Будущие прогнозные бури автоматически появляются как события с уровнем, пиком Kp, ссылкой на подробности и напоминанием за шесть часов.
Календарь периодически перечитывает фид, поэтому прогноз может обновляться без действий пользователя. Это не разовый экспорт файла, а живая подписка.
Мне нравится эта функция именно своей приземлённостью. Вместо попытки заставить человека каждый день открывать ещё одно приложение сервис встраивается туда, где он уже смотрит свои планы.
«Безопасный день» и граница честного прогноза
После календаря возник следующий вопрос: можно ли заранее выбрать спокойную дату для перелёта, важного мероприятия или другой нагрузки?
Для ближайших трёх дней есть детальный прогноз NOAA по трёхчасовым окнам. Для более длинного горизонта NOAA публикует 27-дневный обзор, основанный в том числе на повторяемости солнечной активности при вращении Солнца.
Я объединил эти данные в планировщике «Безопасный день». Ближайшие даты помечаются как более надёжные, дальние — как ориентир. Сервис выбирает дни с низким ожидаемым Kp, но не обещает, что через три недели всё произойдёт именно так.
Название функции специально бытовое, но внутри страницы есть прямое ограничение: «безопасный» означает только спокойный ожидаемый геомагнитный фон. Это не медицинская рекомендация и не гарантия хорошего самочувствия.
Особенно важно было не рисовать точный календарь на полгода. За пределами 27-дневного обзора можно говорить лишь об общих циклах солнечной активности, но не о конкретной буре в конкретный вторник. Иногда лучшая продуктовая функция — явно показать границу, после которой у тебя нет данных.
Что находится под капотом
Фронтенд сделан на Next.js 16 и React, данные хранятся в PostgreSQL. Python-пайплайн раз в 15 минут забирает у NOAA:
фактический планетарный Kp;
трёхдневный прогноз;
27-дневный обзор.
Записи сохраняются через upsert, поэтому свежий прогноз заменяет старое значение для того же временного окна. Затем детектор группирует последовательные интервалы с Kp от 5 в отдельные бури, определяет пик и класс по шкале G1–G5.
Исторические данные дополняются из GFZ Potsdam. На сайте есть архивы по годам, месяцам и дням, страницы отдельных бурь и регионов. Карта построена на Leaflet. Погодные данные приходят из Open-Meteo. Короткие пояснения генерируются через DeepSeek, но основные значения, статусы и пороги рассчитываются детерминированно.
Фронтенд и PostgreSQL развернуты на Railway, там же по расписанию работает поллер. Сам сайт сделан как PWA: его можно добавить на главный экран, но отдельное мобильное приложение для первой версии я не делал.
Главный технический принцип проекта — не смешивать сбор данных, интерпретацию и доставку. Если NOAA недоступен, это одна проблема. Если детектор неверно сгруппировал окна — другая. Если не ушёл push — третья. Разделение этих этапов экономит больше времени, чем любая «идеальная» архитектура на старте.
Что я переделывал по ходу
Проект не двигался по заранее написанному плану. Большинство полезных решений появилось после того, как первая версия показала свои ограничения.
Сначала главная была почти полностью про текущий Kp и ближайшую бурю. Затем я добавил самочувствие и понял, что этот блок должен находиться выше архива и вторичных ссылок.
Сначала интерфейс был светлым и похожим на обычный погодный сервис. Потом я несколько раз менял палитру и в итоге пришёл к тёмной теме с солнечным золотом и цветами полярного сияния. Это не влияет на точность прогноза, но влияет на характер продукта: он перестал выглядеть как случайная таблица из государственного сайта.
Сначала пуш должен был сообщать только о факте начавшейся бури. Потом стало понятно, что пользователю важно подготовиться заранее, и появился отдельный прогнозный пуш. При этом пришлось развести срочность, дедупликацию и статусы.
Сначала история самочувствия была просто полосой отметок. Затем добавились симптомы, личное сравнение спокойных и напряжённых дней и городской агрегат.
Иными словами, код первого MVP не оказался главным активом. Главным активом стала последовательность продуктовых вопросов, которые он позволил задать.
Где я не хочу притворяться медицинским сервисом
Связь геомагнитной активности с самочувствием изучается, но вокруг темы много противоречивых публикаций, слабых обобщений и откровенного кликбейта.
Гелиошторм не диагностирует заболевания, не рекомендует менять лечение и не обещает предсказать головную боль. Индекс самочувствия — ориентир, а пользовательские отметки — способ наблюдать за собой, а не доказательство причинной связи.
Первую версию формулы я пересмотрел ещё до накопления заметной пользовательской истории: убрал фазу Луны, ослабил влияние обычных температурных колебаний и привязал Kp к порогу конкретного города. В дальнейшем полезность каждого оставшегося компонента нужно проверять на накопленных анонимных отметках. Если фактор не улучшает объяснение пользовательских данных, его логичнее убрать, а не защищать только потому, что он красиво смотрится в интерфейсе.
Для меня это важная граница. В теме, где человек может тревожиться за здоровье, лучше недообещать, чем сделать убедительный, но ложный вывод.
Что дальше
Ближайшее направление — не добавлять ещё десять графиков, а сделать личные наблюдения полезнее.
Я хочу:
синхронизировать историю между устройствами через лёгкий вход;
добавить уведомления о резких перепадах давления;
импортировать сон и другие показатели из трекеров, если это можно сделать без сложного онбординга;
улучшить личные сравнения, когда накопится достаточно данных;
понять, какие факторы действительно связаны с пользовательскими отметками, а какие только создают шум;
развивать городской «пульс», не скрывая размер выборки.
Отдельная задача — удержать баланс между понятностью и точностью. Большинству пользователей не нужна лекция по гелиофизике на первом экране. Но за каждой простой фразой должна оставаться возможность открыть источник, увидеть исходный Kp и понять, где наблюдение, а где прогноз.
Что я вынес из этой разработки
Я начинал с идеи «сделать хороший сайт про магнитные бури». Это была слишком широкая и одновременно слишком поверхностная формулировка.
Рабочая версия идеи звучит иначе: помочь человеку сопоставить внешние условия со своим состоянием и заранее предупредить о заметных изменениях, не выдавая предположение за медицинский факт.
Сам по себе доступ к NOAA ничего не решает. Эти данные бесплатны и доступны всем. Ценность появляется в продуктовых деталях:
отделить прогноз от подтверждённого события;
не присылать лишний пуш;
учесть город;
объяснить число нормальным языком;
встроить прогноз в календарь;
накопить личную историю;
честно показать предел точности.
Сейчас Гелиошторм остаётся ранним проектом. В нём уже работает полный контур от получения данных до персональной сводки и уведомлений, но главная гипотеза ещё проверяется: нужен ли людям не просто прогноз магнитных бурь, а дневник связи между внешними факторами и собственным самочувствием.
Посмотреть текущую версию можно здесь: https://heliostorm.ru.
Особенно интересна критика трёх вещей: насколько понятен индекс самочувствия, стали бы вы подписываться на такой календарь и готовы ли отмечать своё состояние несколько дней подряд ради личной статистики.

