{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreifltrqxxlxtkffmlokhc63cbxzgd6mb7cmfurqv3toykiz3kwruqi",
    "uri": "at://did:plc:uzai4vzxm37suvnjiwfzi63w/app.bsky.feed.post/3m7vrp3hvs5n2"
  },
  "path": "/posts/blog-hacking.html",
  "publishedAt": "2026-04-05T20:52:03.295Z",
  "site": "https://www.terracrypt.net",
  "tags": [
    "guile-horton"
  ],
  "textContent": "Starting December Adventure off with a little meta this year (and a bit late, whoops!). Since setting up this blog, it's always felt like a little too much friction to start a new blog post. It's not _too_ bad, but it does involve creating a file in the `posts` directory with a given name, manually typing out the timestamp.\n\nI'm always writing my blog posts in emacs anyway, and emacs is the most hackable of editors. So I figured, why not have a template to make things easier?\n\nI'm a heavy user of org-capture to quickly add entries to my TODO list. Although my blog posts are markdown rather than org-mode (for now?), org-capture seemed flexible enough to do the job. And sure enough, it was!\n\nIt felt a little gross to do this, but I ended up setting a global variable for the post slug. I tend to use the slug as the filename of each post file, and I didn't want to be prompted for the slug twice. Org-capture can accept a function that controls the file path to capture to; having that function prompt me and save the result seemed like an okay solution.\n\n\n    (defun jfred/capture-blog-post () (interactive) (let ((name (read-string \"Post slug: \"))) (setq jfred-capture-blog--slug name) (expand-file-name (format \"%s.md\" name) \"~/src/website/posts\")))\n\nAfter that, it was a matter of defining a plain org-capture template to start a new file when captured. I'll just show you all my capture templates so you have the new one in context:\n\n\n    (setq org-capture-templates '((\"t\" \"Todo\" entry (file \"~/org/Inbox.org\") \"* TODO %?\\n %a\") (\"tn\" \"Todo - no link\" entry (file \"~/org/inbox.org\") \"* TODO %?\") (\"j\" \"Journal\" entry (file+olp+datetree \"~/org/journal.org\") \"* %?\\nEntered on %U\\n %i\\n %a\") (\"b\" \"Blog post\" plain (file jfred/capture-blog-post) \"title: %^{title} slug: %(format jfred-capture-blog--slug) tags: date: %<%Y-%m-%d %H:%M:%S> --- %?\") (\"m\" \"Meeting Notes\" entry (file+olp+datetree \"~/org/meetings.org\") \"* Meeting Notes - %?\")))\n\n(As an aside, I just realized while looking at these that the `tn` capture doesn't actually work and would be useful. Guess I'll fix that up soon!)\n\nI can tell that the org-capture template system is really meant for templating org files, but it worked here. There's a template string representing a timestamp, but it defaults to the format that org-mode expects; if you want a timestamp in a specific format, you have to use more explicit formatting. But you _can_ do that!\n\nThat's all for today. Today's the first day of my holiday break, so I hope to have more time to work on side projects for the rest of the month. My goal this holiday season is to get guile-horton finally supporting persistence. It's not very useful without it, but I did a few things that were perhaps a bit too clever when originally writing it, so it'll likely be annoyingly complicated to get that working. Fingers crossed!",
  "title": "Hacking on my blogging workflow",
  "updatedAt": "2025-12-13T11:50:00.000Z"
}