Содержание

Hugo: создание и настройка статического сайта шаг за шагом

Hugo — это быстрый генератор статических сайтов (Static Site Generator), написанный на Go. Он превращает контент (Markdown) и шаблоны в готовые HTML-страницы без использования базы данных и серверной логики, что делает сайты очень быстрыми, безопасными и удобными для хостинга.

Практическая рекомендация, что выбрать YAML vs JSON

Hugo читает data‑файлы из каталога data/ в форматах YAML, JSON и TOML, после чего они доступны в шаблонах. Формат данных никак не влияет на конечный HTML: это просто разные способы сериализации ключ‑значение и массивов.

Технически можно без проблем комбинировать: глобальные справочники в YAML, «сырые» выгрузки из API в JSON — Hugo спокойно обработает оба варианта.

Установка Hugo в Linux

У меня сейчас под рукой Ubuntu 24.04.3 LTS, поэтому протестирую инструкцию на этой ОС. Проще установить Hugo версии из репозитория Ubuntu.

sudo apt update
sudo apt install hugo
 
$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2025-07-18T03:41:49Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3

Если нужна самая свежая версия, можно скачать .deb с GitHub и поставить через dpkg, но для старта достаточно пакета из дистрибутива.

Не заработала тема с это версией hugo - обновляем системную версию

Скачиваем .deb Hugo Extended нужной версии и устанавливаем через dpkg. Версии hugo смотрим здесь https://github.com/gohugoio/hugo/releases В консоли Linux вводим команды, в переменной HUGO_VER задаем нужную версию hugo.

cd /tmp
HUGO_VER=v0.165.0  # или другая актуальная
 
wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VER}/hugo_extended_${HUGO_VER}_Linux-amd64.tar.gz
tar -xzf hugo_extended_${HUGO_VER}_Linux-amd64.tar.gz
 
# В архиве один бинарник hugo
sudo mv hugo /usr/local/bin/hugo

Установленный бинарник окажется в /usr/local/bin/hugo, я для простоты использования затер системный бинарник установленный из репозитория. Флаг –force нужен, чтобы Hugo не ругался на то, что в папке уже лежит созданная нами директория bin/.

cp /usr/local/bin/hugo /usr/bin/hugo

Как создать чистый проект с конкретной версией Hugo

Нам нужно проигнорировать версию Hugo установленную в систему и поставить более новую версию, для конкретного проекта. То есть в каждом проекте может использоваться своя версия Hugo.

hugo_local_install.sh
#!/bin/bash
set -euo pipefail
 
# --- Настройки ---
HUGO_VER="0.165.0"
BIN_DIR="$HOME/bin"
# -----------------
 
case "$(uname -m)" in
  x86_64)  ARCH="amd64" ;;
  aarch64) ARCH="arm64" ;;
  *) echo "Неизвестная архитектура: $(uname -m)"; exit 1 ;;
esac
 
ASSET="hugo_extended_${HUGO_VER}_linux-${ARCH}.tar.gz"
URL="https://github.com/gohugoio/hugo/releases/download/v${HUGO_VER}/${ASSET}"
 
mkdir -p "$BIN_DIR"
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
 
echo "1. Скачиваем Hugo v${HUGO_VER} (${ARCH})..."
wget -q "$URL" -O "$TMP_DIR/$ASSET"
 
echo "2. Проверяем checksum..."
wget -q "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VER}/hugo_${HUGO_VER}_checksums.txt" -O "$TMP_DIR/checksums.txt"
( cd "$TMP_DIR" && grep " ${ASSET}\$" checksums.txt | sha256sum -c - )
 
echo "3. Распаковываем в $BIN_DIR..."
tar -xzf "$TMP_DIR/$ASSET" -C "$TMP_DIR" hugo
mv -f "$TMP_DIR/hugo" "$BIN_DIR/hugo"
chmod +x "$BIN_DIR/hugo"
 
