Бложим как фрики

f64298bc60edaf8bedf04eabd7b29114

Сидишь бывало, записываешь всякие штукуёвины, которые сам вечно забываешь и вдруг кааак захотелось начать наносить людям добро и причинять радость вопреки их желаниям, а тут ещё и народ периодически спрашивает, стало быть надо завести блох, но не в свитере, а который будет удобный, быстрый, защищённый, красивый и не будет зависеть от модных веяний на очередной платформе-однодневке, не будет обмазан странными всплывашками, баннерами, пропагандой…

Но писать с нуля новый движок или пользоваться вечно дырявыми php-бложиками не барское дело и вообще не хочется разбираться со всей этой кухней из протухших зависимостей.

Markdown

Писать будем простой удобочитаемый текст, из любого удобного места, практически с первого попавшегося холодильника, в любом первом попавшемся редакторе, хоть в vim, как деды верещали, не отвлекаясь в творческом угаре на проблемы софта, доступности облачков, новые свистоперделки облачков, обновления свистоперделок и прочие всплывашки и отвлекаторы. Чем проще — тем лучше. Надёжно как кирпич. Нам поможет в этом тёплый ламповый Markdown, который неплохо так везде поддержан оставаясь достаточно простым и умеет хорошо расширяться. Ну и вообще, все же знают и умеют в Markdown.

Hugo

Markdown будем раскатывать в статичный сайт, который по определению быстр, хорошо кэшируется, индексируется и не хакается, не говоря о том что зависимостей которые будут протухать и отваливаться просто нет из коробки. GitHub Pages проталкивает Jekyll, но ведь есть божественный и быстрый Hugo, с его сотнями шаблонов оптимизированных на любой вкус и цвет, от мобилок и Accessibility (который правильно сделанный помогает не только лишь людям с проблемами, но и для всяких удобных штук типа vimium очень полезен), до СЕО, комментариев и нормальной поддержки опций типа Reader View в Firefox. Hugo написан на Go, поэтому есть под все основные платформы и без приседаний с окружением и зависимостями — просто скачал и работай. Только нам, скорее всего, понадобится SCSS, поэтому из сборок качаем hugo extended. Теперь можно сходить почитать документацию.

Но мы ленивые, а Hugo достаточно взрослый, если его позапускать из консоли, он сам расскажет про hugo help new, ну, а дальше по накатанной

> hugo new site my-blog
Congratulations! Your new Hugo site was created in D:\Projects\my-blog.
Just a few more steps...
1. Change the current directory to D:\Projects\my-blog.
2. Create or install a theme:   
  - Create a new theme with the command "hugo new theme "   
  - Or, install a theme from https://themes.gohugo.io/
3. Edit hugo.toml, setting the "theme" property to the theme name.
4. Create new content with the command "hugo new content \.".
5. Start the embedded web server with the command "hugo server --buildDrafts".
See documentation at https://gohugo.io/.

И как бы можно с места в карьер, но…

Нужно сначала один раз нормально разобраться и настроить.

Тема по умолчанию — это черновик, который будет добавлять 3 тестовых поста из themes\default\content и в целом просит кирпича напильника.
Поэтому идём в репозиторий тем и выбираем что-нибудь покавайнее под наши нужды. Мне, например, понравилась m10c.

git clone https://github.com/vaga/hugo-theme-m10c.git themes/m10c
echo "theme = 'm10c'" >> hugo.toml

Новые посты по умолчанию генерятся в директории content из шаблона сохранённого в archetypes, но не забывайте прописывать формат файла, иначе получите ошибку

> hugo new content posts\my-first-post
Error: failed to resolve "posts\\my-first-post" to an archetype template

> hugo new content posts\my-first-post.md
Content "my-blog\\content\\posts\\my-first-post.md" created

Пост не будет генериться в блог, пока в шапке с метаданными присутствует draft = true. Удаляем, дописываем что-нибудь весёленькое и дальше по вкусу: можно просто запустить hugo в директории с проектом и он сгенерит public со статичным сайтом, а можно запустить hugo server, кликнуть на предложенный урлик и сразу посмотреть в браузере результат.

