Импортозамещение своего сайта
О чем название статьи, о том и текст
Введение
Рождение идеи

Пилим с Йунцом проект, и мне в голову приходит мысль, как спустить весь свой отпуск в наименее эффективной форме. И вот идея - переделать свой сайт. В N-ый раз
Что хочу
- уйти на коробочный
server-side - баланс и в
DXи вUX - уйти от сторонних платформ
- везде свои
WYSWYGредакторы и постинг где-либо это всегда болезненный процесс - цензура
- по отношению к другим пользователям
- по отношению к контенту
- везде свои

Что импортозамещаем
До старта работ уже случились
- проблемы со масштабированием и поддержкой старой конфигурации
client-side custom: любое «добавить» = разработкаVercel: классная платформа, но по деньгам не сходитсяSupabase(Postgreвнутри): инструмент отличный, но дорогой; после 2022-го платить стало отдельным квестомGoogle Analyticsстал избыточно сложным- надоел дизайн 2018-го.

Мой знаменатель — это два классических ограничителя: время и деньги
И сразу понятно, что менять:
- систему мониторинга
- коробку для блоггинга
- хостинг
- дизайн
Roadmap
План я расписал до деталей — элегантно и чётко. И он... пошёл курить уже к концу первого дня
Основная часть
Мониторинг
Что тут сказать, за последние 10 лет перепробовал много
- и
Google Analytics - и
Yandex Metrika - и
Firebase Crashlytics - и ряд
self-hostкоробок
Выбор инструмента
Краткие обзор чего касался
| Система | Плюсы | Минусы | Цена | Где крутится |
|---|---|---|---|---|
| Google Analytics (GA4) | + мощная экосистема (BigQuery, Ads) + куча готовых отчётов + интеграции со всем подряд | – сложный интерфейс, нужен отдельный курс – блокируется AdBlock – после 2022 у RU-проектов проблемы с доступом | бесплатно (базовый) | облако Google (США) |
| Yandex Metrika | + простая настройка + карта кликов и вебвизор + интеграция с Yandex Ads/Direct + не режется AdBlock | – отчёты проще, чем в GA – фокус на RU, для глобала бесполезно | бесплатно | облако Яндекса (РФ) |
| Umami | + open-source, без трекеров + минимализм и быстрый UI + self-host или любой сервер | – мало “из коробки” (например, нет вебвизора) – нужен свой хостинг | бесплатно (только хостинг) | где сам поставишь |
| Matomo (бывш. Piwik) | + open-source альтернатива GA + отчёты почти как в GA + GDPR-friendly | – интерфейс тяжелее, чем у Umami – требует больше ресурсов сервера | бесплатно (self-host) есть платный Cloud | self-host или Matomo Cloud (ЕС) |
| Plausible Analytics | + минимализм + privacy-first + очень лёгкий код (не режется блокировщиками) | – платный SaaS – нет вебвизора/тепловых карт | от $9/мес | EU облако (Германия) |
У меня в голове эта таблица визуализируется следующим образом
Взял Umami потому, что мне нужен не набор для приготовления суши, а шаверма за углом: быстро и без рекламы
- Использовать: если нужен лёгкий self-hosted мониторинг без лишней рекламы
- Не использовать: если проекту критичны сложные отчёты, реклама, воронки или автоматическая аналитика
Применение
Для начала тест, решил обкатать это решение на своём браузерном расширении (Github Gloc - считает приблизительное количество строк в исходниках на GitHub). Несколько месяцев собирал логи и смотрел на то как растет потребление по базе

Скрин с Umami сервиса по части расширения
Как пользователю результатов, мне нравится
- простота использования
- разворачивание всех логов в нужные мне отчеты и графики