echo "4. Прописываем PATH (если ещё не прописан)..."
if ! grep -q '# hugo-local-path' "$HOME/.bashrc" 2>/dev/null; then
  echo -e "\n# hugo-local-path\nexport PATH=\"\$HOME/bin:\$PATH\"" >> "$HOME/.bashrc"
fi
 
echo "Готово. Версия:"
"$BIN_DIR/hugo" version
echo "Перелогиньтесь или выполните: source ~/.bashrc"

В итоге получаем абсолютно чистый стандартный проект, созданный конкретной версией Hugo, без каких-либо внешних тем. Генерируем чистую структуру Hugo:

#!/bin/bash
set -e
 
# --- Настройки ---
PROJECT_NAME="new_project_latest_hugo"
HUGO_VER="0.165.0"
# -----------------
 
PROJECT_DIR="$HOME/$PROJECT_NAME"
 
echo "2. Генерируем чистую структуру Hugo..."
cd "$PROJECT_DIR"
./bin/hugo new site . --force
 
echo "3. Инициализируем Git..."
git init
 
echo "Готово! Чистый проект создан:"
echo "cd $PROJECT_DIR && ./bin/hugo server -D"

Установка Hugo и Hextra в Windows 11

Откройте PowerShell от имени администратора и установите Hugo (обязательно версию extended, так как Hextra использует обработку CSS/SASS):

winget install Hugo.Hugo.Extended

Как видно на скриншоте Hugo установился последней версии и появился в списке установленных программ Windows (что меня приятно удивило).

PS C:\WINDOWS\system32> hugo version
hugo v0.165.0-76a5e1880ab46688155b02e99bab9be2a6134492+extended windows/amd64 BuildDate=2026-08-12T14:26:28Z VendorInfo=gohugoio

Рекомендуемые расширения для VS Code:

Создадим проект в Windows 11. Переходим в папку нашего проекта и создаем структуру Hugo:

cd C:\Projects\project_dnet
hugo new site . --force

Тема Hextra подключается как Hugo Module или Git Submodule. Инициализируем Git и модуль (если git не установлен изучите Как установить GIT в Windows):

git init
git submodule add https://github.com/imfing/hextra.git themes/hextra

Создание проекта

Перейди в каталог, где хочешь держать проект (мой проект называется vs_engine). Эта команда создаст структуру каталогов (content/, layouts/, static/, config и т.д.).

hugo new site vs_engine
cd vs_engine

Инициализируй Git (желательно сразу), что упростит дальнейшую работу, деплой и откат изменений.

git init
git add .
git commit -m "init"

Добавление темы

cd /home/darkfire/vs_engine
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo "theme = 'ananke'" >> hugo.toml

Тема Hugo Book

Тема Book Introduction Hugo Book.

Откуда теперь берутся названия разделов? Их не нужно прописывать в . Названия и порядок задавай в _index.md соответствующего раздела. Например, content/ru/services/_index.md:

---
title: 'Софт и сервисы'
weight: 1
---

Если нужен короткий текст именно в меню, можно задать linkTitle.

Установка Book с готовым шаблоном сайта и нужной версией Hugo

#!/bin/bash
set -e
 
# --- Настройки ---
PROJECT_NAME="project_book_latest_hugo"
HUGO_VER="0.165.0"
# -----------------
 
PROJECT_DIR="$HOME/$PROJECT_NAME"
 
echo "1. Скачиваем Hugo v${HUGO_VER}..."
mkdir -p "$PROJECT_DIR/bin"
wget -q "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VER}/hugo_extended_${HUGO_VER}_linux-amd64.tar.gz" -O /tmp/hugo.tar.gz
tar -xzf /tmp/hugo.tar.gz -C "$PROJECT_DIR/bin" hugo
chmod +x "$PROJECT_DIR/bin/hugo"
rm -f /tmp/hugo.tar.gz
 
echo "2. Настраиваем Git и тему..."
cd "$PROJECT_DIR"
git init
git submodule add https://github.com/alex-shpak/hugo-book.git themes/hugo-book
git add .
git commit -m "Initial commit"
 
