Сидишь бывало, записываешь всякие штукуёвины, которые сам вечно забываешь и вдруг кааак захотелось начать наносить людям добро и причинять радость вопреки их желаниям, а тут ещё и народ периодически спрашивает, стало быть надо завести блох, но не в свитере, а который будет удобный, быстрый, защищённый, красивый и не будет зависеть от модных веяний на очередной платформе-однодневке, не будет обмазан странными всплывашками, баннерами, пропагандой...
Но писать с нуля новый движок или пользоваться вечно дырявыми 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:Projectsmy-blog.
Just a few more steps...
1. Change the current directory to D:Projectsmy-blog.
2. Create or install a theme:
- Create a new theme with the command "hugo new theme <THEMENAME>"
- 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 <SECTIONNAME><FILENAME>.<FORMAT>".
5. Start the embedded web server with the command "hugo server --buildDrafts".
See documentation at https://gohugo.io/.
И как бы можно с места в карьер, но...
Нужно сначала один раз нормально разобраться и настроить.
Тема по умолчанию - это черновик, который будет добавлять 3 тестовых поста из themesdefaultcontent
и в целом просит кирпича напильника.
Поэтому идём в репозиторий тем и выбираем что-нибудь покавайнее под наши нужды. Мне, например, понравилась m10c.
git clone https://github.com/vaga/hugo-theme-m10c.git themes/m10c
echo "theme = 'm10c'" >> hugo.toml
Новые посты по умолчанию генерятся в директории content из шаблона сохранённого в archetypes, но не забывайте прописывать формат файла, иначе получите ошибку
> hugo new content postsmy-first-post
Error: failed to resolve "posts\my-first-post" to an archetype template
> hugo new content postsmy-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-blogcontentpostsarticle.md
будет сгенерена в my-blogpublicpostsarticleindex.html
И раз у нас всё равно под каждую статью генерится директория, чтобы избегать путаницы, я предпочитаю сразу все посты именовать в формате contentpostsYYYYMMDD-article-nameindex.md
и всякие скрины и аттачи к ним складывать в директорию к статье.
Т.е. новая статья будет генериться как-то так
hugo new content posts2024-08-24-blog-like-a-freakindex.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
игнорируется. Если нас такое поведение страниц со списками сайтов не устраивает, можно в m10clayouts_defaultlist.html
добавить секцию {{ .Content }}
после заголовка. Если же мы хотим ещё больше кастомизации, то создаём themesm10clayouts_defaulthome.html
с кастомизацией для корневой страницы. Для примера можно взять копию файла из дефолтной темы
{{ define "main" }}
{{ .Content }}
{{ range site.RegularPages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ .Summary }}
{{ end }}
{{ end }}
Теперь на странице будет присутствовать вводный текст, а уже после него будут перечисляться посты блога с кратким содержимым. Но возможно удобнее будет, например, отображать основные секции
{{ range .Site.Sections }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ 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 собирал новую версию статики и публиковал её. Что мы и запишем в .githubworkflowshugo.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 belowFolder 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 postswhatever.md
или всё-таки за шаблон будет отвечать Obsidian и тогда прописываем пути к шаблонам.
Вообще хорошо бы поставить какой-нибудь более продвинутый плагин с шаблонами, чтобы генерить сразу в нужную директорию, но хотя бы минимально из коробки можно настроить
Core plugins - Daily notes
New file location
= content/postsTemplate 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.
Автор: ritorichesky_echpochmak