Org-Mode Octopress Setup V2
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:
- Any interest in using org-mode to publish to Octopress including some reasons I use Org Mode (with Emacs).
- Some explanation of what Octopress and git are doing.
- 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
-
Rob Dodson on Octopress: Start off with these instructions from this posting on April 30th, 2012. There are a few differences worth noting:
- You should change the .rvmrc to a .ruby-version file
- Github recommends your deployment repository be named
yourname.github.io
, notyourname.github.com
. - After you run
rake setup_github_pages
and before runningrake generate
, you should runrake install
. If you forget, there's a clear message indicating this omission.
-
Customize
octopress/_config.yml
. The yaml file contains descriptions. -
Update the DNS to use your custom domain if you wish: Github directions on setting up a custom domain
-
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:
- File is located in =source/_posts.
- File has a header containing the meta-data for the post. The post
URL and date are determined by the by the
title
anddate
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:
- Files are located in
source/page-title
- 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):
- All headers and list items can be reordered with minimal keystrokes (think super powerful outliner).
- Numbered lists.
- Editable tables in text editor, with movable columns, movable rows.
- Ergonomics of insertion of URLs and images.
- 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:
-
Install Emacs 24.3 and use the package manager to install org-mode and org-octopress.
-
See my Emacs configuration below.
-
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.
-
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 octopressimg
directive within a HTML begin/end block. -
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:
- 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. - 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 notfile:/
absolute path and notfile:~/
).
- Links work when you test your blog locally using
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!
-
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 tosass/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 thediv
tag to this line around 100 in_syntax.scss
. You're just adding thediv
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-x, 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)))
`(,prj . (:base-directory ,base-dir
:publishing-directory ,base-dir
,@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 ,(expand-file-name "org_posts")
:publishing-directory ,(expand-file-name "_posts")
,@my-common-octopress-settings))
("blog-extra" . (:base-directory ,(expand-file-name "org_posts")
:publishing-directory ,(expand-file-name ".")
:base-extension "css\\|pdf\\|png\\|jpg\\|gif\\|svg"
:publishing-function org-publish-attachment
:recursive t
:author nil))
;; static articles
,@(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).
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.
Here's the github source branch. This contains the octopress environment, as well as your customizations and blog posts.
Useful Links
- Getting Started with Octopress: Nice overall tutorial. Very current! March 2013.
- Rob Dodson on Octopress: Most of the instructions I show below are from this posting on April 30th, 2012.
- Joel McCracken on Octopress: Use Jekyll? You Really Should Be Using Octopress
- Github directions on setting up a custom domain
- dblock.org Article on Octopress: A good explanation from Jan 17, 2012, especially on the difference of the source and master branches.
- Introducing Octopress Blogging for Org-Mode: For org-mode. See below.
- 18 Months of Octopress: Nice article on why Octopress was worth the switch.
- Shell Aliases for Octopress: Save time with these shortcuts
- org-octopress package: The connection between emacs/org-mode and octopress.
- 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.