echo "3. Копируем готовый шаблон..."
cp -r themes/hugo-book/exampleSite/* .
 
echo "Готово! Запуск проекта:"
echo "cd $PROJECT_DIR && ./bin/hugo server -D"

Тема Hextra альтернатива Book

Hextra выглядит современнее Hugo Book и уже включает:

Тема Hextra активно развивается, но до сих пор имеет ряд недостатков:

  1. В текущем исходный код на 06.09.2026: переключатель перебирает все языки сайта. Если перевода текущей страницы нет, функция lang-link возвращает адрес главной страницы выбранного языка. Поэтому отсутствие перевода не убирает язык из списка. То есть та же самая проблема что и у Astro Starlight.
  2. FlexSearch остаётся браузерным поиском. Его можно заменить на Pagefind, но тогда преимущество «всё из коробки» частично исчезает.

Тема Relearn

Тема Relearn главный конкурент Book: больше готовых функций: Более развитая навигация и поиск, таксономии, печать разделов, включение файлов, много компонентов.

Что Relearn даёт сверх простой базы знаний

Полезные именно тебе возможности:

Эти функции описаны в документации Relearn. По возможностям организации и чтения большого справочника он ближе к возможностям DokuWiki установка (Nginx + PHP-FPM или Apache), настройка и использование.

Тема PaperMod

Предустановленные CSS-переменные PaperMod. Тема использует стандартные CSS Variables для светлой и тёмной темы. Вы можете легко переопределить их в вашем assets/css/extended/custom.css:

/* Изменение палитры для тёмной темы (по умолчанию) */
:root {
    --gap: 24px;
    --content-gap: 20px;
    --nav-width: 1024px;
    --main-width: 720px;
    --header-height: 60px;
    --footer-height: 60px;
    --radius: 8px;
    --theme: rgb(29, 30, 32);
    --entry: rgb(37, 38, 40);
    --primary: rgb(218, 218, 219);
    --secondary: rgb(155, 156, 157);
    --tertiary: rgb(65, 66, 68);
    --content: rgb(196, 196, 197);
    --hljs-bg: rgb(46, 46, 51);
    --code-bg: rgb(55, 56, 62);
    --border: rgb(51, 51, 51);
}
 
/* Изменение палитры для светлой темы */
.list.light {
    --theme: rgb(255, 255, 255);
    --entry: rgb(255, 255, 255);
    --primary: rgb(30, 30, 30);
    --secondary: rgb(108, 108, 108);
    --tertiary: rgb(214, 214, 214);
    --content: rgb(50, 50, 50);
    --hljs-bg: rgb(28, 29, 33);
    --code-bg: rgb(245, 245, 245);
    --border: rgb(238, 238, 238);
}

Создание первой страницы и запуск

Создай первый пост:

hugo new posts/first-post.md

Hugo создаст файл с front matter и draft: true; отредактируй его и поставь draft: false, чтобы пост был виден.

Запусти dev‑сервер. По умолчанию сайт откроется на http://localhost:1313, пересборка идет автоматически при изменении файлов. Ключ D позволяет показывать также черновики ваших постов.

hugo server -D

Для продакшен‑сборки запусти просто hugo. Готовый статический сайт окажется в каталоге public/, его уже можно заливать на VPS, Nginx, GitHub Pages и т.п.

Содержимое public/ можно спокойно удалять, это просто результат сборки, а не исходники. Обычно public/ не коммитят в Git (добавляют в .gitignore), а используют только как артефакт для деплоя.

Статические файлы

В Hugo все статические файлы должны лежать в папке static.

Мультиязычность

Мультиязычность i18n. Hugo берет значение из текущего языка (например, ru.toml). Если перевода для ключа в ru.toml нет, Hugo автоматически берет значение из языка по умолчанию (en.toml). Поэтому файл en.toml служит «базовым словарем» всего сайта.

В каком формате могут храниться языковые файлы i18n?

