I'm blogging about Emacs, Drupal, php and exciting subjects
The service account this site's automated pipeline runs under, api_publisher, is a small role: a handful of permissions in a YAML file, tracked in sync/ like every other piece of this site's configuration. Reading that file today tells you what it can do.
Ad placements on this site had started looking wrong — not broken, just not deliberate: spots that clearly weren't ones I remembered choosing. My first assumption was that some old ad unit had been dropped into a template years ago and half-forgotten, so I went looking for it in the theme. There's exactly one ad-related line in the entire theme, and it isn't a placement at all:
This site's article pipeline runs unattended from a wrapper shell script, invoking a claude -p session wrapped in timeout to draft and schedule posts. One run, I decided partway through that I didn't like the direction it was taking and killed it — kill <wrapper-pid>, the process I could see in my terminal.
This site runs on a Europe/Warsaw system clock, and its automated article pipeline needed to compute a publish-time window in UTC from a plain local-time string like "2026-08-31 16:00". The obvious tool is GNU date's -u flag, which converts to UTC — except it doesn't do what that sentence implies.
Look at the "created" date on a handful of consecutive articles from this site's automated pipeline, and you'd expect them to be scattered across a day — that's the whole point of scheduling posts hours apart instead of dumping them all at once. For three articles published during one run, they weren't.
This site's automated publishing pipeline runs under a scoped account, api_publisher, that has no permission to touch a node's status field. That's deliberate: a hook_node_presave() in this site's custom module forces any new node owned by that role unpublished, no matter what the content type's default says or what the API client asked for:
I had exactly four URLs I wanted redirected. Two articles had accidentally been published twice in July under different titles — a mixup during the early days of the JSON:API publishing pipeline — and once I'd settled on which copy of each to keep, the other needed to 301 somewhere instead of just disappearing. Four source paths, four targets, done.
No human being reads this site's sitemap.xml. It exists entirely for crawlers, gets zero direct visits worth counting, and if it silently broke tomorrow the only symptom would be a slow decline in indexing over weeks, with nothing in the site's own analytics pointing at the cause.
This site runs on a VPS that also runs two other things I don't think about most days: carmen-crm.net and fasterwebsites.net, neither of which has anything to do with linkhub.
The composer.json diff for the Drupal 10 to 11 upgrade on this site is thirteen lines: a handful of version constraints bumped, doctrine/annotations added back, symfony/runtime allow-listed. The composer.lock diff for that same commit is 2,109 lines changed — 1,416 insertions, 693 deletions, one file.
Subscribe to Linkhub