Как устроен этот блог: минимализм, Astro и дух IDE
Когда я решил завести свой личный блог, у меня было одно четкое требование: он должен быть быстрым, аскетичным и при этом ощущаться как родная IDE. Никакого визуального мусора, только код, текст и удобная навигация.
В этой статье я расскажу, как я собрал то, что вы видите перед собой, и какие «грабли» пришлось обойти, чтобы подружить современный веб с ламповым текстовым интерфейсом.
Стек технологий
Я остановился на Astro. Это сейчас золотой стандарт для контентных сайтов.
- Astro: Генерация статики (SSG). Весь блог — это набор HTML-файлов, которые отдаются мгновенно.
- Pico.css: Потрясающе легкий фреймворк. Он берет стандартные HTML-теги и делает их красивыми без сотен классов.
- JetBrains Mono: Тот самый шрифт, который делает любой интерфейс чуточку «техничнее».
- Chroma: Для подсветки синтаксиса в блоках кода (через интеграцию Astro).
Архитектура: Файлы — это всё
В основе блога лежит принцип Content-first. Все статьи — это просто Markdown-файлы в папке src/content/blog/.
graph TD
subgraph "Контент (Markdown)"
Blog[Blog Posts: src/content/blog/]
Pages[Special Pages: src/content/pages/]
end
subgraph "Сборка (Astro SSG)"
CC[Content Collections]
Router["Dynamic Router ([...path], blog/index)"]
Statics["Static Pages (index, about-me)"]
Layout["Layout.astro (Container + Sidebar)"]
end
Blog -->|Fetch| CC
Pages -->|Fetch| CC
CC -->|Blog Data| Router
CC -->|Pages Data| Statics
CC -->|Sidebar Data| Layout
Router -->|Injected into| Layout
Statics -->|Injected into| Layout
Layout -->|Build| HTML[Static HTML Files]
subgraph "Развертывание"
HTML --> Web[GitHub Pages]
end
style Blog fill:#f9f,stroke:#333
style Pages fill:#f9f,stroke:#333
style HTML fill:#bbf,stroke:#333
style Web fill:#dfd,stroke:#333
Astro автоматически типизирует эти файлы через Content Collections. Это позволяет мне на этапе сборки проверять, что у каждой статьи есть дата, заголовок и раздел.
Фишки сайдбара
Самая сложная и интересная часть — навигация. Я хотел, чтобы она работала как дерево файлов в VS Code.
Поиск с транслитерацией
Поскольку блог на русском, а файлы часто называются латиницей, я реализовал «умный» поиск. Если вы пишете «архитектура», скрипт на лету превращает это в arhitektura и находит нужный файл.
const ruToEn = { 'а':'a', 'б':'b', 'в':'v', ... };
function transliterate(text) {
return text.split('').map(c => ruToEn[c] ?? c).join('');
}
Продуманная сортировка
Разделы в дереве всегда отсортированы по алфавиту, чтобы навигация была предсказуемой и папки не меняли положение. А вот внутри каждого раздела статьи выстроены по новизне — свежие мысли всегда сверху.
Сохранение состояния
Поскольку это статический сайт, при каждом клике страница перезагружается. Чтобы поиск не сбрасывался, а дерево не «прыгало», я использую localStorage. Кроме того, состояние поиска дублируется в URL параметры, так что результатом фильтрации можно поделиться просто скопировав ссылку.
Чистота контента
Чтобы работа с текстом была максимально приятной, я настроил автоматизацию:
- Layout автоматически подхватывает
titleиз метаданных (frontmatter) и делает его главным заголовком страницы. - Markdown остается чистым. В нем нет лишних
h1, только суть и подзаголовки. - Markdownlint настроен так, чтобы не ругаться на отсутствие заголовка в первой строке, так как система добавит его сама.
Почему это стоит повторить?
Такой подход дает невероятное чувство контроля. Вы не зависите от баз данных, вам не нужен сложный сервер. Ваш блог — это репозиторий на GitHub. Вы пишете текст в любимом редакторе, делаете git push, и через минуту новая статья уже в сети. А еще вам не надо думать о бэкапах, так как git — лучший файлообменник (а не skype).