Настраиваем параметры генератора и шаблона

Всё основное конфигурируется через config.toml и достаточно очевидно

baseURL = 'https://USERNAME.github.io/'
title = "USERNAME blog"

languageCode = 'ru-ru'
defaultContentLanguage = "ru"
defaultContentLanguageInSubdir = true

theme = 'm10c'

# publishdir = '_site'

enableRobotsTXT = false

[params]
  author = 'USERNAME'
  description = 'Whatever Developer, full-stack. Interested in *nix, maker culture, home assistant, photo, nature, birdwatching'
  avatar = 'https://avatars.githubusercontent.com/u/USERID'

[[params.social]]
  icon = "github"
  name = "My Github"
  url = "https://github.com/USERNAME"
[[params.social]]
  icon = "linkedin"
  name = "linkedin"
  url = "https://www.linkedin.com/in/USERNAME"
[[params.social]]
  icon = "telegram"
  name = "telegram"
  url = "https://t.me/USERNAME"

[menu]
  [[menu.main]]
    identifier = "home"
    name = "Home"
    url = "/"
    weight = 1
  [[menu.main]]
    identifier = "posts"
    name = "Posts"
    url = "/posts/"
    weight = 2
  [[menu.main]]
    identifier = "tags"
    name = "Tags"
    url = "/tags/"
    weight = 3
  [[menu.main]]
    identifier = "about"
    name = "About"
    url = "/about/"
    weight = 4

Меняем под свои аккаунты.

Фото на аватарку можно либо залить сразу в репозиторий, либо сделать ссылку на фото из профиля гитхаба, либо ещё про какой gravatar подумать.

Немножко систематизируем

В директории у нас могут быть

  • _index.md — индексный файл который указывает что нам нужно сгенерировать список статей из того что лежит в текущей директории и поддиректориях. В принципе это поведение по умолчанию для директории, но возможно вы захотите задать заголовок для этой страницы, тогда минимальное содержимое будет примерно таким

    ---
    title: "My custom title for this category"
    ---
  • index.md — главный файл для данной директории (по аналогии с index.html), если он есть то для данного пути Hugo будет использовать именно его и на все остальные статьи вам где-то придётся самостоятельно прописывать ссылки

  • всякие прочие *.md — файлы из которых будут генериться статичные страницы с вашими статьями.

Статья my-blog\content\posts\article.md будет сгенерена в my-blog\public\posts\article\index.html

И раз у нас всё равно под каждую статью генерится директория, чтобы избегать путаницы, я предпочитаю сразу все посты именовать в формате content\posts\YYYYMMDD-article-name\index.md и всякие скрины и аттачи к ним складывать в директорию к статье.
Т.е. новая статья будет генериться как-то так

hugo new content posts\2024-08-24-blog-like-a-freak\index.md

Шапка статьи у меня выглядит примерно так

---
title: 'Бложим как фрики'
description: О мой бложе, что я несу...
date: 2024-08-28T11:46:29+03:00
categories: Blog
tags: ['Blog', 'Hugo', 'Markdown']
layout: post
---

date влияет на порядок сортировки статей

Теги и категории используются для генерации /tags/ и /categories/ соответственно
layout переопределяет какой шаблон из выбранной темы используется

И отдельно стоит упомянуть лэндинг в корне сайта. По умолчанию конкретно эта тема создаёт список постов, а весь контент из content\_index.md игнорируется. Если нас такое поведение страниц со списками сайтов не устраивает, можно в m10c\layouts\_default\list.html добавить секцию {{ .Content }} после заголовка. Если же мы хотим ещё больше кастомизации, то создаём themes\m10c\layouts\_default\home.html с кастомизацией для корневой страницы. Для примера можно взять копию файла из дефолтной темы

{{ define "main" }}
  {{ .Content }}
  {{ range site.RegularPages }}
    

{{ .LinkTitle }}

{{ .Summary }} {{ end }} {{ end }}

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

{{ range .Site.Sections }}
  

{{ .LinkTitle }}

{{ end }}

