Запустил блог за один вечер
Год веду @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 мая — Непал, первое платное мобильное производство. Основной пост придёт оттуда
Полка открыта. Дальше — по мере поступления.