Как сделать блог, если ты s&box разработчик
Первым постом для блога показалось уместным написать про опыт создания этого самого блога. Как максимально просто и эффективно обзавестись собственным сайтом, если ты уже умеешь разрабатывать под s&box? Давайте узнаем.

Как сделать сайт
Итак, если вы до этого имели хотя бы какой-то опыт программирования, то в общих чертах представляете, как оно должно быть. Помимо скучных вещей, таких как покупка домена и настройка DNS, где-то должен быть сервер, который будет показывать браузеру странички вашего сайта:
- если это современное SPA, то HTML-разметка генерируется на лету в браузере или на сервере;
- если это что-то попроще, сервер генерирует HTML-файл по запросу;
- если совсем-совсем попроще, то на сервере просто лежит HTML-файлик, который сервер возвращает по запрошенному адресу.
SPA нам скорее не нужен — никаких продвинутых взаимодействий со стороны пользователя в блоге не ожидается. Отойдя на шаг назад, мы попадём к PHP-стилю, где бэкенд просто генерирует HTML и отправляет его в браузер. Но тут всё ещё придётся писать бэкенд, поддерживать его, заботиться о безопасности. К тому же, для бэкенда нужен сервер, а за него нужно платить. Догадываетесь, к чему я клоню?
Действительно, самый простой способ избавиться от головной боли с бэкендом — это избавиться от бэкенда и просто отправлять пользователям заранее сделанные HTML. Статические сайты полностью убирают всю головную боль, описанную выше. Для меня стало некоторым озарением тот факт, что для статических сайтов не надо писать разметку руками, как в эпоху Web 1.0, а всё так же можно использовать современные инструменты.
Static Site Generation
Да, нам ничто не мешает использовать современные фреймворки, но при этом получать все преимущества статических сайтов. Впервые я о такой возможности узнал у Svelte, но подобные режимы работы и библиотеки для них есть во многих фреймворках. Суть простая:
- Пишем сайт так, будто это обычное серверное приложение, но без интерактива со стороны пользователя.
- Фреймворк автоматически генерирует набор HTML-файлов с заданной маршрутизацией.
- Нам остаётся только взять полученные артефакты и отправить их на сервер.
И тут самое время вернуться к началу — не просто же так я упоминал s&box. А поворот в том, что SSG можно делать с помощью Blazor, то есть при помощи того же самого языка разметки Razor, что и в игре. И, наконец, без ограничений по стилям. Хоть и с понятными ограничениями по интерактиву — готовьтесь при любой необходимости использовать JavaScript.
Уже работавшие с Blazor знают, что по умолчанию поддержки SSG там нет, только SPA-опции в виде Blazor Server и Blazor WASM, а также PHP-подобный вариант в виде Blazor Static SSR.
Так вот, где инструмент не может — сообщество поможет. Если поискать в интернете фреймворк для SSG на основе Blazor, то можно найти Blazor Static. Тогда как благодаря Blazor любой, кто знаком с C#, легко может попробовать веб-программирование, то при помощи Blazor Static с той же простотой можно сделать статически генерируемый сайт, за что разработчикам большое уважение.
Делаем сайт
Итак, Blazor Static. В своей основе это генератор статических сайтов, причём со вполне конкретным назначением: быть основой для блогов. Основой дело не ограничивается, ведь есть полноценный шаблон проекта в виде BlazorStatic Minimal Blog, в котором всё уже есть из коробки. На данный момент это:
- создание постов для блога из Markdown-файлов;
- теги и поиск по ним;
- подключённый Tailwind;
- адаптивная вёрстка;
- минимум для SEO в виде автоматической генерации sitemap.xml.
Мне этого почти хватило — если осмотреться по сайту, можно обнаружить пару вещей, которых в шаблоне нет: выбор языка и отличающийся вид блога. К счастью, движок достаточно гибкий, чтобы реализовать их без больших проблем. Ну и страничка с играми — её, очевидно, пришлось делать с нуля.
На бумаге есть также возможность отладки в интерактивном режиме с Hot Reload, но меня смутила разница в поведении между статической и отладочной версией, так что я впервые в жизни написал свои собственные мини-скрипты запуска для C#, включающие генерацию файлов и запуск dotnet serve. Видимо, Java повлияла.
Игры
Тут от судьбы не убежишь: если хочется что-то более красивое, чем страничка на основе Markdown-файла, придётся верстать её самому. Казалось бы, имея опыт проектирования UI в s&box, не составит труда накидать небольшую .razor-страничку, но нам надо учесть, что у нас в планах локализация. Учитывая небогатый набор игр, конечно, можно было бы просто скопировать страницу два раза, но я слишком уважаю DRY, чтобы это делать. Поэтому тут был придуман небольшой велосипед: генерация страницы на основе TOML.
Этот формат файлов как-то очень неожиданно вошёл в мою жизнь, проникнув даже на мою работу. И, что иронично, как раз по вине s&box. Для Terry Dev Tycoon мне нужно было много текстов разных форматов: задачи для трекера и события. Мне кажется уместным небольшой отступление на тему того, как выбирался вариант их хранения:
- Вариант хранить ресурсы прямо в коде мы не рассматриваем.
- Традиционные для C# файлы ресурсов отпадают, их использовать в s&box нельзя.
- JSON, казалось бы, лёгкий выбор, но лично мне он не нравится плохо читаемым синтаксисом. Кроме того, в нём нет поддержки многострочного текста, что для меня критично, ведь в событиях нужны абзацы.
- YAML — следующий лёгкий выбор, но не для игровых ресурсов. Да, у него более приятный для работы синтаксис, и в YAML есть поддержка многострочного текста. Но древовидная структура мне просто не нужна, а синтаксис печально известен своей комплексностью с точки зрения парсинга.
- TOML же — идеальный вариант. Простой и понятный синтаксис, отсутствие ненужной вложенности, многострочные литералы, с помощью Tommy читать файлы можно, добавив один файл в проект.
Это что касается Terry Dev Tycoon, но по забавному совпадению для сайта сработала та же логика. Разве что можно использовать Tomlyn через NuGet и не заморачиваться. В TOML-файле я указываю всю нужную информацию: название, описание в Markdown, ссылки и путь до скриншотов. Далее повторяем то же для другого языка, настраиваем сервис чтения файла в зависимости от языка, верстаем страничку и любуемся на результат.
Кстати, выше я упоминал, что в Blazor придётся использовать JavaScript, и это как раз тот случай. Сейчас скриншоты там перелистываются автоматически, чего не сделать без воздействия на разметку страницы. В Blazor Server или Blazor WASM это можно было бы сделать через C#, но на статическом сайте помогут только традиционные методы.
Страница блога
Тут пришлось сидеть и разбираться в том, как работает Blazor Static. Проблема, которая у меня была: я хотел изменить, как выглядит страница блога. Если что, по умолчанию выглядит она так:
А итоговый результат, на момент написания этой статьи, так:
Не учитывая вёрстку, сущностных отличия два:
- пост снабжён титульной картинкой;
- аннотация берётся прямо из статьи, а не задаётся отдельно.
Сделать это оказалось не настолько просто, ведь напрямую нигде этот процесс не описан. Так что отступлю от формата и кратко опишу процесс тут.
IFrontMatter
Это самый низ иерархии классов, которая нам нужна. Представляет из себя структуру для хранения данных из Frontmatter — блока метаданных в формате YAML в начале Markdown-файла. Для этой статьи он сейчас выглядит так:
title: Как сделать блог, если ты s&box разработчик
published: 2026-03-14
tags: [misc]
authors: [Right]
Именно информация отсюда отображается на странице блога и в метаданных (автор, теги и пр.) поста. По умолчанию интерфейс реализует BlogFrontMatter, но, если мы хотим свои метаданные, то и наследник нам понадобится свой. Надо только ещё не забыть унаследовать IFrontMatterWithTags для поддержки тегов. И да, как можно заметить в коде выше, картинки и аннотации там нет. Логично, ведь я хотел брать их напрямую из текста, так что нам надо идти далее.
Post
Далее идёт класс напрямую из движка Blazor Static, поменять который напрямую нельзя, но и отказаться тоже. Именно через Post<IFrontMatter> в Frontmatter попадают метаданные, а в самом Post содержится HTML нашего поста.
В движок из шаблона мы влезть не можем, но нам ничего не мешает сделать обёртку над ним, чтобы использовать её на странице блога. Так я и поступил — на каждый Post я создаю PostWrapper. Там, при помощи простого, но сердитого парсинга HTML через AngleSharp я вытаскиваю картинку и абзац до неё, превращая их в титульную картинку и аннотацию соответственно.
Такой схемы мне сполна хватило для своих целей, а позже она ещё и спокойно поддалась локализации.
Локализация
Когда я думал об этой задаче, она мне представлялась в целом понятной, но муторной: нужно пробежаться по всем страницам и оставить язык как параметр, сделать свой пайплайн загрузки контента в блог, вынести текст на страницах в ресурсы и доставать их в зависимости от языка. Дополнительно нужно было реализовать то же для чтения TOML-файлов.
В общем, задача довольно многогранная, так что я сильно удивился, когда Composer 1.6 от Cursor с ней уверенно справился. Да, с постоянным надзором и напоминанием, что это статический сайт, а значит, штуки типа перенаправлений через NavigationManager сделать не выйдет. И всё же справился. Что особенно удивило — агент сам разобрался, как работает пайплайн загрузки постов, и доработал мою обёртку поверх них.
Да, возможно, этот раздел не очень впечатляет: вроде сложная и интересная задача, а решена через ИИ. Или это просто моё ощущение. Возможно, это повод подумать, что вообще есть «сложно» и «просто» в нашей работе.
Дизайн
Решить, каким хочешь видеть сайт, довольно сложно, особенно когда вёрстка — это не твоя специализация. Но если всё же приходится делать вещи своими руками, я обычно тяготею к приятному глазу минимализму. Думаю, по непритязательному UI в Terry Dev Tycoon и Sboku Arena это заметно.
Но также мне нравятся современные интерфейсы, а также как их обычно реализовывают нейросети. И, по забавному стечению обстоятельств, ИИ-дизайн и стал для меня вдохновением. Если конкретнее, то им послужила заглушка, которая тут висела во время разработки сайта:
К счастью, с нуля делать ничего не надо. В шаблоне Minimal Blog всё уместно расположено, так что глобальные перестановки не нужны. Достаточно поменять используемые стили на страницах, добавив по минимуму CSS от себя. Причём благодаря Tailwind делать это и правда придётся по минимуму, хотя в его использовании ещё придётся разобраться. Из хорошего — с этим отлично справляется Cursor. Из плохого — ИИ разоряет разработчиков Tailwind. Мораль этой истории додумайте сами.
Хостинг
Я в начале упоминал, что без бэкенда мы экономим не только на головной боли, но и на хостинге. И, действительно, такая возможность есть, хотя у разных провайдеров разные условия. Я сам перепробовал следующих провайдеров:
- Cloudflare Workers: не самый понятный интерфейс, сбивающая с толку документация, но зато в той же панели управления можно очень удобно управлять DNS. Для этого использую Cloudflare до сих пор.
- Netlify, Vercel: очень удобный интерфейс, разворачивать прямо из GitHub — одно удовольствие, на Netlify также очень удобно это делать вручную. В целом, любой из этих двух — вполне логичный первый выбор.
- GitHub Pages: популярное среди разработчиков, проверенное решение, ожидаемо отличная интеграция с GitHub Workflows. Хотя проблемы тоже были — получилось развернуть сайт только со второй попытки. Документация на вопросы ответы не давала. Ещё из минусов: нет поддержки перенаправлений, необходимо раскрывать исходники на бесплатном тарифе.
Пробовал я их в том же порядке, что они тут перечислены. Почему я остановился на GitHub Pages?
Мимо меня как-то прошла вся эта шумиха с блокировками, но люди в теме уже знают — Cloudflare подвергся официальным блокировкам ещё полгода назад, из-за чего из России недоступен в принципе. С Netlify и Vercel ситуация более неоднозначная: развёрнутый сайт открывается через раз, но переходить по нему не получается совсем. Официальных блокировок вроде бы не было, так что в чём конкретно дело — непонятно. В любом случае, пока GitHub Pages доступен, так что я перешёл на него. В РФ я не нашёл бесплатных хостеров статических сайтов, так что в случае ухудшения ситуации всё же придётся покупать хостинг.
Послесловие
Ну и немного цифр. Если судить по датам коммитов, то на разработку сайта у меня ушла ровно неделя работы по вечерам. Плюс ещё неделя на перебор хостингов. Кажется, сравнительно шустро.
Также разработка вряд ли на этом остановится: только сейчас заметил, что в блоге нет пагинации, было бы неплохо добавить RSS-ленту, может, ещё поменяю маршрутизацию. Но пока я результатом вполне доволен.
Вот такой получилась история про разработку этого сайта. Запущен он был, кстати, как раз месяц назад. Следующим на очереди, скорее всего, будет пост-мортем по разработке Terry Dev Tycoon, который я уже обещал. За всеми анонсами можно следить в Discord.