diff --git a/archetypes/default.md b/archetypes/default.md index 0cf716e..7961b4c 100644 --- a/archetypes/default.md +++ b/archetypes/default.md @@ -1,6 +1,21 @@ --- date = '{{ .Date }}' +lastmod = '{{ .Date }}' draft = true title = '{{ replace .File.ContentBaseName "-" " " | title }}' +slug = '{{ .File.ContentBaseName }}' +description = '' ---- +categories = [ + 'uncategorized', +] + +tags = [ + 'draft', +] + +keywords = [ + 'hugo', + 'blog' +] +--- \ No newline at end of file diff --git a/content/posts/hugo-slugs-archetypes-bundles/index.md b/content/posts/hugo-slugs-archetypes-bundles/index.md new file mode 100644 index 0000000..51e662b --- /dev/null +++ b/content/posts/hugo-slugs-archetypes-bundles/index.md @@ -0,0 +1,179 @@ +--- +date = '2026-04-18T09:44:39+03:00' +lastmod = '2026-04-18T09:44:39+03:00' +draft = true +title = 'Как автоматизировать создание постов в Hugo: slugs, архетипы и бандлы' +slug = 'hugo-slugs-archetypes-bundles' +description = 'Настраиваем Hugo так, чтобы не копировать index.md вручную, не мучиться с транслитерацией и получать красивые URL с датами' + +categories = [ + 'Hugo', + 'DevOps' +] + +tags = [ + 'hugo', + 'static-site-generator', + 'automation', + 'frontmatter' +] + +keywords = [ + 'hugo', + 'blog' +] +--- + +## Проблема: рутина при создании постов + +Когда я только начинал вести блог на Hugo, каждый новый пост создавался через боль и страдания: + +1. Создать папку вручную `content/posts/название-поста/` +2. Скопировать туда `index.md` из соседней папки +3. Отредактировать front matter (дату, заголовок, теги) +4. Придумать slug для красивого URL +5. ...и не забыть, что папку лучше назвать на латинице + +На всё это уходило пара минут чисто механической работы. А когда постов 10–20, это начинает реально бесить. + +В этой статье я расскажу, как я решил эту проблему с помощью штатных возможностей Hugo: **архетипов (archetypes)**, **пермалинков (permalinks)** и правильной организации **бандлов (bundles)**. + +## Что такое бандл и зачем папка для каждого поста + +Hugo поддерживает два типа контента: + +- **Leaf bundle** — папка с файлом `index.md`. Внутрь можно складывать изображения, файлы, другие ресурсы. Идеально для блога. +- **Branch bundle** — папка с `_index.md`. Используется для секций-списков (например, `/posts/`). + +Структура моего блога: +content/ +├── posts/ +│ ├── hugo-slugs-archetypes-bundles/ +│ │ ├── index.md +│ │ ├── images/ +│ │ │ └── diagram.png +│ │ └── code-example.txt +│ └── другой-пост/ +│ └── index.md + +Плюсы такого подхода: +- Все файлы поста в одном месте +- Можно удобно ссылаться на изображения: `![схема](images/diagram.png)` +- Не нужно придумывать уникальные имена для картинок глобально + +## Почему папку бандла нужно называть на латинице + +Здесь кроется важный момент. Hugo позволяет использовать любые символы в именах папок, включая кириллицу. Но есть **две причины использовать латиницу**: + +1. **Чистые URL.** Если папка называется `мой-пост`, то URL будет `/%D0%BC%D0%BE%D0%B9-%D0%BF%D0%BE%D1%81%D1%82/`. Браузер это поймёт, но выглядит ужасно. +2. **Slug без транслитерации.** Имя папки удобно использовать как `slug` — последний сегмент URL. А латиница в URL — это стандарт и хороший тон. + +**Правило:** папку называем на латинице (например, `my-awesome-post`), а заголовок внутри пишем по-русски. + +## Как автоматизировать создание бандла через консоль + +Команда для создания бандла с одной папкой: + +```bash +hugo new content posts/название-папки/index.md +``` + +Hugo сам создаст папку, сгенерирует index.md с front matter из архетипа. + +Важно: эта команда появилась в Hugo 0.112. В старых версиях нужно было сначала создать папку, потом файл. + +## Настройка архетипа (archetype) + +Архетип — это шаблон для новых файлов. Он лежит в archetypes/default.md (или в archetypes/post-bundle.md для конкретного типа). + +Мой архетип выглядит так (TOML-формат): + +```toml +--- +date = '{{ .Date }}' +lastmod = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' +slug = '{{ .File.ContentBaseName }}' +description = '' +author = 'Кразя' + +categories = [ + 'uncategorized' +] + +tags = [ + 'draft' +] +--- +``` + +Разберём ключевые моменты: +Поле Значение +title Берёт имя папки, заменяет дефисы на пробелы и делает заглавные буквы. my-awesome-post → My Awesome Post +slug Просто берёт имя папки как есть: my-awesome-post +.File.ContentBaseName Встроенная переменная Hugo — имя текущей папки без расширения и пути + +После создания поста я вручную меняю title на русский и заполняю description, categories, tags. + +## Настройка permalinks для красивых URL + +Чтобы URL выглядел как 2025/03/my-awesome-post/, а не как posts/my-awesome-post/, добавляем в hugo.toml: + +```toml +[permalinks] + posts = "/:year/:month/:slug/" +``` + +Теперь при сборке сайта Hugo сам построит нужную структуру. При этом внутри content/ всё остаётся по-прежнему — папка в posts/. + +## Полный цикл создания поста (без лишних телодвижений) + +Вот как теперь выглядит создание нового поста в моём блоге: + +```bash +# 1. Создаём бандл с латинским именем папки +hugo new content posts/hugo-best-practices/index.md + +# 2. Открываем файл и правим русский заголовок, описание, теги +vim content/posts/hugo-best-practices/index.md + +# 3. Пишем пост в markdown +# 4. Смотрим локально +hugo server -D + +# 5. Публикуем +make deploy +``` + +## Что ещё можно добавить в front matter + +В процессе настройки я выяснил, что Hugo поддерживает много полезных полей: +|Поле |Назначение| +|publishDate |Отложенная публикация (не рендерится до указанной даты)| +|expiryDate |Автоматическое снятие с публикации| +|lastmod |Дата последнего изменения (для SEO)| +|aliases |Редиректы со старых URL| +|weight |Ручная сортировка в списке (меньше — выше)| +|images |Изображение для Open Graph и Twitter Cards| +|params |Кастомные параметры для темы| + +## Итог + +После всех настроек создание нового поста занимает ровно столько времени, сколько нужно на написание контента. Никакой ручной возни с папками и копированием index.md. + +Ключевые выводы: + +- Используйте leaf bundles (папка + index.md) для хранения всех ресурсов поста в одном месте + +- Папки называйте на латинице — это даст чистые URL и автоматический slug + +- Настройте архетип с переменной {{ .File.ContentBaseName }} для автоматической генерации title и slug + +- Добавьте [permalinks] в конфиг для красивых URL с датами + +Создавайте новый пост одной командой: ```bash hugo new content posts/имя-папки/index.md``` + +Теперь можно сосредоточиться на том, ради чего всё затевалось — на содержании. + +Если у тебя есть свои лайфхаки по Hugo или ты знаешь, как сделать транслитерацию slug прямо из заголовка — пишите мне в Telegram https://t.me/kpa39l. Обсудим. \ No newline at end of file