For years I have been thinking about creating a blog. But the thought of setting everything up has always kept me from doing it. Now I finally did it and in this initial post I’ll explain how I set everything up and running.

Hosting

First, we need a place for the blog. Before buying a domain and then abandoning the project after a week I looked for a free solution and found Netlify.
With Netlify we can simply use a GitHub repository for the code and the power of git and the command line for managing everything else.

Infrastructure

Next, for the barebone webpage we use Jekyll. Setting it up is straight forward as described on their website. After adding, committing, and pushing to GitHub the deployment is as easy as:

cd blog
jekyll build
netlify deploy --prod  # --prod is used as publish/production flag

Done!

Emacs Setup

Because Jekyll uses Markdown as source file and I prefer org-mode for text writing we need some export backend. After some research I found the ox-jekyll-md package, which simply converts org files to Markdown with C-c C-e m m. Setup finished.

But wait. Wouldn’t it be nice to just M-x create-blogpost? Let’s do that. First we have to remember that Jekyll searches for blogposts in _posts/ with a %Y-%m-%d-title filename. So we need to grab the current date, ask for the title, create the file, and open it in a new buffer. Below is the code:

(defun create-blogpost (x)
    "Create a new blogpost."
    (interactive "sPost title: ")
    (let ((date (shell-command-to-string "echo -n $(date +%Y-%m-%d)"))
          (title (s-replace " " "-" x))
          filename filepath)
      (setf filename (concat date "-" title ".org"))
      (setf filepath (concat "~/blog/_posts/" filename))
      (write-region "" 0 filepath t)
      (find-file filepath)))

So far, so good. But what about publishing? Let’s automate that by creating an alias for the steps mentioned earlier:

alias build="cd ~/blog && jekyll build && netlify deploy"
alias deploy="cd ~/blog && netlify deploy --prod"

And that’s it.

Workflow

Finally, after setting everything up the workflow for a new blogpost is:

  • M-x create-blogpost <Insert Title> <RET>
  • write the blogpost
  • export with C-c C-e m o for reviewing the Markdown file
  • fix the mentioned conversion issues
  • build
  • check the live draft URL
  • commit everything to git
  • deploy

Problems

Still, I encountered a couple of problems regarding ox-jekyll-md:

  • The grace accent ` is escaped and underscore becomes < sub> < /sub>. This can be fixed with Query replace: M-% or in elisp:

    (defun format-markdown ()
    "Format markdown correctly after converting from org-mode"
    (interactive)
    (goto-char (point-min))
    (while (re-search-forward "< sub>" nil t)
      (replace-match "_"))
    (goto-char (point-min))
    (while (re-search-forward "< /sub>" nil t)
      (replace-match ""))
    (goto-char (point-min))
    (while (re-search-forward "\\\`" nil t)
      (replace-match "`"))
    (goto-char (point-min)))
    
  • Org-mode’s templates don’t get converted, i.e. the front-matter has to be inserted afterwards. Inserting

    defaults:
    -
    scope:
      path: "" # an empty string here means all files in the project
      type: "posts"
    values:
      layout: "post"
    

    fixes this.

  • Jekyll adds the org file to _site. This can be fixed in the _config.yml as well with:

    exclude:
    - "_posts/*.org"