Как разработчику мне нравится
- быстрое и понятное разворачивание
- нормализация данных. Всего 10 таблиц (нет бесконечного прироста сущностей)
- скос нагрузки только на 2-х основных таблицах - то есть понятно что мигрировать и что партицировать (я бы сделал по дате отправки лога
created_at)
Кстати, в какой-то момент я хотел оптимизировать по типу событий (у меня это event_name) пока я не запустил сл скрипт
-- топ событий за последние 120 дней
SELECT event_name,
COUNT(*) AS events,
MIN(created_at) AS first_seen,
MAX(created_at) AS last_seen
FROM website_event
WHERE created_at >= now() - interval '120 days'
GROUP BY event_name
ORDER BY events DESC;

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

В этом плане Supabase просто прекрасен, лучшая оболочка для работы с БД которую я встречал
- и работа с данными
- и анализ нагрузки
- и анализ объёма
- и обширная рекомендательная система. Но даже без неё информации столько много и она так детализирована, что ты сразу понимаешь куда копать и что делать (в примере выше вообще нашел
FEбаг копаяБД)
Одновременно с миграцией у меня стало заканчиваться место в Supabase а лишаться 3-х косарей я не хотел и логи мне нужны - люблю собирать куки, а потом читать
В общем моя миграция началась именно с миграции мониторинга. Пересобрал расширение и запушил это в
Edge storeChrome store
Как только пошли логи я успокоился, что на проде не повалились багтрейсы. Мои эксперименты часто оборачиваются бедой для пользователей. Взять например мою попытку запартнёриться с одним сервисов который оказался мошенническим

В тот день у сотен людей сгорели пердаки, я в какой-то момент стал получать
- пачки Issue на
Github - гневные письма
- сообщения в отзывах в
Chrome storeи прочих магазах расширений (Opera,Mozilla)
Под капотом использую Umami в таком режиме. Кастомные события не кидаю
scripts: isProd ? [
{
src: "https://MY_INSTANCE/script.js",
defer: true,
"data-website-id": "LONG_HASH",
},
] : [],
Коннект BE и DB случился только по этому методу
postgresql://USERNAME:PASSNAME:PORT/default_db?sslmode=verify-full
Занимательный факт. Как только подключил логирование сразу отписалось более 10% людей. Отписки продолжаются до сих пор. Пользаки параноят за куки, а ведь это лечится простой наклейкой на вебкамеру

Сперва, не переживал. Думаю, с 10% отписок можно жить. К текущему моменту цифра составила минус 33%. Кстати если суммарно посчитать то за 2 года лишился 50%. Есть план по возврату аудитори. Но, думаю эффективнее будет вложиться в крипту

