3 мин чтения#meta#infrastructure#engineering

Запустил блог за один вечер

Год веду @techaroundsports. Часть вещей живёт дольше одного поста — для этого и собрал полку.

Сегодня вечером поднял daniel.csylabs.com. С нуля до боевого контура.

Что внутри: → 21 заметка на старте — переложил архив канала в MDX → Русский и английский, переключатель справа сверху, парные переводы связаны полем translationOf в заголовке файла → Тёмная тема, иконка-луна в меню, localStorage помнит выбор → Кликабельные теги — на каждый отдельная страница → RSS, sitemap, hreflang — без CMS, без базы данных, просто MDX в git → Вёрстка под чтение: IBM Plex Sans 18 px, Unbounded Black для заголовков, колонка не шире 48 rem

Стек: → Next.js 16.2 + React 19.2 + Tailwind v4 + MDX → В монорепозитории csylabs-platform, пакет apps/daniel-blog, порт 3020 → Caddy на входе, Docker Compose сбоку, GitHub Actions разворачивает на каждый пуш в main → Своя Umami, без куков, смотрю только откуда приходят люди

Что сломалось (и зачем это интересно):

Docker Hub не достаётся из Москвы. node:20-slim упал три раза подряд — таймаут на TLS-рукопожатии. Лимит запросов оказался ложным диагнозом. Настоящая причина — геоблокировка IP-диапазонов Servers.ru. Починилось одним файлом на хосте:

/etc/docker/daemon.json:
{"registry-mirrors": ["https://mirror.gcr.io"]}

Google держит анонимный зеркальный кэш library/*. С российских серверов пробивается надёжно. systemctl restart docker — и все docker pull идут через Google, падая обратно на Docker Hub только при промахе мимо кэша.

MDX не любит <url> автоссылки. Парсер видит < и ждёт JSX-компонент. Ошибка: «Unexpected character / before local name». Решение: писать не <https://github.com/x>, а явную ссылку [github.com/x](https://github.com/x). Прошёлся скриптом по 21 файлу, заменил три вхождения.

Tailwind Typography выиграл гонку специфичности. Привязал свои цвета через .prose-blog { --tw-prose-body: var(--fg) }, но тело постов упорно рендерилось серым. Причина: плагин кладёт свой .prose { --tw-prose-body: #364153 } в @layer utilities, а мой блок жил в @layer components — каскад играл не в мою пользу. Починилось усилением селектора до .prose.prose-blog (специфичность 0,2,0 против 0,1,0 у плагина).

Тёмная тема не слышала переключатель. dark: в Tailwind v4 по умолчанию слушает @media (prefers-color-scheme: dark), а не атрибут [data-theme="dark"], который ставит моя кнопка. Если у человека системная светлая — он мог жать на луну, и ничего не происходило. Одна строка в globals.css: @custom-variant dark (&:where([data-theme="dark"] *)) — и dark: слушает атрибут.

План: → На неделе: ловить косяки в разных браузерах, сделать превью для соцсетей → Май: дописать разбор про iPhone и SRT (задержка меньше 3 секунд по сотовой) → 22 мая — Непал, первое платное мобильное производство. Основной пост придёт оттуда

Полка открыта. Дальше — по мере поступления.

Читать по теме