Hugo поддерживает 3 основных формата файлов в директории i18n/. Вы можете выбрать любой, Hugo определит его по расширению:

  1. TOML (i18n/en.toml, i18n/pt.toml) — Рекомендуемый. Идеален для проектов, где основной конфиг hugo.toml написан на TOML.
  2. YAML (i18n/en.yaml, i18n/pt.yaml). Очень чистый синтаксис без лишних скобок, удобен для чтения человеком.
  3. JSON (i18n/en.json, i18n/pt.json) Стандарт для web-разработки, удобно, если тексты переводов будут генерироваться скриптами или импортироваться из внешних систем.
    {
      "tld_domain": {
        "other": "Domain Zone"
      },
      "tld_type": {
        "other": "Type"
      },
      "tld_manager": {
        "other": "Registry Manager"
      }
    }

Поиск на статическом сайте через Fuse.js

Fuse.js — это лёгкий клиентский библиотечный движок для нечёткого поиска (fuzzy search). Он идеален для static-first архитектуры на Hugo, так как не требует backend-серверов или Node.js в runtime.

Принцип работы Fuse.js в Hugo:

  1. Генерация JSON-индекса: Hugo при сборке сайта генерирует единый компактный файл index.json.
  2. Загрузка через fetch: При открытии страницы браузер асинхронно скачивает индекс.
  3. Поиск в памяти: При вводе символов Fuse.js мгновенно ищет совпадения по массиву, учитывая опечатки, сходство строк и заданные веса полей.
  4. Динамический рендер: Поисковая выдача подставляется в DOM без перезагрузки страницы.

FAQ 1: Как работает обычный пост (hugo new posts/first.md)

Когда ты создаешь обычный пост, ты пишешь текст внутри файла (после —). У этого поста нет параметра layout.

Hugo действует так:

  1. Видит пост в папке posts.
  2. Ищет специальный шаблон. Не находит.
  3. Берет стандартный шаблон темы (themes/ananke/layouts/_default/single.html).
  4. Этот шаблон делает простую вещь: берет текст твоего поста и выводит его на экран.

Если же мы генерируем файлы, то там не будет текста. Если мы применим к ним стандартный шаблон (как для обычных постов), то Hugo просто выведет Заголовок и… пустую страницу. Именно поэтому в Python-скрипте мы добавили строчку: layout: "compare". Эта строчка говорит Hugo: "Не используй стандартный шаблон! Ищи специальный файл с именем compare.html".

Куда положить этот compare.html?

Hugo ищет шаблоны в строгом порядке. Если твой контент лежит в content/posts, то Hugo ищет шаблон в такой последовательности:

  1. layouts/posts/compare.html
  2. layouts/_default/compare.html (Запасной вариант).

Обычные посты (без layout: "compare") будут по-прежнему открываться через стандартный шаблон темы.

FAQ 2: Как создать robots.txt, ads.txt в Hugo

Решение: Поскольку ads.txt — это статический текстовый файл, который не требует обработки Hugo, его проще всего поместить в папку static. Создайте файл в директории с нужным содержимым static/ads.txt. Как это работает: Любой файл, помещенный в папку static/, копируется Hugo как есть в корень папки public/.

  1. Разрешает сканировать весь сайт (Allow: /).
  2. Ссылается на ваш sitemap.xml.

В разных версиях Hugo файл robots.txt может генерироваться по разному, в версии hugo v0.152.2 мне пришлось создать файл layouts/index.robots.txt с содержимым

User-agent: *
Allow: /
 
Sitemap: {{ "sitemap.xml" | absURL }}

и в начало файла hugo.toml добавить настройки:

# ==========================================================
# --- 1. НАСТРОЙКИ ВЫВОДА ФОРМАТОВ (RobotsTXT) ---
# ==========================================================
[mediaTypes]
  [mediaTypes."text/plain"]
    suffixes = ["txt"]
    delimiter = ""
 
[outputFormats]
  [outputFormats.RobotsTXT]
    mediaType = "text/plain"
    baseName = "robots"
    isPlainText = true
    notRendering = false
 
[outputs]
  home = ["HTML", "RSS", "RobotsTXT"]
# ==========================================================

