Org-Mode Octopress Setup V2

otherMarch 05, 2014Dotby Justin Gordon

Note: This is a refresh of my original post from April, 2013 to adjust for Emacs 24.3 and org-mode 8.2.x

WordPress seemed like a good blogging platform, but it just didn't feel right. I spend all my day editing text files using vim key-bindings, and I love Org Mode for all non-coding writing. If you don't know Org Mode, it's like having Markdown mode on steroids. You can have a numbered list in Markdown, but org-mode lets you re-order the list, and that's just the beginning. Editing blog documents in the WordPress editor felt almost as bad as being told to use MS Word. I found that ergonomics of Org Mode, including all the goodness of recent versions of Emacs, including Evil (Vim emulation), just made organization of creative thoughts so much more enjoyable.

So I bit the bullet one weekend, and dove into Octopress, publishing my first article, Octopress Setup with Github, Org Mode, and LiveReload. The solution presented in that article Introducing Octopress Blogging for Org-Mode stopped working when I upgraded Emacs to 24.3 and org-mode to 8.2.x. Here's a rehash of my original article updated to the latest software versions as of March, 2014.

If you used to writing real web applications, rather than know the intricacies of a giant monolithic blogging platform, then the customization of Octopress seems so much more straightforward. This is so much more like the Unix philosophy that so many of us love, which is small and modular, rather than monolithic.

I like Rob Dodson's summary (noting Org Mode plus Emacs):

  • Octopress is a blogging framework written by Brandon Mathis (@imathis) which sits on top of Jekyll. Jekyll is a static site generator, meaning there's no database associated with your blog. Instead of writing everything in a WSYWIG linked to MySQL (like Wordpress or Blogger) you produce text files using Markdown which are then converted to static HTML. There are 3 huge benefits to this approach. First, writing in Markdown (org-mode for me) is awesome. Once you learn the syntax it's incredibly fast and you don't have to spend time playing with a tiny little editor window just to add some style to your posts. Second, writing in your favorite text editor is also awesome. I produce everything in Sublime Text 2 (Emacs for me) and every day I discover new tricks to make the process better. If you've ever had to write a blog post using one of those horrible little TinyMCE editors you will appreciate this feature. And lastly, static HTML is fast.

This article should be useful for:

  1. Any interest in using org-mode to publish to Octopress including some reasons I use Org Mode (with Emacs).
  2. Some explanation of what Octopress and git are doing.
  3. Anybody curious about how using free github pages works to host Octopress.

Incidentally, since my blog is hosted using github pages, the source code and configuration I use to generate it can all be found here. See the notes below on the difference between the source and master branches.

Basic setup

  1. Rob Dodson on Octopress: Start off with these instructions from this posting on April 30th, 2012. There are a few differences worth noting:

    1. You should change the .rvmrc to a .ruby-version file
    2. Github recommends your deployment repository be named yourname.github.io, not yourname.github.com.
    3. After you run rake setup_github_pages and before running rake generate, you should run rake install. If you forget, there's a clear message indicating this omission.
  2. Customize octopress/_config.yml. The yaml file contains descriptions.

  3. Update the DNS to use your custom domain if you wish: Github directions on setting up a custom domain

  4. At this point, you can create a post:

    rake new_post["my post name"]

    Create a page:

    rake new_page["my page name"]

    Generate and deploy:

    rake gen_deploy

    Watch the site and regenerate when it changes:

    rake watch

    Preview the site in a web browser:

    rake preview

    See all the available rake options:

    rake -T

    Save changes to source branch:

    git add .
    git commit -m "save changes to source"
    git push origin source

Some Perspectives on how Octopress Works

Posts

Posts are created using the rake task rake new_post["Post Title"]. The key things about a post are:

  1. File is located in =source/_posts.
  2. File has a header containing the meta-data for the post. The post URL and date are determined by the by the title and date fields. If you want to change the date of your post, then you change the meta-data. Changing the file name is useful only for file navigation. Here's a gist for a rake task to update the file names to match the metadata.

Pages

Pages are created using the rake task rake new_page["Page Title"]. The key things about a page are:

  1. Files are located in source/page-title
  2. File has a header containing the meta-data for the post.

I use "Pages" for things like my "about" page.

POW

POW allows you to point your browser to http://octopress.dev to see your local, unpublished Octopress website. It's very convenient to not have to remember to run a local server, and it works great with LiveReload. Scroll to the bottom of this link for details on POW. The alternative to running POW is to run rake preview and then point your browser at http://0.0.0.0:4000 (or whatever port you configured).

Automatically Generating the Site

Start a shell tab running this command: rake generate && rake watch. Edit a file in markdown or follow the instructions below to use org-mode.

Org-Mode

You can skip this section if you're not interested in org-mode. However, it's super cool!

Why org-mode for blog publishing?

