I am a big fan of building tools for your workflows. Here is another quick example.

To create these blog posts I need to create a markdown file with some front matter. An example of this is below - indeed this is the front matter for this post.

---
author: Timothy Johnson
title: Emacs - Quick Blog Function
date: 2025-05-27
draft: False
featured_image: ""
tags: ["Emacs", "personal", "tech"]
---

Each time I write a blog I need to do this, I hate duplication of work!

So let’s write an elisp function to do this!

First let us get some stuff cleared up. The below set my blog post folder and the author. This works for me as these are always the same. This could be set as a variable the user could set, or select from a predetermined list. Something for a version two perhaps!

(defvar TJ/my-blog-post-folder "~/Dropbox/test/"
      "Path to the folder where blog posts will be saved.")

(defvar TJ/my-blog-post-author "Timothy Johnson"
  "Default author name for blog posts.")

Then the fun part - the below function takes all the user input - saves it to a file and opens that buffer!

(defvar TJ/my-blog-post-author "Timothy Johnson"
  "Default author name for blog posts.")

(defun TJ/create-blog-post-front-matter ()
  "Prompt user for blog post metadata and create a Markdown file with front matter, then open it."
  (interactive)
  (let* ((title (read-string "Title: "))
         (date (read-string "Date (YYYY-MM-DD): " (format-time-string "%Y-%m-%d")))
         (draft (y-or-n-p "Is this a draft? "))
         (featured-image (read-string "Featured image path (e.g., /img/file.jpg): "))
         (tags-input (read-string "Tags (comma-separated): "))
         (tags (mapconcat (lambda (tag) (format "\"%s\"" (string-trim tag)))
                          (split-string tags-input ",") ", "))
         (slug (replace-regexp-in-string "[^a-zA-Z0-9_-]" ""
                                         (downcase (replace-regexp-in-string " " "-" title))))
         (filename (expand-file-name (concat date "-" slug ".md") TJ/my-blog-post-folder)))
    (with-temp-file filename
      (insert (format "---\nauthor: %s\ntitle: %s\ndate: %s\ndraft: %s\nfeatured_image: \"%s\"\ntags: [%s]\n---\n\n"
                      TJ/my-blog-post-author title date (if draft "True" "False") featured-image tags)))
    (find-file filename)
    (message "Blog post created and opened: %s" filename)))

And boom, done.Evaluate this block and use M-x TJ/create-blog-post-front-matter and you will be walked through what is needed.

Some thoughts I may add in the future:

  1. A function to delete the last blog post created - to help if I make a mistake I can quickly remove a file.
  2. Set author and blog location as select-able variables from a list - use numbers to select.

I am finding myself creating these types of functions all the time, more examples here and here. Little pieces of code to speed up my work. I will, of course, keep posting these here.