Коробка для блоггинга
Выбор инструмента
Пробовал не так много, но каждый из экспериментов был чем-то отличным от предыдущего
| Платформа | Плюсы | Минусы | Где юзал |
|---|---|---|---|
| WordPress | + куча плагинов + легко найти инструкции | – админка в стиле 2000-х – бесконечные апдейты и дырки в безопасности – скорость оставляет желать лучшего | для пары корпоративных сайтов |
| Joomla | + гибкость + локальное комьюнити (когда-то) | – UX на уровне “разберись сам” – ощущение олдскула | учебные проекты лет 10 назад |
| Custom (Next.js/React) | + полный контроль + кастомный дизайн/логика | – время и деньги на поддержку – легко скатиться в велосипед | мой старый блог на Vercel + Supabase |
| Docusaurus | + простой деплой + работаешь с md/mdx + отличная документация + комьюнити от Meta | – не блоговая CMS “из коробки” – сборка может быть тяжёлой – местами костыль в кастомизации | дока на работе + теперь блог |
| Diplodoc | + российский разработчик, open-source, разработано не педофилами | – насвай от Yandex который даже в имени косплеит Docusaurus. Чистейший аналог японской системы по увеличению членов | умозрительно |
Выбрал Docusaurus потому, что
| Характеристика | Плюсы | Минусы |
|---|---|---|
| Лицензия / модель | Open Source (MIT) Поддерживается Meta (Facebook) | Зависимость от экосистемы React Roadmap под контролем Meta |
| Простота | Работа с обычными .md и .mdx файлами Лёгкая структура документации Готовые плагины для блога, i18n, поиска | Сборка может быть тяжёлой (особенно при большом проекте) Иногда требует костылей для кастомизации |
| Функциональность | Автоматическая генерация документации Поддержка версионирования Много тем и плагинов Отличный DX для разработчиков | Нет “админки” из коробки (не для ноукодеров) Не полноценная CMS |
| Развёртывание | Легко хостить где угодно (Vercel, Netlify, Timeweb, GitHub Pages, Docker) Простая CI/CD интеграция | При больших проектах сборка может упираться в ресурсы (RAM/CPU) |
| Интеграция | Хорошо встраивается с React-компонентами Поддерживает плагины для аналитики, поиска, темизации | Сложнее встраивать сторонние виджеты, чем в WordPress/Notion |
| Стоимость | 0 ₽ (только за хостинг) | При использовании платных плагинов или CDN расходы растут |
- Использовать: если нужен блог/дока для разработчиков, любишь работать с Markdown и React
- Не использовать: если хочется drag&drop редактора или бизнес-CMS для маркетологов
Применение
- добавил проект из Github
- прописал скрипт сборку и всё
Вцелом с этим сервисом (Docusaurus) у меня большой опыт, на нескольких проектах всю документацию поднимал именно на нём, так что тут экспериментов и сложноестей не было. Простая работа с md файлами
Инфра/хостер
Выбор инструмента
В первую очередь хотелось
- не иметь проблем с оплатой
- хороший
UX(неC panel) - ну и по бабкам, чтобы не было накладно
| Платформа | Плюсы | Минусы | Цена (базовая) | Где крутится |
|---|---|---|---|---|
| Yandex Cloud | + дата-центры в РФ (нет проблем с оплатой) + богатый набор сервисов (Compute, Object Storage, DB, AI) + нормальный UX, API, Terraform | – иногда тормозит UI – ценник ближе к AWS, чем к “бюджетному” – документация местами тяжеловата | от ~500–700 ₽/мес за VM | РФ |
| Bluehost | + один из старейших хостеров + удобная интеграция с WordPress + 24/7 саппорт | – заточен под WP, слаб для кастомных стэков – cPanel (олдскул, неудобно) – оплата в $ (после 2022 боль) | от $5/мес | США |
| Vercel | + шикарный DX для фронтов + автоматический CI/CD + serverless функции + бесплатный тариф (ограниченный) | – цены быстро растут при нагрузке – Postgre / DB надо выносить отдельно – оплата в $ (сложности для RU) | free → от $20/мес | США / глобально |
| Timeweb Cloud | + российский хостинг + дешёвые тарифы (1–2 GB RAM VM за копейки) + нормальный UI (не cPanel) + можно крутить Docker | – нет богатства сервисов как у Yandex Cloud – саппорт/стабильность похуже чем у hyperscale – не для highload проектов | от 350–400 ₽/мес за VM | РФ |
Vercel— какTesla: удобно, но дорого и в долларахYandex Cloud— какСбер: много сервисов, иногда тяжело разобраться. Это, определённо, сегмент крупного бизнесаBluehost— привет из 2000-х. Хотя был у меня сервис наWordpressсDAUв 40к и ему хоть бы хуй - нагрузки держит как не в себя- А
Timeweb Cloud— ларёк у дома: дёшево, понятно и рядом. Не понятно только когда уходит вpendingпо ряду операций
💡 Лайфхаки по экономии на облаках которые мне известны