Возможности кастомизировать шаблоны Hugo кажутся бескрайними, ярчайший пример тому — документация от Kubernetes

GitHub

Вообще хостить статичный примитив можно тоже на чём угодно, лишь бы места хватило, хоть на ESP32 с microSD или на флешке воткнутой в кинетик. Но уже есть доступный, надёжный, бесплатный и всем знакомый GitHub.

Исключаем в .gitignore всё лишнее

/.hugo_build.lock
/public
/resources/_gen

Инициализируем репозиторий, коммитаем наш нехилый супец

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

Создаём на GitHub публичный репозиторий и в него заливаемся

git remote add origin git@github.com:USERNAME/my-blog.git
git push -u origin master

GitHub Actions

Ну тут всё просто, мы хотим чтобы на любой коммит в мастер Hugo собирал новую версию статики и публиковал её. Что мы и запишем в .github\workflows\hugo.yml

name: Deploy Hugo site to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches: ["master"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true

# Default to bash
defaults:
  run:
    shell: bash

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.133.1
    steps:
      - name: Install Hugo CLI
        run: |
          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
          && sudo dpkg -i ${{ runner.temp }}/hugo.deb
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v2
      - name: Build with Hugo
        env:
          # For maximum backward compatibility with Hugo modules
          HUGO_ENVIRONMENT: production
          HUGO_ENV: production
        run: |
          hugo \
            --minify \
            --baseURL "${{ steps.pages.outputs.base_url }}/"
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v1
        with:
          path: ./public

  # Deployment job
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v1

И раз мы разворачиваем новый контент через GitHub Actions, то и в репозитории, в Settings — Pages — Build and deployment — Source тоже стоит указать GitHub Actions

Всё, уже можно нести в мир улыбку, бешенство и моральную смерть.

Obsidian

Но надо ещё редактор покомфортнее. Если вы себе ещё не нашли подходящий, редактировать сырой Markdown лениво, а редактор самого GitHub вас не устраивает, возьмите Obsidian — замечательный WYSIWYG редактор к Markdown, много кто уже использует для заметок.
Заставим его открыть директорию с нашим репозиторием блога как новый Vault и пройдёмся по настройкам

Editor

Strict line breaks = включаем
Indent using tabs = отключаем, пробелы наше всё

Files and links

Default location for new notes = in the folder specified below
Folder to create new notes in = content/posts

New link format = Relative path to file

Use [[Wikilinks]] — отключаем, нам нужен честный Markdown

Default location for new attachments = Same folder as current file
поскольку для каждой статьи всё равно будет отдельная директория. И всё это можно будет спокойно переносить куда угодно

Шаблоны

Определяемся, будем мы каждый раз ручками вызывать из консоли

hugo new content posts\whatever.md

или всё-таки за шаблон будет отвечать Obsidian и тогда прописываем пути к шаблонам.

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

Core plugins — Daily notes

New file location = content/posts
Template file location = archetypes/default

Core Plugins — Templates

Пусть наши шаблоны берутся из директории archetypes

А так же меняем сам шаблон на что-то вида

---
title: PAGE TITLE
description: PAGE DESCRIPTION
date: {{date}} {{time:HH:mm:ss Z}}
categories: blog
tags: []
layout: post
---

Obsidian Git

Идём в настройках в Community Plugins, включаем их, жмём Browse и ищем всякое про Git. Находим, например, Git за авторством Vinzent (Denis Olehov). Ставим, включаем.

Теперь по Ctrl+P мы можем найти нужные нам commit/push/pull прямо в Обсидиане

Коммитаемся… всё наши настройки редактора тоже в репозитории и теперь можно синкать всё на другой ПК или телефон и неспешно, смакуя, под кофирёк, строчить всякую дичь, чтобы полыхало веселее

И простым Ctrl+C, Ctrl+V эти статьи потом при желании можно репостить на хабр и прочие ресурсы с минимальными правками.

При желании всё это можно приспособить для ведения документации, всяких лендингов, сайта-визитки с CV.

Habrahabr.ru прочитано 11209 раз