How This Blog Works in 2026

Published: (February 13, 2026 at 12:08 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Overview

Back in 2019 I wrote about how this blog works. A lot has changed since then — automated deploys, dev.to sync, AI‑generated tweets. Time for an update.

Tech Stack

  • Grav CMS – flat‑file, PHP 8.2, Markdown, no database.
  • Deployer 7.3 – handles the actual deploy (symlink strategy, shared dirs for cache, automatic cleanup of old releases).
  • GitLab CI – orchestrates the whole pipeline.

Theme

The blog theme extends Quark and adds custom styles: alternating white/gray section backgrounds, a tag cloud with CSS custom properties, and article cards. All JavaScript is pure vanilla.

Bilingual Setup

The site is bilingual – Czech (*.cs.md) and English (*.en.md). Every article has both files side by side.

Deployment Pipeline

# .gitlab-ci.yml (excerpt)
stages:
  - build
  - deploy

build_image:
  stage: build
  script:
    - docker build -t myblog:ci -f Dockerfile.ci .
  only:
    changes:
      - Dockerfile.ci

deploy:
  stage: deploy
  script:
    - dep deploy
  only:
    - master
  • Push to master triggers the pipeline.
  • Build image – Docker image with PHP 8.2 and Deployer (only when Dockerfile.ci changes).
  • Deploydep deploy over SSH to biberle.cz.

The SSH key is stored as a base64 CI variable, decoded at runtime. The entire deploy is fully automatic.

dev.to Synchronization

  • Export: English articles are automatically published to dev.to.

    • A sync script scans all English articles, matches them against existing dev.to posts via canonical_url, and creates or updates as needed.
    • Stateless – the canonical URL serves as the key.
    • Runs in CI after every deploy and on a schedule (for future‑dated articles that become publishable).
  • Import: dev.to articles can be imported back into the local blog, downloading cover images and setting canonical_url back to the blog.

Twitter Automation

When a new article goes live, it is automatically tweeted. The tweet text is generated by OpenAI (gpt‑4o‑mini) following a writing‑style guide.

Process

  1. Scan all English articles.
  2. Skip already‑tweeted articles (tracked list).
  3. For new articles, send the title, excerpt, and tags to OpenAI.
  4. OpenAI returns a tweet (max 250 chars) matching the author’s tone.
  5. Post the tweet via Twitter API v2 with OAuth 1.0a.
  6. Record the article URL and commit the update back to Git.

The style guide lives in a single file, providing a single source of truth for both the AI and the author. Tweets are sent only on weekdays at 09:00 AM (Europe/Prague) via a separate GitLab CI schedule with the TWITTER_POST=true variable.

Things That Remain Unchanged

  • Grav remains perfect for a personal blog – fast, simple, minimal maintenance.
  • Markdown + Git continues to be the best workflow for writing technical articles.
  • Deployer does exactly what it should and nothing more.
  • Umami analytics replaces Google Analytics (the template placeholder is already there).
  • Better cover images for articles.

Future Ideas

  • Add an RSS feed for Czech articles.

Automation is great, but it’s useless without articles. So, write more.

0 views
Back to Blog

Related posts

Read more »