Org-mode offers quite a bit more than plain markdown. It's quite the hacker's delight for note taking and authoring of blog articles. Down below I list a few reasons why org-mode. Here's a few org-mode features I love (Some are Emacs ones):

  1. All headers and list items can be reordered with minimal keystrokes (think super powerful outliner).
  2. Numbered lists.
  3. Editable tables in text editor, with movable columns, movable rows.
  4. Ergonomics of insertion of URLs and images.
  5. Includes the basics of markdown, such as source code blocks and much more.

Org-mode Integration

The org-octopress plugin automates the process of converting an org-mode document (.org file) in source/org_posts into a .html document in source/_posts. Once the html document is saved in posts, the rake watch task picks up the change and deploys the file. Neat!

Here are the basic steps:

  1. Install Emacs 24.3 and use the package manager to install org-mode and org-octopress.

  2. See my Emacs configuration below.

  3. Note, there are two ways to use org-octopress. I do not use its features to automate the setup of the directories. This automated setup does not provide a way to have "pages". As of March, 2014, you can only have "posts". Instead, my configuration below handles the mapping of directories.

  4. Images work fine. Well, almost fine. The big gotcha is that the standard inclusion of images in org-mode results in broken paths at deployment. The workaround is to embed the Octopress syntax for an image, and to place the images under source/images. Note, you'll want to be sure to use an absolute path, or else your article might look OK on the home page, but might now work in the postings directory. If I'm creating a document with many images, I'll group the images for that document in a sub-directory of images named like the document. This is how it should look. The trick is to place the octopress img directive within a HTML begin/end block.

    image1

  5. Links: This is key thing to get right. It's critical to understand the issues links, or else you'll have one of these issues:

    1. Links work when you test your blog locally using pow, but not when you go to your published website. This happens if you use a relative link from blog articles, because blog articles sometimes appear on your home page and sometimes under the /blog directory. You have to use your domain address to link from blog articles to other articles on your blog.
    2. You'd like your local links to point to the correct local spot. You can do this for links on static pages, but just not blog articles. Thus, for non-blog articles, it's preferable to use the file: relative path format (just not file:/ absolute path and not file:~/).

Here's the rules:

Links from static pages, relatively specified to other static pages and to posts. Ensure that there's no / immediately following file:. For example:

[[file:telecommuting.html][Why telecommuting works and how I maximize productivity]]

Or if the link is one level under the current directory:

[[file:misc/telecommuting.html][Why telecommuting works and how I maximize productivity]]

Links from a page to a post can use a relative link like this. Important: you must use the YYYY/MM/DD/blog-title/index.html format! and you must specify the article title.

[[file:../blog/2013/04/27/octopress-setup-with-github-and-org-mode/index.html][Org-Mode Octopress Setup V2]]

However, links from posts to other posts require an absolute URL using your published domain name. The big gotcha is that blog posts sometimes are shown on the home page and sometimes inside of the blog directory. To avoid trouble, you need to follow a format as this example shows. It's easiest to copy the URL from the browser address bar.

