Блог
3 мин чтения
Выходные данные: как сделан этот сайт
Эта страница — обычный файл на диске. Как и любая другая здесь. За сайтом нет ни процесса приложения, ни базы: ломаться в нём почти нечему и держать тёплым нечего.
Сборщик
sitegen — небольшой пакет на Python в том же репозитории. Он читает файлы разметки с TOML-заголовками из content/, структурные данные — резюме, список ресурсов — из data/, и складывает готовое дерево в public/. Из стороннего не используется ничего: настройки разбирает tomllib, а разметку — намеренно маленькое подмножество Markdown, написанное руками, а не подключённое зависимостью.
Последнее стоит защитить. Личному сайту нужны заголовки, списки, ссылки, выделение, код, цитаты и таблицы. Это закрытый набор, он укладывается в двести строк — и взамен сборка запускается везде, где есть Python 3.11, включая сам сервер, на котором не установлено ничего.
Прибор с бумагой
У оформления одно правило, и из него следует всё остальное: обвязка всегда темнее содержимого. Шапка, надзаголовки разделов, ось прокрутки и полоса состояния — это прибор: почти чёрный, моноширинный, янтарный. Всё, что действительно читают, лежит на светлом листе с янтарной кромкой, заряженном в эту рамку.
Правило же решает и вопрос об акцентах. Янтарь принадлежит обвязке, ультрамарин — документу, и местами они не меняются: два акцента, у каждого из которых своя область, остаются различимыми, а два блуждающих перестают что-либо значить. Кнопки — клавиши: тонкая рамка и вынос в два пиксела, который пропадает при нажатии. Разделы в навигации пронумерованы, потому что их шесть, порядок постоянный, и номер даёт глазу за что держаться в моноширинном ряду.
Тёмная тема сохраняет правило, а не материал: лист перестаёт быть бумагой и становится подсвеченным экраном — по-прежнему светлее обвязки вокруг. Различие «рамка и документ» держится, буквальная бумага — нет, а работало именно различие.
Портрет нарисован графитом, и палитра листа взята с него. С подложкой рисунок смешивается по «темнейшему»: бумага уходит в фон, остаются одни штрихи.
Два языка
Оба равноправны: /en/ и /ru/ собираются из зеркальных деревьев, каждая страница объявляет свою пару через hreflang, а корневой адрес разводит читателей по заголовку Accept-Language. Если перевода ещё нет, переключатель языка ведёт на перечень раздела, а не выбрасывает на главную.
В более раннем варианте подпись сайта была набрана сразу на двух языках: активный плотным начертанием, второй контуром. Это была самая интересная деталь страницы, и её пришлось убрать: на английской странице русская строка контуром читается как смешение языков, а не как приём.
Единственный скрипт
Здесь один файл JavaScript, около сотни строк, и он ничего не решает. Он докладывает положение: в каком разделе читатель и как далеко он ушёл, — и строит ось с засечками справа. Без него работает каждая страница: ось просто не появляется, а полоса состояния остаётся с тем, что отдал сервер. Поэтому ось строится в скрипте, а не в разметке: элементу, который без JavaScript ничего не значит, в HTML делать нечего.
Ось появляется начиная с трёх разделов. На статье с одним она была бы украшением, изображающим прибор.
Как отдаётся
Caddy отвечает на 443, отдаёт public/ файлами и получает сертификат Let's Encrypt без всякого cron. Политика безопасности разрешает скрипты только с этого адреса и ничего кроме — сторонних узлов нет никаких. Агрегатор новостей работает на той же машине, теперь по адресу /news.
Шрифты
Три начертания, все лежат рядом: Unbounded для заголовков, Golos Text для текста, JetBrains Mono для меток и данных. Именно рядом, а не ссылкой: половина сайта по-русски, а fonts.gstatic.com из России отвечает не всегда. Страница вообще не делает запросов на сторонние домены.