| Платформа | Лайфхак | Экономия |
|---|---|---|
| Yandex Cloud | Бери минимальные VM и выноси статику в Object Storage (он дешёвый, а трафик CDN покрывает многое). Используй preemptible VM (временные, в 3 раза дешевле). | 30–70% от тарифа |
| Bluehost | Оплачивай не помесячно, а на 1–3 года вперёд — у них жёсткий дисконт. Лови купоны/акции (часто 60–70% скидка). | до 50% |
| Vercel | Оптимизируй билды: реже деплой, меньше функций. Вынеси тяжёлые API на сторонний сервер (иначе платить за серверлес как за космос). | 20–40% |
| Timeweb Cloud | Собирать проект на VM с 2 GB RAM (чтобы прошла сборка), а потом переключать на 1 GB (runtime живёт). Для пет-проектов хватит тарифов за 350 ₽. | 50% |
Визуализирую так
Timeweb cloud
Timeweb Cloud — для пет-проектов и блогов — идеально. Для Enterprise-нагрузки — лучше смотреть на Яндекс, или AWS
Применение инструмента
Плюсы
Я рассмотрю их как с точки зрения BE так и FE
Так выглядит главная страница FE сервиса

особенно нравитсято, что я могу на одной странице увидеть основные показатели здоровья по сервису. Особенно отклик по памяти в ответ на траффик

логи дэплоя находятся отдельно. Нигде такого не встречал, разве что в Vercel

тут же могу выбрать на какую версию приложения откатитсья. Откат, обычно, происходит моментально и незаметно для пользователя - очень похоже на подмену пода в Kubernetes

Удобная работа с логами. Ничего лишнего

Тут-же консоль

Немаловажная часть работы для тех кто работает с хостерами - это домены. Они и тут сделали всё удобно

и особенно круты настройки домена - добавление записей. Кто сталкивался с линковкой своих сервисов к доменам меня поймёт. На Vercel этот участок для меня был всегда самым противным. А скорость обновления была непредсказуемой. Тут я обновил настройки DNS, переключился в соседний таб с абсолютно другим сервисом и всё подтянулось

Теперь обзор всех моих сервисов и доменов. Всё чётко и понятно

Также есть возможность обзора в режиме мэш

По итогу - потрясающий UX и его начинка логикой и данными. Интерфейс похож на рабочую панель звездолёта где находится всё самое нужное. Я не задумываюсь о UI когда с ним работаю. Чувствуется многолетний опыт работы команды
Теперь работа с базой. Моя любимая главная панель и здесь всё самое важное

и нагрузки по конектам и транзакциям

И морда для работы с базой. Ну, это точно не Supabase. Это Adminer

вот структура таблички

а вот сами данные

и напоследок - выполнение SQL запросов. Никаких автокомплитов - только суть как она есть. В Supabase intellisence на каждый чих

Минусы

Не без них. Сайт написал пару месяцев назад, но написать статью руки дошли только сейчас. И вот захожу в панель Timeweb а мой сервис Umami лежит. Перезапускаю и логи деплоя не появляются по несколько часов. Лечил каждый раз по разному
- на конфигурации в 1GB по RAM не проходил. В итоге отключил минификацию и взял план на 2GB и сборка прошла со свистом
- затем все сервисы пизданулись сохраняя по показателям стабильность и не присылая уведомлений
- конфигурацию поднял до 2GB
- второй этап повторился
- конфигурацию поднял до 4GB
Лайфхак
- можно разворачивать сервис на профиле в 2GB
- а потом переключать на 1GB. Runtime он держит
- в итоге экономия в 2 раза. Но делать так не стал. Лень

И в какой-то момент произошло еще вот что

То есть очевидно, что для бизнеса я бы порекомендовал не использовать этого хостера. Пока он не дотягивает до бесплатного плана Versel
Почему, а вот почему
- сервис лежал и я не получил уведомления
- аптайм непресказуемый
- не происходил сбор логов с другого приложения на сервис мониторинга который лежит здесь (то есть вся моя микроэкосистема умерла)
- само приложение ни логирование/мониторинг не работали. В панеле все было зеленым цветом

Дни без статистики (13 дней)
Дизайн
Палитра/концепт
Мне хотелось вложить на этот раз в работу некоторый символизм и дизайн-систему развивать от него. Спустя какое-то время у меня родилась мысль которую я быстро набросал во flyvi (кстати, неплохой аналог Canva)

