1. Blog in Org2jekyll - 4. Workflow of writing a blog post

This post is part 4 of a short series about writing in org mode, using org2jekyll.

TL;DR: If you do not want to read this, go to 1.1

This part 4 describes next steps after configuring the stack for blogging in Jekyll and emacs org mode, as described in the software configuration step of this series. As a brief repeat from the previous part 3, we need the following to configure the blog stack:

  • Setup Github pages and it's local repo (for example, in directory BLOG=~/mzimmerm.github.io).
  • Setup Jekyll and a theme.
  • Setup org2jekyll in emacs.
  • Configure Org2jekyll directories and in init.el.

Once the setup is finished, the steps below represent a typical workflow of creating a new blog post in the above stack.

  1. M-x: org2jekyll-create-draft - Creates an empty post in org format, with today's date. Assuming the Org2jekyll directories were configured, emacs knows where to place the post we are creating - so this can run from any buffer in emacs. The command asks a series of questions, for values, required answers are:

    • layout: (post | default) - select post.
    • title: We enter the name of our post. This will end up the title, displayed on top of post. e.g. Test Blog, and also the file name of the post (mangled a bit - I do not use dots and weird characters, as the title is converted to file name, spaces replaced with dashes.)
    • Tags: We enter same values as category for now.
    • Category: We enter space separated list of categories. we can use the same for category and tag. I am not sure what is the difference.

    The end result of this step is a new file $BLOG/org/a-test-blog.org and a buffer with it's content, like this

    #+STARTUP: showall
    #+STARTUP: hidestars
    #+OPTIONS: H:2 num:nil tags:nil toc:nil timestamps:t
    #+LAYOUT: post
    #+AUTHOR: mzimmerm
    #+DATE: 2017-05-18 Thu 22:14
    #+TITLE: A Test Blog
    #+DESCRIPTION: A Test Blog
    #+TAGS: org_mode,blog,org2jekyll
    #+CATEGORIES: org_mode,blog,org2jekyll
    #+COMMENTS: true
    
  2. Write the post in org mode.. We write the blog text in the $BLOG/org/a-test-blog.org opened above. Continue with steps below when the blog is ready.
  3. M-x: org2jekyll-publish - org-exports the post from steps 1 and 2 to html by calling the "org emacs export". This command does a few things:
    • Exports the org contents to html.
    • Places the exported html to the _posts directory from which Jekyll will build and serve the post.
    • Prefixes the blog file name with date, and replaces the .org extension with the .html extension.
    • Result of this step is a file $BLOG/_posts/2017-03-18-a-test-blog.html.
  4. $ cd $BLOG; jekyll build - (Optional) Performs the Jekyll steps to build the "Jekyll published" blog. This step is optional, but we will likely want to do it, to test locally before pushing to github.
    • A simplified description of the this command: Jekyll performs a series of transforms, e.g. surrounds the contents of the file _posts/2017-03-18-a-test-blog.html with header and footer, and places the result in the _site directory.
    • Result of this step is a file $BLOG/_site/2017/03/a-test-blog.html.
  5. $ cd $BLOG; jekyll serve --baseurl=''; (Optional) Starts the Jekyll server - we use this to test the blog locally before pushing on github.
  6. Test our blog locally by browsing to http://127.0.0.1:4000/. To change a post, edit the org file and re-publish by running steps 4 and 5.
  7. $ cd $BLOG; git commit; git push - Pushes and published the post to Github.
    • The server on github builds and serves the pushed post, similarly what is described in steps 4 and 5, and makes the post available publicly.

Notes:

  • Simplified workflow - skipping the jekyll build: Jekyll's default watch settings is to pick up and rebuild changed files. Instead of steps 2,3,4,5,6, we can run a simpler steps, in the order 5, 2, 6. See
    • Run jekyll serve --baseurl='' (described in step 5)
    • Edit the post's org file (described in step 2)
    • M-x: org2jekyll-publish. This will publish the org as html to Jekyll's _posts, where Jekyll will pick it up and "Jekyll build and publish to _site".
    • Reload the post in the browser (described in step 6)
  • Re-Publishing a changed post: If we make a change to an older blog, the steps are the same, except that step 1 is skipped. The blog's date will not change, unless we change the #+DATE: directiver from the org file being published (in this blog's example, a-test-blog.org).
  • Publishing all changed posts instead of publishing the "currently edited" post: In step 3, we can use M-x: org2jekyll-publish-posts instead of M-x: org2jekyll-publish. The plural version publishes all changed posts. Org2jekyll will figure out all posts in the org directory which changed, and publish or re-publish them all. Then, Jekyll's build/serve will pick them up and update them.

1.1. Conclusion

Assuming our Jekyll is configured the serve settings to "watch" (to pick up and rebuild changed files), this 6-step workflow of creating and publishing a post all the way to github.io:

  1. $ cd $BLOG; jekyll serve --baseurl='' (a shell command, step 5 in text)
    • Starts jekyll server locally, so we can view the blog changes locally in the browser, before pushing to github.
  2. M-x: org2jekyll-create-draft (an emacs command, step 1 in text)
    • Asks a series a questions about the type (blog, page), and so on
      • Layout: {post | default} - use r-mouse/l-mouse to select post
      • Title e.g.: A test blog - No column or dot (this creates a-test-blog—no-column-or-dot.org - replaces spaces with - and converts to lowercase)
      • Description e.g.: A longer description
      • Tags (space separated), e.g.: math walk-musings combinatorics
      • Categories (space separated) e.g.: category-math category-walk-musings category-combinatorics
    • Creates an empty blog post, with today's date, e.g. $BLOG/a-test-blog.org
  3. Edit the post content in org mode : Add the blog text.
  4. M-x: org2jekyll-publish (an emacs command, step 3 in text)
    • Locally publishes the post which is being edited. Details of this local publishing step:
      • Copies directory $BLOG/org/img/ to $BLOG/img
      • Copies directory $BLOG/org/css/ to $BLOG/css
      • Copies directory $BLOG/org/js/ to $BLOG/js
      • Org-exports the blog $BLOG/org/a-test-blog.org to html and places the html to the $BLOG/_posts/2021-04-20-a-test-blog.html
        • Converts the link types [[img:some-file.some-ext]] and [[file:img/some-file.some-ext]] in the .org file to links in the html file.
      • Notes:
        • If you want to rename a blog, remove the html from the _posts directory.
        • The blog index is built from all html files in the _posts directory
    • The Jekyll auto-watch will then copy all "special" dirs from _posts to _site, but also converts html files, in detail:
      • Despite being called "html", the first file contains markdown for Jekyll
      • During this step, Jekyll also edits some markdown tags on top of the first file to html in second html, so the two html files contents differ.
      • Edits, then copies $BLOG/_posts/2017-04-08-a-test-blog.html to $BLOG/_site/2021/04/a-test-blog.html
      • Copies directory $BLOG/img/ to $BLOG/_site/img
      • Copies directory $BLOG/css/ to $BLOG/_site/css
      • Copies directory $BLOG/js/ to $BLOG/_site/js
      • Copies directory $BLOG/org/ to $BLOG/_site/org !!! This is NOT DESIRABLE
  5. Test the post on http://127.0.0.1:4000/.
    • Browse to the above link to view the post locally.
    • Go back to step 3 to re-edit if needed.
  6. $ git commit; git push
    • Pushes the blog post to Github. The server there builds and serves our post, and makes it available for readers.