← Главная

3 просм. 5 мин чтения

Ни строчки кода своими руками или как был написан MiniBlog

Konstantin Anisimoff

Все началось с задумки сделать минималистичную площадку в духе Telegra.ph, где можно писать статьи. Было сделано несколько подходов к воплощению этого, но проект так и не был доведен до конца. В этот раз проект был доведен до конца!

Сопутствующей задачей проекта было провести эксперимент с вайб-кодингом. Я сознательно отказался от написания кода руками, а только формулировал идеи, требования и замечания, проверял результат и направлял разработку армии агентов. Получился своеобразный тест: можно ли собрать работоспособное приложение и что из этого выйдет.

В начале...

После первого запуска пользователь попадает в мастер настройки /setup, где создает учётную запись владельца, вводит название сайта, девиз, описание, ссылки на социальные сети.

На главной странице находится лента опубликованных материалов с пагинацией. Статьи можно снабжать тегами, из которых формируется облако тегов. Пока это единственный рубрикатор сайта, с помощью которого статьи можно объединить по теме или общему смыслу.

Для ленты и карты сайта используется кеширование. При изменении публикации соответствующий кеш сбрасывается.

Редактор, состоящий из блоков

Главная часть проекта — собственный блочный редактор на vanilla JavaScript.

Я сознательно не стал хранить статью в одном огромном поле. Вместо этого документ может иметь один или несколько блоков, и состоит из:

  • заголовков;
  • абзацев;
  • цитат и списков;
  • блоков кода или формул;
  • изображений и видео;
  • разделителей;
  • вставок YouTube, Vimeo и X/Twitter.

В текстовом редакторе используется Markdown. Если пользователь с ним не знаком, ему поможет встроенная подсказка, где собрана информация о разметке и список горячих клавиш.

Markdown, код и математика

Текст проходит через Markdig и превращается в HTML на сервере. Поддерживаются привычные элементы Markdown: выделение, ссылки, списки, цитаты и fenced-блоки кода.

Для вставок программного кода предусмотрена серверная подсветка синтаксиса. У каждого блока есть кнопка «Копировать», которая позволяет одним нажатием поместить код в буфер обмена.

Text
using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

Кроме программирования, я интересуюсь машинным обучением и большими языковыми моделями. В этих областях без математики далеко не уйти: формулы, вероятности, векторы, матрицы - наши лучшие друзья. Поэтому для меня было важно, чтобы MiniBlog умел корректно обрабатывать математические выражения. Это позволяет использовать сайт для технических заметок и публикации материалов по ML и LLM, не прибегая к изображениям.

Формулы записываются в LaTeX-синтаксисе и отображаются через KaTeX:

Text
$E = mc^2$

\(E = mc^2\)

Безопасность контента

Нельзя просто взять и Markdown и превратить его HTML
Нельзя просто взять и Markdown и превратить его HTML

Поэтому MiniBlog проверяет содержание каждого блока, допустимые типы, размеры документа и адреса медиа. Сгенерированный HTML проходит через санитаризацию с явно заданным набором разрешённых тегов и атрибутов.

Embed-ссылки тоже разбираются отдельно. К примеру, YouTube и Vimeo превращаются в безопасные iframe-вставки, а неподдерживаемый или некорректный URL получает ошибку валидации. Принцип здесь простой: доверяй пользователю, но проверяй.

Пользователи и права доступа

Аутентификация построена на ASP.NET Core Identity с cookie-сессиями.

У каждой статьи есть владелец. Имя автора берётся из профиля и не вводится вручную при публикации. Владелец сайта дополнительно может изменять общие настройки и страницу «Обо мне».

Медиа: локально или в S3

Во время локальной разработки изображения и видео можно хранить в wwwroot/uploads. В производственной среде все попадает в S3-совместимое хранилище: AWS S3, MinIO, Ceph и аналогичные сервисы - тут кому как больше нравится. Это относительно дорого или даже избыточно, но позволяет пересобирать контейнер без тревожной мысли: «А где файлы?».

Для развертывания подготовлены Dockerfile и несколько Compose-конфигураций. За подробностями в репу. 😀 Разработчики поймут.

SEO на минималках

Чтобы не превращать SEO в набор чек-листов, после каждой публикации. Для публичных страниц MiniBlog автоматически формирует полный набор базовых SEO-атрибутов: title, description, канонический URL, Open Graph и Twitter Cards, а также robots.txt и sitemap.xml.

Изображения не остаются без альтернативного текста: если автор не указал описание, приложение генерирует его самостоятельно. Заголовки статьи используются для построения оглавления, а страницы ошибок помечаются как noindex.

В production есть еще одна мера предосторожности. Если базовый URL сайта настроен неправильно — например, указывает на http://localhost, — приложение предпочтет завершиться с ошибкой.

Архитектура тоже заслуживает пары слов

Внутри MiniBlog разделён на несколько понятных частей:

  • Razor Pages отвечают за публичные страницы, редактор и учётные записи;
  • Minimal API обслуживает публикацию, редактирование, предпросмотр Markdown, настройки и загрузку файлов;
  • сервисы содержат правила работы со статьями, Markdown, SEO, медиа и настройками сайта;
  • Entity Framework Core работает с PostgreSQL;
  • ASP.NET Core Identity управляет пользователями;
  • JavaScript реализует поведение блочного редактора.

Конечно, можно было разбить всё на десяток микросервисов, но во первых это был бы уже не MiniBlog. А основная тема статьи была бы: как это хозяйство наконец запустить и сколько это будет стоить.

Тесты и эксплуатация

В проекте есть модульные и интеграционные тесты. Они проверяют публикацию и чтение статей, авторизацию, запрет редактирования чужих материалов, обработку ошибок, HTML-страницы, Markdown, валидацию контента и работу S3-хранилища.

API документирован через Swagger и доступен в средах разработки и тестирования. Для базы используются миграции Entity Framework, которые автоматически применяются при запуске.

Production-развёртывание описано отдельно. За подробностями — опять же в репу. 😀

Посмотреть проект

Исходный код можно найти на GitHub: kanisimoff/MiniBlog.

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

Подводя черту

MiniBlog начинался как небольшой аналог Telegra.ph. Потом появились Markdown, математические формулы, подсветка синтаксиса, SEO, S3, Docker, Identity, кеширование, тесты и прочие свистелки-хотелки вещи, которые делают сайт приятным в использовании.

Внутри, конечно, всё уже не так минималистично. Но эта сложность - необходимое зло ради того, чтобы пользователь никогда её не замечал.

Самым интересным экспериментом стала разработка без написания кода вручную. Я ставил задачи, принимал решения, проверял результат и регулярно убеждал ИИ сделать то что мне необходимо. Вайб-кодинг не отменяет инженерную работу. Он лишь меняет инструмент, которым создаётся код.