blurt#
You want to write something and share it with the world. But you'd need to set up a blog. Woe! Who has the time?
Hold up there, sunshine. Blurt's got your back. This is everything you really need to write and publish stuff on the internet.
Note: Code was written primarily by AI because I'm not nuts enough to maintain a shell script of this complexity.
Quick start#
- Create a repo from this template
- On your repo, go to settings -> Pages -> Source: select GitHub Actions
- Clone your repo
Now just write your posts (see docs below), commit and push. After a short while, your repo should have a deployment (check the right side).
That's it!
Requirements#
- pandoc - for the actual heavy lifting
- ImageMagick (optional) - for OpenGraph image generation
- python3 (optional) - for the dev server (
startcommand) - fswatch (optional) - for instant rebuilds during development
- curl or wget (optional) - for self-updating
Docker#
A Docker image is available at shkm/blurt:
docker run --rm -v $(pwd):/repo shkm/blurt
Usage#
# Create a new post
./blurt new "My Post Title"
# Create and open in $EDITOR
./blurt new -e "My Post Title"
# Build the site
./blurt build
# Watch, rebuild, and serve at http://localhost:8000
./blurt start
# Update to the latest version
./blurt update
# Show version
./blurt version
Structure#
โโโ blurt # CLI
โโโ config.yaml # Settings
โโโ templates/
โ โโโ index.html # Index page template
โ โโโ post.html # Post page template
โ โโโ social.html # OpenGraph/social meta tags partial
โ โโโ *.html # Other partials (optional)
โโโ static/ # Static files (copied to dist/)
โโโ posts/ # Markdown posts
โโโ dist/ # Generated site
Templates#
Templates use pandoc's variable syntax:
$blog_title$- from config.yaml$title$- post title from frontmatter$date$- post date from frontmatter$body$- converted markdown content
Partials#
You can create reusable template snippets in templates/. For example, templates/footer.html can be included in other templates with $footer()$.
Placeholders#
The following placeholders are replaced at build time:
__BUILD_TIME__- Time taken to build that specific page (e.g.,42ms)__COMMIT_SHA__- Short git commit hash, usesGITHUB_SHAenv var if available__BLURT_VERSION__- Blurt version number (e.g.,1.0.1)
Example usage in a template:
<footer>
<p>
Built in __BUILD_TIME__ ยท
<a href="https://github.com/you/repo/commit/__COMMIT_SHA__"
>__COMMIT_SHA__</a
>
</p>
</footer>
Posts#
Posts are markdown files with YAML frontmatter:
---
title: My Post Title
date: 2026-01-13
---
Post content here.
Output goes to dist/my-post-title/index.html for clean URLs.
Atom Feed#
An Atom feed is automatically generated at dist/feed.xml when site_url is configured in config.yaml. The feed includes the full HTML content of each post.
Required config:
site_url: "https://example.com"
Optional config for the feed:
site_title: "My Blog"
site_author: "Your Name"
Favicon#
A favicon is automatically generated at dist/favicon.svg using your site title initials. It uses the social_highlight color as the background and requires the Open Sans font.
OpenGraph Images#
When ImageMagick is installed, blurt automatically generates OpenGraph images for social sharing. Requires the Open Sans font to be installed. Images are created at:
dist/og.jpg- for the index pagedist/<post>/og.jpg- for each post
Images display:
- Site URL (top-left)
- Date (top-right, posts only)
- Title (bottom-left)
Highlight Color#
Both the favicon and OpenGraph images use a configurable highlight color. Set it in config.yaml:
social_highlight: "#3b82f6" # Any hex color
The social.html partial includes all necessary meta tags for OpenGraph and Twitter cards.