Заглавная анимация
Создав концепт, я быстро его переложил в код. На самом деле не быстро. Столкнулся со следующими сложностями
- подогнать внешний круг под элементы для которых они предназначены
- выровнить татуху. Покрути код и сделай её вертикальной. Если получится, то с меня обед
import React from "react";
import { KasLogoProps } from "./KasLogo.types";
/**
* Логотип с прорезями на двух кругах:
* - напротив левого глаза (angleLeft)
* - напротив правого глаза (angleRight)
* - напротив тату на горле (angleNeck)
*
* @author Elvirov Kas
*/
export const KasLogo: React.FC<KasLogoProps> = ({
size,
strokeColor = "#E62323",
strokeWidth = 8,
step = 0.18,
innerRingRadius = 180,
angleLeft = 170,
angleRight = 25,
angleNeck = 277,
gapPct = 0.04, // ~6% окружности
}) => {
const d = (i: number) => `${(i * step).toFixed(3)}s`;
// helper: перевод угла в оффсет [0..1] для stroke-dashoffset (0° = 3 часа)
const toOffset = (deg: number) => ((deg % 360) + 360) % 360 / 360;
const gaps = [
{ id: "gLeft", offset: toOffset(angleLeft) },
{ id: "gRight", offset: toOffset(angleRight) },
{ id: "gNeck", offset: toOffset(angleNeck) },
];
return (
<div style={{ justifyItems: "center" }}>
<svg
width={size}
height={size}
viewBox="0 0 512 512"
role="img"
aria-label="Изоморфический логотип Каса Элвирова с прорезями"
style={{ overflow: "visible", display: "block" }}
>
<defs>
<linearGradient id="isoStroke" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stopColor={strokeColor} />
<stop offset="100%" stopColor={strokeColor} />
</linearGradient>
<filter id="isoEmboss" x="-100%" y="-100%" width="300%" height="300%">
<feConvolveMatrix
order="3"
kernelMatrix="-2 -1 0 -1 1 1 0 1 2"
divisor="1" bias="0" edgeMode="duplicate"
/>
<feComposite in2="SourceGraphic" operator="atop" />
</filter>
<style>{`
.isoLine {
fill: none;
stroke: url(#isoStroke);
stroke-width: ${strokeWidth}px;
stroke-linecap: round;
stroke-linejoin: round;
vector-effect: non-scaling-stroke;
stroke-dasharray: 100;
stroke-dashoffset: 100;
animation: draw 1s ease forwards;
}
@keyframes draw { to { stroke-dashoffset: 0; } }
`}</style>
{/* Маска для вырезов на внешнем кольце */}
<mask id="outerMask">
{/* <!-- белый фон = всё видно --> */}
<rect x="0" y="0" width="512" height="512" fill="white" />
{/* <!-- три "чёрных" коротких дуги = невидимые участки --> */}
{gaps.map((g, i) => (
<circle
key={i}
cx="256" cy="256" r="230"
fill="none"
stroke="black"
strokeWidth={strokeWidth * 1.6}
pathLength={1}
strokeDasharray={`${gapPct} ${1 - gapPct}`}
strokeDashoffset={g.offset}
/>
))}
</mask>
{/* Маска для вырезов на внутреннем кольце */}
<mask id="innerMask">
<rect x="0" y="0" width="512" height="512" fill="white" />
{gaps.map((g, i) => (
<circle
key={i}
cx="256" cy="256" r={innerRingRadius}
fill="none"
stroke="black"
strokeWidth={strokeWidth * 1.6}
pathLength={1}
strokeDasharray={`${gapPct} ${1 - gapPct}`}
strokeDashoffset={g.offset}
/>
))}
</mask>
</defs>
<g filter="url(#isoEmboss)">
{/* Внешний круг с прорезями */}
<circle
className="isoLine"
pathLength={100}
cx={256}
cy={256}
r={230}
style={{ animationDelay: d(0) }}
mask="url(#outerMask)"
/>
{/* Внутренний круг-ореол с прорезями */}
{/* <circle
className="isoLine"
pathLength={100}
cx={256}
cy={256}
r={innerRingRadius}
style={{ animationDelay: d(0.7) }}
mask="url(#innerMask)"
/> */}
{/* Контур головы (как было) */}
<path
className="isoLine"
pathLength={100}
d="M256,116c-70,0-112,50-112,130s42,130,112,130s112-50,112-130S326,116,256,116z"
style={{ animationDelay: d(1.4) }}
/>
{/* Шея */}
<path className="isoLine" pathLength={100} d="M192,356c0,30-12,46-28,58" style={{ animationDelay: d(2.0) }} />
<path className="isoLine" pathLength={100} d="M320,356c0,30,12,46,28,58" style={{ animationDelay: d(2.2) }} />
{/* Глаза */}
<line className="isoLine" pathLength={100} x1={200} y1={240} x2={240} y2={250} style={{ animationDelay: d(2.6) }} />
<line className="isoLine" pathLength={100} x1={272} y1={250} x2={312} y2={240} style={{ animationDelay: d(2.8) }} />
{/* Вертикальная тату. Должна быть, но не такая */}
<line className="isoLine" pathLength={100} x1={256} y1={400} x2={257} y2={450} style={{ animationDelay: d(3.0) }} />
</g>
</svg>
</div>
);
};
В результате и получилась данная работа