[[http://www.railsonmaui.com/blog/2013/05/08/strategies-for-rails-logging-and-error-handling/][Strategies for Rails Logging and Error Handling]]

I tried using a file:../blog syntax, but that either would work on the home page or in the specific blog article, but not both. http:/blog links would work in Chrome but not mobile Safari. Hopefully, one day we'll be able to specify relative links from blog article to blog article. For now, this is a big gotcha. Tip: You can specify relative links between org pages using the .org file suffix, rather than html. The earlier example could have been specified as:

[[file:misc/telecommuting.org][Why telecommuting works and how I maximize productivity]]

That allows you to put your cursor on the link in emacs, and hit F12 to go the org file! I've got F12 mapped to org-open-at-point. Awesome!

  1. Bold and italic styling (text inside of stars and /) was a bit of mystery using the standard theme. Octopress has styling for <strong> and <em>. Org-mode spits out <b> and <i> tags. Add this to sass/custom/_fonts.scss.

    b { font-weight: bold; }
    i { font-style: italic; }

    Code styling (text inside of equals) like this did not work after a code block unless I added the div tag to this line around 100 in _syntax.scss. You're just adding the div selector.

    // Sometimes html gen by org-mode misses p or li tags, so add div to the mix
    div, p, li {
      code {
        @extend .mono;

Useful Scripts

  • Just configure OCTO_HOME
  • Emacs tip: Visit the created file by placing cursor over file name and then hit Ctrl-xundefined f.
export OCTO_HOME=~/octopress
ogen () {
  cd $OCTO_HOME; rake generate; cd -
}

osave () {
  cd $OCTO_HOME; git commit -am "Updates" && git push origin source; cd -
}

odeploy () {
  cd $OCTO_HOME; osave; rake gen_deploy; cd -
}

# this one is for orgmode only
opost() {
  cd $OCTO_HOME
  output=$(rake new_post["${1}"])
  new_file=$(echo $output | awk '{print $4}')
  base=$(basename $new_file)
  new_location=$OCTO_HOME/source/org_posts/
  mv $OCTO_HOME/$new_file $new_location
  echo created $new_location/$base
  cd -
}

opage() {
  cd $OCTO_HOME
  rake new_page["${1}"]
  cd -
}

Emacs setup

;; Justin's customized org to octopress publishing
;; Based on
;; org-mode 8.x+
;; http://blog.paphus.com/blog/2012/08/01/introducing-octopress-blogging-for-org-mode/
;; https://github.com/yoshinari-nomura/org-octopress
;; See http://wwww.railsonmaui.com

;; the converter from org to jekyll html files
(require 'ox-jekyll)

;; I prefer to use the plugin for source formatting. More colors!
(setq org-jekyll-use-src-plugin t)

;; We're going to create the yaml-front-matter in the rake task
(setq org-jekyll-include-yaml-front-matter nil)

(defun save-then-publish ()
  (interactive)
  (save-buffer)
  (org-save-all-org-buffers)
  (org-publish-current-project))

(setq org-export-with-sub-superscripts `{})

(setq my-common-octopress-settings
      '(:base-extension "org"
                        :with-toc nil
                        :with-sub-superscript nil
                        :section-numbers nil
                        :recursive t
                        :publishing-function org-jekyll-publish-to-html
                        :headline-levels 4
                        :body-only t))

(setq my-static-directories '("about" "meta" "tips"))
(setq my-base-directory "~/j/railsonmaui-octopress/source")

(defun my-create-octopress-static (prj)
  (let ((base-dir (expand-file-name prj)))
    `(undefinedprj . (:base-directory undefinedbase-dir
                              :publishing-directory undefinedbase-dir
                              undefined@my-common-octopress-settings))))

(defun my-static-components ()
  (mapcar 'my-create-octopress-static my-static-directories))

(let ((default-directory my-base-directory))
(setq org-publish-project-alist
      `(
        ;; components
        ("blog" . (:components ("blog-org" "blog-extra" "about" "meta" "tips")))

        ;; blog articles
        ("blog-org" .  (:base-directory undefined(expand-file-name "org_posts")
                                        :publishing-directory undefined(expand-file-name "_posts")
                                        undefined@my-common-octopress-settings))
        ("blog-extra" . (:base-directory undefined(expand-file-name "org_posts")
                                         :publishing-directory undefined(expand-file-name ".")
                                         :base-extension "css\\|pdf\\|png\\|jpg\\|gif\\|svg"
                                         :publishing-function org-publish-attachment
                                         :recursive t
                                         :author nil))

        ;; static articles
        undefined@(my-static-components))))

Deploying to Github: Directory Structure of Octopress and the master and source Git Branches

Github offers free hosting of both the blog deployment and source. You're looking at the deployment right now. You can find the source here at my git repo justin808.github.io. I doubt you could beat the price, performance, and convenience. You can look inside of this repo, clone it, etc. and you have everything that it took to make this blog.

I originally was quite confused by the concept of using two separate git branches to make up what gets deployed on the live website versus the git repository of my articles. Plus, there's the issue of Octopress git repository that you clone when starting out. Eventually, I figured out that the two branches simply contain different files, with one containing the original Octopress files. Here's a few screen grabs that might clarify the situation for you.

Don't forget that you never push to the master branch, but rather the rake deploy task does it for you. Instead, you run git push origin source to push the content of your blog to github.

The octopress/public directory corresponds to what you'll find on the github site for your deployment (master branch).

image2

The octopress/.gitignore file contains entries like public, which essentially keeps the rake generate files out of the source branch.

Here's the github master branch right after creation. Note the correspondence with public. This is what gets deployed as your blog.

image3

Here's the github source branch. This contains the octopress environment, as well as your customizations and blog posts.

image4

Useful Links

  1. Getting Started with Octopress: Nice overall tutorial. Very current! March 2013.
  2. Rob Dodson on Octopress: Most of the instructions I show below are from this posting on April 30th, 2012.
  3. Joel McCracken on Octopress: Use Jekyll? You Really Should Be Using Octopress
  4. Github directions on setting up a custom domain
  5. dblock.org Article on Octopress: A good explanation from Jan 17, 2012, especially on the difference of the source and master branches.
  6. Introducing Octopress Blogging for Org-Mode: For org-mode. See below.
  7. 18 Months of Octopress: Nice article on why Octopress was worth the switch.
  8. Shell Aliases for Octopress: Save time with these shortcuts
  9. org-octopress package: The connection between emacs/org-mode and octopress.
  10. Check your blog for broken links: Super useful to scan for broken links. This link is more efficient than the W3C Link Checker

Live Reload

Previously, I tried to get Live Reload to work. It would be neat it worked, but I ran into a snag. The browser gets triggered to update before the Jekyll page is generated. I tried some various techniques for working around this, but nothing seemed reliable. If you figure out how to fix this, please let me know.

Parting words…

Thanks in advance for any suggestions on this article. I hope you find it helpful.

Are you looking for a software development partner who can
develop modern, high-performance web apps and sites?
See what we've doneArrow right