[{"content":"","date":"30 March 2026","externalUrl":null,"permalink":"/","section":"Erik Tóth","summary":"","title":"Erik Tóth","type":"page"},{"content":" TL;DR # If you just want to use it, follow the README.md instructions in the repository.\nerik-toth/hugo-auto-deployer Docker compose for an automated hugo static website generator setup. Shell 0 0 What for? # Creating a website and adding new content to it should be an easy and straightforward process. So just automate it, right? I searched the web for already available pipeline setups but couldn\u0026rsquo;t find anything that fit my needs. This was the perfect opportunity to learn about Docker, webhooks, and of course Hugo.\nLet\u0026rsquo;s make it happen # As a hobbyist in programming and other technical fields, I like to keep everything under version control. If something goes wrong or doesn\u0026rsquo;t work the way I want it to, I can simply revert to an earlier version. Also, documenting with Markdown files is an easy way to get \u0026ldquo;pretty\u0026rdquo; formatting.\nThe classic approach is to use something like WordPress, but that uses a lot of unnecessary resources for a static website. So I discovered Hugo, which is a static site generator from Markdown, exactly what I was looking for! Text-based files are great for version control with Git.\nThe plan # flowchart TB A[\"Git Push\"] --\u003e X[\"Remote\\nGit Server\"] X --\u003e B[\"POST Webhook\"] C \u003c-. secret .-\u003e B D \u003c-. Deploy Key .-\u003e X B -- on push--\u003e C[\"Webhook\"] subgraph \" \" C --\u003e D[\"Git fetch/pull\"] D --\u003e E[\"Build hugo\\nstatic files\"] end E --\u003e F[\"Serve static files\"] It\u0026rsquo;s coming to life # I want to work with Docker because I think it is the easiest way to set up the whole pipeline. I’m using docker-compose because I want the deployer (webhook, Hugo build, and Git fetch/pull) and the web server to run in separate containers.\nProject structurehugo-auto-deployer ├── docker-compose.yml ├── deployer │ ├── Dockerfile │ ├── deploy.sh │ ├── entrypoint.sh │ └── hooks.json.tpl ├── .env └── nginx └── nginx.conf docker-compose.yml 1services: 2 3 ssh-init: 4 image: alpine:latest 5 container_name: hugo-ssh-init 6 volumes: 7 - ssh-keys:/root/.ssh 8 command: \u0026gt; 9 sh -c \u0026#34; 10 apk add --no-cache openssh-keygen \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u0026amp;\u0026amp; 11 mkdir -p /root/.ssh \u0026amp;\u0026amp; 12 chmod 700 /root/.ssh \u0026amp;\u0026amp; 13 if [ ! -f /root/.ssh/id_ed25519 ]; then 14 ssh-keygen -t ed25519 -C \u0026#39;hugo-deployer\u0026#39; -f /root/.ssh/id_ed25519 -N \u0026#39;\u0026#39; \u0026amp;\u0026amp; 15 chmod 600 /root/.ssh/id_ed25519 \u0026amp;\u0026amp; 16 chmod 644 /root/.ssh/id_ed25519.pub \u0026amp;\u0026amp; 17 echo \u0026#39;\u0026#39; \u0026amp;\u0026amp; 18 echo \u0026#39;════════════════════════════════════════════════════════\u0026#39; \u0026amp;\u0026amp; 19 echo \u0026#39; Generated SSH deploy key.\u0026#39; \u0026amp;\u0026amp; 20 echo \u0026#39; Please add following public key:\u0026#39; \u0026amp;\u0026amp; 21 echo \u0026#39;════════════════════════════════════════════════════════\u0026#39; \u0026amp;\u0026amp; 22 cat /root/.ssh/id_ed25519.pub \u0026amp;\u0026amp; 23 echo \u0026#39;════════════════════════════════════════════════════════\u0026#39; 24 else 25 echo \u0026#39;SSH Key already present. Skip generating. Public Key:\u0026#39; \u0026amp;\u0026amp; 26 cat /root/.ssh/id_ed25519.pub 27 fi 28 \u0026#34; 29 restart: \u0026#34;no\u0026#34; 30 31 deployer: 32 build: 33 context: ./deployer 34 args: 35 HUGO_VERSION: ${HUGO_VERSION:-0.159.1} 36 container_name: hugo-deployer 37 restart: unless-stopped 38 depends_on: 39 ssh-init: 40 condition: service_completed_successfully 41 environment: 42 GIT_REPO_URL: ${GIT_REPO_URL} 43 GIT_BRANCH: ${GIT_BRANCH:-main} 44 WEBHOOK_SECRET: ${WEBHOOK_SECRET} 45 HUGO_EXTRA_FLAGS: ${HUGO_EXTRA_FLAGS:-} 46 TZ: ${TZ:-Europe/Vienna} 47 48 volumes: 49 - ssh-keys:/root/.ssh 50 - hugo-public:/public 51 52 ports: 53 - \u0026#34;${WEBHOOK_PORT:-9000}:9000\u0026#34; 54 networks: 55 - internal 56 57 nginx: 58 image: nginx:alpine 59 container_name: hugo-nginx 60 restart: unless-stopped 61 volumes: 62 - hugo-public:/usr/share/nginx/html:ro 63 - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:rw 64 ports: 65 - \u0026#34;${HTTP_PORT:-80}:80\u0026#34; 66 networks: 67 - internal 68 depends_on: 69 - deployer 70 healthcheck: 71 test: [\u0026#34;CMD-SHELL\u0026#34;, \u0026#34;wget -qSO/dev/null http://127.0.0.1/ 2\u0026gt;\u0026amp;1 | grep -q \u0026#39;HTTP/\u0026#39; || exit 1\u0026#34;] 72 interval: 30s 73 timeout: 5s 74 retries: 3 75 start_period: 15s 76 77volumes: 78 hugo-public: 79 driver: local 80 ssh-keys: 81 driver: local 82 83networks: 84 internal: 85 driver: bridge I created three services ( = containers): ssh-init, deployerand nginx. The ssh-container is only used once at startup and gets shutdown afterwards. It is needed to configure the ssh-key for fetching/pulling the git repo. The container generates a (public) ssh-key that can be copied from the log file. Brains of the whole pipeline is the deployer-container, which is a custom container. Its functions and operations are going to be discussed later. The ssh-container and deployer share a common volume to exchange the ssh-keys. And at last there is the webserver running on nginx. It shares a volume with the deployer-container in which the web-page files are contained.\nDockerfile 1FROM alpine:latest 2 3ARG HUGO_VERSION=0.159.1 4 5RUN apk add --no-cache \\ 6 git \\ 7 openssh-client \\ 8 ca-certificates \\ 9 wget \\ 10 tar \\ 11 gettext \\ 12 su-exec \\ 13 tzdata \\ 14 webhook \\ 15 gcompat \\ 16 libstdc++ 17 18ENV TZ=Europe/Vienna 19 20RUN ARCH=$(uname -m) \u0026amp;\u0026amp; \\ 21 case \u0026#34;$ARCH\u0026#34; in \\ 22 x86_64) HUGO_ARCH=\u0026#34;amd64\u0026#34; ;; \\ 23 aarch64) HUGO_ARCH=\u0026#34;arm64\u0026#34; ;; \\ 24 armv7l) HUGO_ARCH=\u0026#34;arm\u0026#34; ;; \\ 25 *) echo \u0026#34;Unsupported arch: $ARCH\u0026#34; \u0026amp;\u0026amp; exit 1 ;; \\ 26 esac \u0026amp;\u0026amp; \\ 27 URL=\u0026#34;https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${HUGO_ARCH}.tar.gz\u0026#34; \u0026amp;\u0026amp; \\ 28 echo \u0026#34;Downloading Hugo ${HUGO_VERSION} from: ${URL}\u0026#34; \u0026amp;\u0026amp; \\ 29 wget -O /tmp/hugo.tar.gz \u0026#34;${URL}\u0026#34; \\ 30 || { echo \u0026#34;ERROR: Hugo-Download\u0026#34;; exit 1; } \u0026amp;\u0026amp; \\ 31 mkdir -p /tmp/hugo-extract \u0026amp;\u0026amp; \\ 32 tar -xzf /tmp/hugo.tar.gz -C /tmp/hugo-extract \u0026amp;\u0026amp; \\ 33 ls -la /tmp/hugo-extract/ \u0026amp;\u0026amp; \\ 34 HUGO_BIN=$(find /tmp/hugo-extract -type f -name \u0026#39;hugo\u0026#39; | head -1) \u0026amp;\u0026amp; \\ 35 [ -n \u0026#34;$HUGO_BIN\u0026#34; ] || { echo \u0026#34;ERROR: hugo-Binary not in archive\u0026#34;; exit 1; } \u0026amp;\u0026amp; \\ 36 mv \u0026#34;$HUGO_BIN\u0026#34; /usr/local/bin/hugo \u0026amp;\u0026amp; \\ 37 chmod +x /usr/local/bin/hugo \u0026amp;\u0026amp; \\ 38 rm -rf /tmp/hugo.tar.gz /tmp/hugo-extract \u0026amp;\u0026amp; \\ 39 hugo version 40 41RUN webhook --version \u0026amp;\u0026amp; hugo version 42 43WORKDIR /app 44 45COPY hooks.json.tpl /app/hooks.json.tpl 46COPY deploy.sh /app/deploy.sh 47COPY entrypoint.sh /app/entrypoint.sh 48 49RUN chmod +x /app/deploy.sh /app/entrypoint.sh 50 51RUN mkdir -p /public /app/repo 52 53EXPOSE 9000 54 55ENTRYPOINT [\u0026#34;/app/entrypoint.sh\u0026#34;] I built on top of the commonly used image alpine, a very lightweight linux distro. First we install all needed packages. Next we pull the prebuilt binary for hugo. After that a quick check if webhook and hugo a correctly installed. Then the pre-written scripts and template get copied.\nentrypoint.sh 1#!/bin/sh 2set -eu 3 4LOG_PREFIX=\u0026#34;[entrypoint]\u0026#34; 5log() { echo \u0026#34;${LOG_PREFIX} $*\u0026#34;; } 6 7: \u0026#34;${GIT_REPO_URL:? ERROR: GIT_REPO_URL not set (SSH-Format: git@host:user/repo.git)}\u0026#34; 8: \u0026#34;${WEBHOOK_SECRET:? ERROR: WEBHOOK_SECRET not set}\u0026#34; 9: \u0026#34;${GIT_BRANCH:=main}\u0026#34; 10 11if [ ! -f /root/.ssh/id_ed25519 ]; then 12 echo \u0026#34;\u0026#34; 13 echo \u0026#34; ╔═════════════════════════════╗\u0026#34; 14 echo \u0026#34; ║ ERROR: SSH-Key not found! ║\u0026#34; 15 echo \u0026#34; ╚═════════════════════════════╝\u0026#34; 16 echo \u0026#34;\u0026#34; 17 exit 1 18fi 19 20chmod 600 /root/.ssh/id_ed25519 21log \u0026#34;SSH-Key found: /root/.ssh/id_ed25519\u0026#34; 22 23log \u0026#34;Generating hooks.json from template...\u0026#34; 24export GIT_BRANCH WEBHOOK_SECRET 25envsubst \u0026#39;${WEBHOOK_SECRET} ${GIT_BRANCH}\u0026#39; \\ 26 \u0026lt; /app/hooks.json.tpl \\ 27 \u0026gt; /app/hooks.json 28 29log \u0026#34;hooks.json done.\u0026#34; 30 31log \u0026#34;Initating first deploy...\u0026#34; 32/app/deploy.sh || { 33 log \u0026#34;WARN: Error during first deploy. Webhook-listener will still start.\u0026#34; 34} 35 36log \u0026#34;Webhook-Endpoint: POST /hooks/hugo-deploy\u0026#34; 37 38exec webhook \\ 39 -hooks /app/hooks.json \\ 40 -port 9000 \\ 41 -ip 0.0.0.0 \\ 42 -verbose \\ 43 -hotreload A simple entrypoint script that checks for the ssh-key and sets the rigths. It also starts the webhook.\ndeploy.sh 1#!/bin/sh 2set -euo pipefail 3 4REPO_DIR=\u0026#34;/app/repo\u0026#34; 5PUBLIC_DIR=\u0026#34;/public\u0026#34; 6SSH_KEY=\u0026#34;/root/.ssh/id_ed25519\u0026#34; 7LOG_PREFIX=\u0026#34;[hugo-deployer]\u0026#34; 8 9log() { echo \u0026#34;${LOG_PREFIX} $(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;) INFO $*\u0026#34;; } 10warn() { echo \u0026#34;${LOG_PREFIX} $(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;) WARN $*\u0026#34; \u0026gt;\u0026amp;2; } 11err() { echo \u0026#34;${LOG_PREFIX} $(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;) ERROR $*\u0026#34; \u0026gt;\u0026amp;2; exit 1; } 12 13: \u0026#34;${GIT_REPO_URL:?GIT_REPO_URL must be set (SSH-Format: git@host:user/repo.git)}\u0026#34; 14: \u0026#34;${GIT_BRANCH:=main}\u0026#34; 15 16[ -f \u0026#34;$SSH_KEY\u0026#34; ] || err \u0026#34;SSH-Key not found: $SSH_KEY.\u0026#34; 17 18chmod 600 \u0026#34;$SSH_KEY\u0026#34; 19 20if [ -f /root/.ssh/known_hosts ]; then 21 log \u0026#34;known_hosts found\u0026#34; 22 export GIT_SSH_COMMAND=\u0026#34;ssh -i ${SSH_KEY} -o StrictHostKeyChecking=yes -o BatchMode=yes\u0026#34; 23else 24 warn \u0026#34;No known_hosts\u0026#34; 25 export GIT_SSH_COMMAND=\u0026#34;ssh -i ${SSH_KEY} -o StrictHostKeyChecking=accept-new -o BatchMode=yes\u0026#34; 26fi 27 28log \u0026#34;GIT_SSH_COMMAND: $GIT_SSH_COMMAND\u0026#34; 29 30if [ -d \u0026#34;${REPO_DIR}/.git\u0026#34; ]; then 31 log \u0026#34;Repository already cloned... fetching instead\u0026#34; 32 cd \u0026#34;$REPO_DIR\u0026#34; 33 34 git fetch origin \u0026#34;${GIT_BRANCH}\u0026#34; 35 git checkout \u0026#34;${GIT_BRANCH}\u0026#34; 36 git reset --hard \u0026#34;origin/${GIT_BRANCH}\u0026#34; 37 git submodule update --init --recursive 38 39 log \u0026#34;Sync done. Current commit: $(git log -1 --oneline)\u0026#34; 40else 41 log \u0026#34;Cloning ${GIT_REPO_URL} (Branch: ${GIT_BRANCH})...\u0026#34; 42 git clone \\ 43 --branch \u0026#34;${GIT_BRANCH}\u0026#34; \\ 44 --depth 1 \\ 45 --recurse-submodules \\ 46 \u0026#34;${GIT_REPO_URL}\u0026#34; \\ 47 \u0026#34;${REPO_DIR}\u0026#34; 48 49 log \u0026#34;Clone done. Current commit: $(git -C \u0026#34;${REPO_DIR}\u0026#34; log -1 --oneline)\u0026#34; 50fi 51 52cd \u0026#34;$REPO_DIR\u0026#34; 53 54log \u0026#34;Starting hugo-build...\u0026#34; 55 56mkdir -p data 57 58HASH=$(git rev-parse HEAD) 59AUTHOR=$(git log -1 --format=\u0026#34;%an\u0026#34;) 60DATE=$(git log -1 --format=\u0026#34;%ad\u0026#34; --date=format:\u0026#34;%d.%m.%Y %H:%M:%S\u0026#34;) 61SUBJECT=$(git log -1 --format=\u0026#34;%s\u0026#34;) 62 63cat \u0026lt;\u0026lt;EOF \u0026gt; data/build_info.json 64{ 65 \u0026#34;hash\u0026#34;: \u0026#34;$HASH\u0026#34;, 66 \u0026#34;author\u0026#34;: \u0026#34;$AUTHOR\u0026#34;, 67 \u0026#34;date\u0026#34;: \u0026#34;$DATE\u0026#34;, 68 \u0026#34;subject\u0026#34;: \u0026#34;$SUBJECT\u0026#34; 69} 70EOF 71 72log \u0026#34;Build info generated: ${HASH}\u0026#34; 73 74 75# shellcheck disable=SC2086 76hugo \\ 77 --destination \u0026#34;${PUBLIC_DIR}\u0026#34; \\ 78 --cleanDestinationDir \\ 79 ${HUGO_EXTRA_FLAGS:-} 80 81log \u0026#34;Hugo-Build done.\u0026#34; 82log \u0026#34;Stored in ${PUBLIC_DIR}:\u0026#34; 83find \u0026#34;$PUBLIC_DIR\u0026#34; -maxdepth 2 -type f | head -30 The deploy script executes git fetch/pull, generate build info (page) and build hugo files.\nhooks.json.tpl 1[ 2 { 3 \u0026#34;id\u0026#34;: \u0026#34;hugo-deploy\u0026#34;, 4 \u0026#34;execute-command\u0026#34;: \u0026#34;/app/deploy.sh\u0026#34;, 5 \u0026#34;command-working-directory\u0026#34;: \u0026#34;/app\u0026#34;, 6 \u0026#34;response-message\u0026#34;: \u0026#34;Deploy triggered\u0026#34;, 7 \u0026#34;response-headers\u0026#34;: [ 8 { \u0026#34;name\u0026#34;: \u0026#34;Content-Type\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;text/plain; charset=utf-8\u0026#34; } 9 ], 10 11 \u0026#34;pass-environment-to-command\u0026#34;: [ 12 { \u0026#34;source\u0026#34;: \u0026#34;entire-payload\u0026#34;, \u0026#34;envname\u0026#34;: \u0026#34;WEBHOOK_PAYLOAD\u0026#34; }, 13 { \u0026#34;source\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;X-GitHub-Event\u0026#34;, \u0026#34;envname\u0026#34;: \u0026#34;GIT_EVENT\u0026#34; }, 14 { \u0026#34;source\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;X-Gitlab-Event\u0026#34;, \u0026#34;envname\u0026#34;: \u0026#34;GITLAB_EVENT\u0026#34; } 15 ], 16 17 \u0026#34;trigger-rule\u0026#34;: { 18 \u0026#34;and\u0026#34;: [ 19 { 20 \u0026#34;match\u0026#34;: { 21 \u0026#34;type\u0026#34;: \u0026#34;payload-hmac-sha256\u0026#34;, 22 \u0026#34;secret\u0026#34;: \u0026#34;${WEBHOOK_SECRET}\u0026#34;, 23 \u0026#34;parameter\u0026#34;: { 24 \u0026#34;source\u0026#34;: \u0026#34;header\u0026#34;, 25 \u0026#34;name\u0026#34;: \u0026#34;X-Hub-Signature-256\u0026#34; 26 } 27 } 28 }, 29 { 30 \u0026#34;or\u0026#34;: [ 31 { 32 \u0026#34;match\u0026#34;: { 33 \u0026#34;type\u0026#34;: \u0026#34;value\u0026#34;, 34 \u0026#34;value\u0026#34;: \u0026#34;refs/heads/${GIT_BRANCH}\u0026#34;, 35 \u0026#34;parameter\u0026#34;: { \u0026#34;source\u0026#34;: \u0026#34;payload\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;ref\u0026#34; } 36 } 37 }, 38 { 39 \u0026#34;match\u0026#34;: { 40 \u0026#34;type\u0026#34;: \u0026#34;value\u0026#34;, 41 \u0026#34;value\u0026#34;: \u0026#34;${GIT_BRANCH}\u0026#34;, 42 \u0026#34;parameter\u0026#34;: { \u0026#34;source\u0026#34;: \u0026#34;payload\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;ref\u0026#34; } 43 } 44 } 45 ] 46 } 47 ] 48 } 49 }, 50 51 { 52 \u0026#34;id\u0026#34;: \u0026#34;hugo-deploy-gitlab\u0026#34;, 53 \u0026#34;execute-command\u0026#34;: \u0026#34;/app/deploy.sh\u0026#34;, 54 \u0026#34;command-working-directory\u0026#34;: \u0026#34;/app\u0026#34;, 55 \u0026#34;response-message\u0026#34;: \u0026#34;GitLab Deploy triggered.\u0026#34;, 56 \u0026#34;response-headers\u0026#34;: [ 57 { \u0026#34;name\u0026#34;: \u0026#34;Content-Type\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;text/plain; charset=utf-8\u0026#34; } 58 ], 59 60 \u0026#34;pass-environment-to-command\u0026#34;: [ 61 { \u0026#34;source\u0026#34;: \u0026#34;entire-payload\u0026#34;, \u0026#34;envname\u0026#34;: \u0026#34;WEBHOOK_PAYLOAD\u0026#34; }, 62 { \u0026#34;source\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;X-Gitlab-Event\u0026#34;, \u0026#34;envname\u0026#34;: \u0026#34;GITLAB_EVENT\u0026#34; } 63 ], 64 65 \u0026#34;trigger-rule\u0026#34;: { 66 \u0026#34;and\u0026#34;: [ 67 { 68 \u0026#34;match\u0026#34;: { 69 \u0026#34;type\u0026#34;: \u0026#34;value\u0026#34;, 70 \u0026#34;value\u0026#34;: \u0026#34;${WEBHOOK_SECRET}\u0026#34;, 71 \u0026#34;parameter\u0026#34;: { \u0026#34;source\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;X-Gitlab-Token\u0026#34; } 72 } 73 }, 74 { 75 \u0026#34;match\u0026#34;: { 76 \u0026#34;type\u0026#34;: \u0026#34;value\u0026#34;, 77 \u0026#34;value\u0026#34;: \u0026#34;refs/heads/${GIT_BRANCH}\u0026#34;, 78 \u0026#34;parameter\u0026#34;: { \u0026#34;source\u0026#34;: \u0026#34;payload\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;ref\u0026#34; } 79 } 80 } 81 ] 82 } 83 } 84] Here is an example for your .env file:\n.env 1# git config 2GIT_REPO_URL=git@git.example.com:user/repo.git 3GIT_BRANCH=main 4 5# generate with: openssl rand -hex 32 6WEBHOOK_SECRET=paste_your_32_char_long_secret_here 7WEBHOOK_PORT=9000 8 9# hugo config (versions: https://github.com/gohugoio/hugo/releases) 10HUGO_EXTRA_FLAGS=--minify 11HUGO_VERSION=0.159.1 12 13# web server port 14HTTP_PORT=8091 15 16# timezone 17TZ=Your/Timezone Finishing up # After your setup is finished, it\u0026rsquo;s about time to copy over the public ssh-key and webhook secret to your git server. Make sure your webhook is reachable from outside (the internet\u0026hellip;) and maybe put a proxy server between for security reasons. Setting up the deploy key basically works the same on all platforms (github, gitlab, gitea, forgejo):\nOpen the repo settings Open the tab \u0026ldquo;Deploy Keys\u0026rdquo; Add deploy key: paste the public ssh-key here Done The webhook service can be added in a similar manner:\nOpen the repo settings Open the tab \u0026ldquo;Webhooks\u0026rdquo; Add Webhook: paste https://your.domain/hooks/hugo-deploy Check option \u0026ldquo;on push\u0026rdquo; Done ","date":"30 March 2026","externalUrl":null,"permalink":"/blog/hugo-cicd-pipeline/","section":"Blog","summary":"","title":"Hugo CI/CD Pipeline","type":"blog"},{"content":"","date":"29 March 2026","externalUrl":null,"permalink":"/blog/","section":"Blog","summary":"","title":"Blog","type":"blog"},{"content":"","date":"29 March 2026","externalUrl":null,"permalink":"/build-info/","section":"Erik Tóth","summary":"","title":"Build Info","type":"page"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"}]