FAQ 3: Что такое Tailwind CSS? Сравнение: PaperMod vs. Tailwind CSS

Tailwind CSS — это utility‑first CSS‑фреймворк: вместо готовых компонентов он даёт кучу маленьких классов типа flex, mt-4, text-gray-700, из которых ты собираешь дизайн прямо в HTML. С Hugo он стыкуется как шаг сборки: Tailwind генерирует итоговый CSS (обычно через CLI/PostCSS), а Hugo подключает этот CSS как ресурс в шаблонах.

Hugo сам по себе не умеет «стилизовать», он просто собирает HTML; Tailwind подключается как отдельная стадия, которая из input.css и шаблонов Hugo собирает минимальный output.css.

Критерий PaperMod Tailwind CSS (через Hugo Pipe)
Скорость запуска 10/10 (установил и забыл) 6/10 (нужна база верстки)
Гибкость дизайна Низкая (сложно менять сетку) Безграничная
Конверсия (CTR) Средняя (похож на сотни сайтов) Высокая (делаем кнопки и таблицы «как в Apple»)
SEO (Core Web Vitals) Отлично Идеально (только нужный CSS)
Сложность правок Мучение (перезапись CSS-файлов темы) Легко (классы прямо в HTML/шаблонах)

FAQ: Настройка внешних ссылок (Render Hooks) в Hugo: автоматическое добавление атрибутов nofollow _blank

Чтобы не прописывать атрибуты target="_blank" и rel="nofollow" вручную для каждой ссылки, в Hugo используются Render Hooks. Это позволяет писать обычный Markdown, а всю техническую работу переложить на движок сайта.

<<a href="{{ .Destination | safeURL }}"{{ with .Title }} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener nofollow"{{ end }}>{{ .Text | safeHTML }}</a>

Почему это лучше, чем использовать прямой HTML-код в статьях? Использование Render Hooks дает три критических преимущества:

Будут ли внутренние ссылки открываться в новом окне? Нет. Логика кода выше проверяет префикс ссылки. Если ссылка начинается с http (внешняя), Hugo добавит атрибуты для открытия в новом окне. Если это относительная ссылка (внутренняя, например /posts/my-article/), она откроется в той же вкладке, сохраняя стандартное поведение пользователя на сайте.

Нужно ли добавлять rel="noopener"? Да, при использовании target="_blank" добавление rel="noopener" является обязательным стандартом безопасности. Это предотвращает доступ открытой страницы к объекту window.opener вашей страницы, что защищает от фишинговых атак и улучшает производительность браузера.

FAQ: Подключение сложного JS и React к Hugo

Мнение о том, что «Hugo — это просто статика и туда нельзя вставить React» — это миф.

В Hugo есть мощный встроенный инструмент Hugo Pipes (который под капотом использует ESBuild). Вы спокойно можете вызывать и запускать внутри Hugo любой современный JavaScript/TypeScript, подключать библиотеки из npm и рендерить React-компоненты. Есть три способа использовать React/JS в Hugo:

  1. Простой React / Vue / JS прямо в Markdown-файлах (Shortcodes). Если вам нужно вставить интерактивный виджет (например, динамический калькулятор, фильтр или интерактивную таблицу) прямо внутрь статьи: Вы создаете обычный React-компонент (или чистый JS) и оборачиваете его в Hugo Shortcode (аналог шорткодов в WordPress или компонентов в MDX).
  2. Использование ESBuild (Встроено в Hugo из коробки). Вы можете положить свои .jsx / .tsx / .ts файлы в папку assets/js/, и Hugo сам автоматически соберет их, скомпилирует, минифицирует и подключит к сайту:
    {{ $built := resources.Get "js/calculator.jsx" | js.Build }}
    <script src="{{ $built.RelPermalink }}"></script>
  3. Подключение через Widget / Web Components (Zero-Build React). Для легких реактивных виджетов можно использовать Preact или React через CDN / ES Modules или компилировать их в стандартные Web Components. Они встают в Hugo без настройки сложных сборщиков Webpack/Vite.