Перейди на главную, кликни на лого и не отводи мышку
Итого
Импортозамещение

Тут я воспользовался старым добрым паттерном
Взять чужое -> Положить в карман -> Сказать, что это наше
Список чужого
| Что | Как называется | Гражданство технологии |
|---|---|---|
| База данных для мониторинга | Postgre | АСАШАЙ (Беркли) |
| Скрипты для мониторинга | Next.js | АСАШАЙ (Vercel) |
| Коробка для мониторинга | Umami | АСАШАЙ (Umami software) |
| Коробка для блоггинга | Docusaurus | АСАШАЙ (Meta). Принадлежит компании Meta, признанной экстремистской и запрещённой на территории РФ |
| Скрипты на клиенте | React | АСАШАЙ (Meta). Принадлежит компании Meta, признанной экстремистской и запрещённой на территории РФ |
| Разметка на клиенте | MD | АСАШАЙ . Блогер Джон Грубер |
Архитектура
Слово громкое, но она тут есть
Риски
Timeweb как хостер - около 10 лет пользуюсь их услугами. Я помню какие были лимиты раньше и как все работало. Чуть MAU на Wordpress сайте скакнет и ты срзу уходишь в за пиковые значения. И потом тебе пишут мол "Ваша популярность не вписывается в текущий план". Сейчас это уже абсолютно другая компания которая одна из первых несет такие мощные и простые в использовании инструменты. Я им искренне желаю не останавливаться и преодолеть эту ИИ трансформацию
Деньги
| Статья расходов | Месячная цена | Годовая цена | Комментарий |
|---|---|---|---|
| Домен .com/.ru | ~200 ₽ | ~2400 ₽ | регистратор Webnames |
| Timeweb Cloud (2 GB RAM) | ~1500 ₽ | ~18000 ₽ | хватает для докухи + умами |
| База данных (Postgres) | включено | включено | в тарифе Timeweb |
| Umami (self-host) | 0 ₽ | 0 ₽ | open-source, только хостинг |
| Timeweb Cloud CI/CD | 0 ₽ | 0 ₽ | в тарифе Timeweb |
| Итого | ~1700 ₽ | ~20 400 ₽ | меньше, чем один ужин в Москве |
Немало конечно, но ничего - часть затрат я отобью вэбкамом
“Раньше только Supabase сожрал бы 25$, а теперь весь блог (DB для мониторинга для нескольких проектов, сервис мониторинга для нескльких проектов, сервис со статикой для блога и домен) живёт за 1500 рублей в месяц. Импортозамещение...”
Вынесенные уроки
Тратить отпуск на инженерную возьню — иногда самое лучшее вложение