title: "Poaster: Solving SSG Microblogging Ergonomics with Ruby and KDialog"
description: "Trying to make it a little less brutal to make small, frequent posts on SSGs."
date: 2025-06-08
tags:
- Site Updates
- Eleventy
- KDE
synopsis: "Trying to make it a little less brutal to make small, frequent posts on SSGs."
imageURL: "/img/poaster/poaster_icon.svg"
imageAlt: "An icon featuring a red toaster with the Ruby diamond on it popping out a sheet with the Markdown logo on it as though it were toast."
mastodon_id: "114650833104413858"
---
Anyone familiar with my blog will know that I like to write about incense. A reader wrote to me some time ago asking about what sticks I've been enjoying lately, and it occurred to me that it might be a nice thing to have a "now listening" type feature on my website, so that fellow incense heads could get a sense of the types of incense I like. After all, while I write plenty of incense reviews, they represent only a small percentage of the sticks, cones, powders, woods, and resins I'm burning or heating from day to day. (If you're here for my incense content, feel free to skip this one and head to [/now-burning](/now-burning) to see the new feature!)
## The issue of ergonomics
While it would have been simple enough for me to build a microblogging feature into my [Eleventy](https://www.11ty.dev/) website, the trouble was *wanting to use it* after it was built. Unlike using a {{ "CMS" | abbr("Content Management System") | safe }} such as WordPress to make a website, I knew of no nice interface for Eleventy, or for that matter any {{ "SSG" | abbr("Static Site Generator") | safe }}, that would help me create a post and publish it online without opening an {{ "IDE" | abbr("Integrated Development Environment") | safe }}[^1] and using the command line. Instead, the process looks something like this:
[ every time I decide to make a tiny status update. Also, I just noticed that I totally screwed up the frontmatter for that post.")](/img/poaster/ergonomics_fail.webp)
As big of a nerd as I am, I'm just not going to want to do that multiple times a day for what amounts to a status post. This lead me to *scour* the internet looking for a solution: something that I could run on my own desktop or laptop that could build my site locally and push changes to my website, hosted the old fashioned way: as a bunch of text files sitting on a server accessible via {{ "SFTP" | abbr("SSH File Transfer Protocol") | safe }}. No needless complexity like running Eleventy on the server, or using a host like Netlify.[^2] Surely there'd be something, right? Surely, the realm of SSGs can't be without at least one nice, local user interface that people can use without being a web developer?
## An attempt to fix the problem
In the end, I did find one answer to the problem: [Publii](https://getpublii.com/). Publii seems to be made predominantly with end-users in mind, however. It's not just a local[^3] CMS, it's an SSG in its own right, which does me no good as I can't make it work with my website[^4]. So after coming up with nothing *I* could use, I gave the idea a rest for a while until I had the epiphany that I could solve the problem with a simple script using KDE's [KDialog](https://invent.kde.org/utilities/kdialog) to provide a rudimentary UI. So that's what I did.
The idea was simple: a [wizard](https://en.wikipedia.org/wiki/Wizard_(software))-like experience that guides the user through the creation of a microblog / status post. Post types and the data they collect should be customized by the user via a JSON configuration file. After the post data is collected from the user, the script should execute a user-defined build command as well as a user-defined command to sync the static files to the server.
## Building "Poaster"
For some reason, I decided to write my script in Ruby, a language for which I once completed a course before promptly forgetting everything I knew about it. I would have had a much easier time using JavaScript and Node, which I am much more familiar with and have successfully used for similar purposes. Why I did not is anyone's guess. All this to say: please do not make (too much) fun of my shitty little script, which I have dubbed "Poaster."
I started with the JSON configuration file, `/Poaster/config/config.json`:
Here, the user can specify as many post types as they like, each with their own output directory. Each post type can also collect as many pieces of frontmatter as the user cares to specify.
The first thing the script needed to do was ask the user which post type they want to create, so I referenced the [KDialog tutorial](https://develop.kde.org/docs/administration/kdialog/) and wrote a method to handle that `/Poaster/lib/spawn_radio_list.rb`:
There is a lot that this script should do that it doesn't, but for now, it's still a handy wee utility for SSG users on GNU/Linux systems running KDE who want to make creating quick status-type posts a little less painful. Just make sure KDialog is installed (as well as Ruby, naturally), clone [the repo](https://upchur.ch/gitea/n_u/Poaster), create `/Poaster/config/config.json` to meet your needs using the example as a reference and you're off to the races! I've even made a silly little toaster icon using assets from some of the KDE MimeType icons that you can use if you want to make a `.desktop` file so that you can click an icon on your app launcher to start the script.
[](/img/poaster/app-menu.webp)
My `poaster.desktop` file looks something like this:
``` bash
[Desktop Entry]
Exec=/path/to/poaster.rb
GenericName[en_US]=Create a post with Poaster.
GenericName=Create a post with Poaster.
Icon=/path/to/poaster_icon.svg
Name=Poaster
NoDisplay=false
Path=/path/to/repo/
StartupNotify=true
Terminal=false
Type=Application
```
Here's the script in action:
<figure><div style="position: relative;"><iframe title="A video showing Poaster being launched from the terminal. The script brings up a series of text input boxes for each piece of frontmatter specified in the configuration file." width="560" height="315" src="https://makertube.net/videos/embed/p8oopZXaLNUXNpBQGY9q4k" frameborder="0" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe></div><figcaption>The ease! The convenience!</figcaption></figure>
To build the new "now burning" incense microblog feature, I created two new pages. [/now-burning](/now-burning) shows the latest entry:
``` html
---
layout: layouts/base.njk
title: "Nathan Upchurch | Now Burning: What incense I'm burning at the moment."
structuredData: none
postlistHeaderText: "What I've been burning:"
---
{% raw %}{% set burning = collections.nowBurning | last %}
And that's about it! There's a lot to do to make the script a little less fragile, such as passing along build / upload error messages, allowing for data validation via regex, et cetera. I'm sure I'll get to it at some point. If Poaster is useful to you, however, and you'd like to submit a patch to improve it, [please do let me know](../../me/).
[^1]: Yes, I am aware that [Kate](https://kate-editor.org/) isn't *technically*
an IDE.
[^2]: At risk of sounding crabbit and behind the times, I don't know why web
development has to be so damned complicated these days. Like, an entire fancy
for-profit infrastructural platform that exists just to host static websites?
It seems nuts to me.
[^3]: Thank christ. Why does everything need to run in the cloud when we
already have computers at home?
[^4]: I did however use it to very quickly set up a nice looking blog site for
synopsis: "What appears to be a pack of cigarettes labeled 11:11. There is also a card featuring the brand name Boy Vienna and a temporary tattoo featuring an image of a lipstick-print and the brand name."
imageAlt: "What appears to be a pack of cigarettes labeled 11:11. There is also a card featuring the brand name Boy Vienna and a temporary tattoo featuring an image of a lipstick-print and the brand name."
synopsis: "Taking a look at Boy Vienna's viral cigarette incense sticks."
mastodon_id: "114462578542598320"
---
[Boy Vienna](https://boyvienna.com/) is a brand from fashion designer and multi-media artist [Afaf Fi Seyam](https://www.instagram.com/zeopatra) that has been receiving attention on [TikTok](https://www.tiktok.com/@boyvienna/video/7366977382508514603) and [Instagram](https://www.instagram.com/zeopatra/reel/DAyIy2Lv0RQ/) for its incense cigarettes. I knew I was going to have to try these sticks the minute they found their way onto my screen—it would seem that [everyone else felt the same way](https://www.instagram.com/zeopatra/p/DJHP0a3NnlI/), as when I made my way to the web store most of Boy Vienna's incense varieties were sold out. For 35 {{ "USD" | abbr("United States Dollars") | safe }}, I was able to snag a box of the 11:11 variety, listed as containing a blend of sage, lavender, and rosemary.
{% set postsCount = collections.nowBurning | removeMostRecent | length %}
{% if postsCount > 1 %}
{% if postsCount > 0 %}
{% set postslist = collections.nowBurning | removeMostRecent %}
{% set showPostListHeader = false %}
{% include "incenseList.njk" %}
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.