Ravi Sagar | Home | Blog

Blogging with Emacs and Org Mode

Table of Contents

1 Overview

So you are wondering if Emacs1 can be used to do blogging and at the same time also thinking about why use Org Mode2? Well the answer is simple. I want to keep things simple. Blogging is all about content and I spend lot of time making notes, keeping a list of things I want to do in Org Mode, there are lot of blog I just couldn't write on my Drupal site www.ravisagar.in because it is a bit of a pain to copy, organise and transfer it to a web portal.

With Emacs and Org mode you can just do blogging from your terminal (yes I used Emacs in terminal mode) and I believe I can do it much faster and will be able to share more information quickly whenever I want. Also the other benefit is that with Org mode I can share code snippets that can also be run and evaluated. It is so much fun :)

Update: I started writing this blog post with the intention to help others who may want to write and publish a blog using Emacs and Org Mode but I have kept on adding stuff to this post and it is no longer just for blogging. I have included lot of things in the post related to literate programming, Org Mode fundamentals and I am still adding things here to share my workflow. Enjoy.

2 Who this blog is for?

  • You use Emacs
  • You use Org mode
  • You want to blog
  • You want to share content with code
  • You like simplicity

3 This blog/site is built with Emacs and Org Mode

I made this site using Emacs of course (otherwise what is the point). Apart from my Drupal sites I have tried using Hugo, Grav, Github pages before, I still have those blogs up and running but I don't plan to update it with more content. Those static site generator where more of an experiment. I personally loved working on Hugo for its simplicity and I was amazed by Grav for its CMS like capabilities (it is still file based).

4 What can you learn here on this blog post?

  • Learn how to use Emacs (not an expert level but enough to get you started)
  • Learn how to use Org Mode for note taking
  • Learn how to use Org Mode for blogging
  • Publish yyour blog and host it

The idea of this blog is to create one big (not too big) document that will make it very easy for anyone to install Emacs and start using it.

5 Come back to this blog post

I will keep on updating this blog post with new content. So you may want to come back to this post if you have want to learn more.

6 Emacs and Org Mode fundamentals

6.1 Basic commands

Let us learn the fundamentals first. I also made a video to show these basic commands.

Abbreviations use:

  • C is Ctrl key
  • M is Meta

Windows - Meta key is Alt Mac - Meta key is Esc

  • Close the IDE: C-x C-c
  • Save the file: C-x C-s
  • Cut: C-w
  • Paste: C-y
  • Undo: C-_
  • Copy: M-w
  • Search: C-s
  • Move header up and down: Esc-UP and Esc-Down
  • Increment and decrement header level: Esc-LEFT and Esc-Right
  • Zoom in: C-x C-+
  • Zoom out: C-x C–
  • Default zoom: C-x C-0
  • After one combination of either C-x C-+, C-x C– or C-x C-0 you can press +, - or 0

6.2 Split the screen

  • Vertical split: C-x-3
  • Horizontal split: C-x-2
  • Move between windows: C-x-b
  • Closing the active window: C-x-0
  • Full screen: M-M-M
  • Make current window wider: C-x }
  • Make current window narrower: C-x {
  • Specify the size to make things simpler C-u 40 C-x } or M-40 C-x } 3
  • Specify the default size of 4 by doing C-u C-x } 3
  • Specify size before the split C-u 40 C-x-3 3

6.3 Tips for making writing experience better

  • Insert a link C-c C-l
  • Open existing link in the browser, move cursor to the link and pres C-c C-o
  • Make the text fit in the window: visual-line-mode

Add this in your .emacs to enable it by default. (add-hook 'org-mode-hook 'visual-line-mode)

  • Indentation based on the headers: org-indent-mode

Add this in your .emacs to enable it by default. (add-hook 'org-mode-hook 'org-indent-mode)

  • Insert footnote: C-c C-x f
  • Demoting a subtree: M-S-right
  • Promoting a subtree: M-S-left


6.4 Macros in Emacs

C-x ( - Start the macro C-x ) - end the macro C-x e - repeat the macro

6.5 Switch between buffers

If you do C-x b then you can type in the name of the buffer or you can press C-x C-b it will bring up the list of all the buffers. However there is another way. You can use C-x <left> and C-x <right> as well which is quicker.

6.6 Clock time

You can record time you spent to work on a task.

  • Start clock: C-c C-x C-i
  • Stop clock: C-c C-x C-o
  • Update time interval: C-c C-c (Do that while the cursor is on the time range. I do that a lot because I often add time lateraa)
  • Reporting: Just insert these lines and press C-c C-c to generate a report anywhere in your file.
Table 1: Clock summary at [2021-09-06 Mon 18:09]
Headline Time
Total time 0:00

Things are self explanatory. For more details check this page.

6.7 Task that needs to be tracked

6.8 Archive a task

When a task is done you can remove it from the org file by C-c C-x C-a

6.9 Clock table

So you have been logging your time, great. What about reports?

Type M-x org-clock-report to insert a report.

Table 2: Clock summary at [2021-01-11 Mon 13:34]
Headline Time
Total time 0:00

7 What is Org Mode?

Org-mode is a document editing, formatting, and organizing mode, designed for notes, planning, and authoring within the free software text editor Emacs. Source: Wikipedia.

8 What can you do with Org Mode?

8.1 Literate Programming with Org Babel

To insert a template I use a short <s - <tab> and it will insert a source block but you can also insert your own block templates.

Insert this in your .emacs file

(add-to-list 'org-structure-template-alist
             '("g" "#+NAME: fileName ?\n#+BEGIN_SRC groovy :exports code :results output :tangle directory/fileName.groovy \n\n#+END_SRC"))

Now using <g - <tab> you can quickly insert this groovy specific template. ? mark is the place where your cursor will be when you insert the template.

For more than one template use the following code.

(add-to-list 'org-structure-template-alist
             '("g" "#+NAME: fileName ?\n#+BEGIN_SRC groovy :exports code :results output :tangle directory/fileName.groovy \n\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
             '("t" "#+TITLE: ?\n#+DATE: \n#+AUTHOR: "))

8.1.1 Editing source code

Now this literate programming this is really cool but when you are writing the code within org mode you may not get your autocomplete or snippets working and for a true rich editing experience you may need that. Especially when you need to write a bit more code. Fortunately there is a way of doing that.

Press C-c ' from within your source code block and it will open a new buffer with the body of your source code block and it will respect the language mode that you may have setup. Press C-c ' again and the buffer will close and return to the document. Super cool I know. You can learn more about it here.

8.2 Power of Emacs

8.3 Everything is a text file

9 Key features of Org Mode

9.1 Folding

9.2 States

9.3 Track progress

9.4 Agenda view

Week-agenda (W17): Monday 20 April 2020 W17 misc: Sched.65x: TODO Update Expense sheet spx: Sched.41x: How to un-exclude the issues from a plan? :video::t1719: spx: Sched.41x: Blog about why I like Jira :blog::t1719: spx: Sched.40x: Create a project using a Groovy script: link :video::p912: spx: Sched.40x: Video Create a project using a Groovy script: link :p912:video: spx: Sched.40x: Write a script to create linked issue :video::p912:

Now when you are looking at the agenda you may want to display it for the next 10 days. You can do that by M-10 C-c a a.

9.4.1 TODO Excluding subtree from the agenda

Sometimes I do have subtree with dates or TODO keywords. Those will start appearing in my agenda but I don't want them to appear there. fortunately there is a way.

Just add COMMENT keyword in front of the subtree and that is it.

COMMENT TODO This will not appear in the agenda.

Cool isn't it?

You can also use C-c ; or org-toggle-comment to add or remove the COMMENT keyword.

9.5 TODO Schedule tasks SCHEDULED: <2020-04-21 Tue>

9.6 Deadline DEADLINE: <2020-04-22 Wed>

9.7 Org Capture

9.8 Refile

9.9 Spell check

M-$ on the word and it will give you suggestions with numbers. Just press the number if you want to use the suggestion.

9.10 TODO Drawer   video

You can store additional information related to an entry and you can do that with the help of drawer.

You can insert then using org-insert-drawer. The format is like this.

This is a drawer

This is my drawer where I keep my documents.

Store your important but kind of hidden.

To avoid this drawer text from getting exported you can add this in this in your document.

#+OPTIONS: num:nil d:(not "DRAWERNAME")

9.10.1 sub tree

Information inside subtree

9.11 Exclude tags are awesome   video

It is possible that there are certain headings in your document that you don't want to be exported. You can add this on top of your document.

#+EXCLUDE_TAGS: noexport

Now any heading with noexport will not get exported but will still be there in your document for you to finish.

9.12 Narrowing and widening

Let us say you are working on a big document but you want to focus on a specific heading. It may be useful when you are presenting a document as a presentation but within Emacs.

  • Narrow: C-x n s
  • Widen: C-x n w

10 Emacs customisations

I use the following configurations to hide/disable to menu bar, scroll bar and tool bar. You don't have to but I like it.

(menu-bar-mode -1)
(toggle-scroll-bar -1)
(tool-bar-mode -1)

11 Do you need Org Mode?

Short answer is yes but don't expect immediate results. You need to spend time learning it. It is mostly for geeky people who are comfortable using terminal. If you are not used to typing commands then don't bother.

12 How to start using Org Mode?

12.1 First install Emacs and then install the org package M-x package-install RET org RET.

12.2 Your best place to learn is https://orgmode.org/

13 Publish a website

So are you ready to launch a website using Org mode? Great. Let us begin. First you need to modify your Emacs configuration file - .emacs for publishing to work.

13.1 Snippet of my .emacs file responsible for publishing this blog

The following code make sure that it will read the *.org files in a specific directory and it will generate HTML out of it and also add few other things like header, footer and css.

; Publishing using Org-mode
;(add-to-list 'load-path "~/.emacs.d/ox-rss.el")
(require 'ox-rss)

(defvar ravipro-html-head
  "<link rel='stylesheet' href='css/style.css' type='text/css'/>")

(defvar ravipro-html-blog-head
  "<link rel='stylesheet' href='../css/style.css' type='text/css'/>")

(defvar ravipro-html-preamble "<div class='preamble'><a href='/'>Ravi Sagar</a> | <a href='/'>Home</a> | <a href='blog/blog.html'>Blog</a></div>")
(defvar ravipro-html-blog-preamble "<div class='preamble'><a href='/'>Ravi Sagar</a> | <a href='/'>Home</a> | <a href='../blog/blog.html'>Blog</a></div>")

(defvar ravipro-html-postamble
  "<div class='nav'>
<li><a href='/'>Home</a></li>
<li><a href='sitemap.html'>Sitemap</a></li>
<li><a href='blog/blog.html'>Blogs</a></li>
<li><a href='http://twitter.com/ravisagar'>Twitter</a></li>
<div class='footer'>Copyright © 2020. Last updated: %C, built with %c</div>"

(defvar ravipro-html-blog-postamble
  "<div class='nav'>
<li><a href='/'>Home</a></li>
<li><a href='../sitemap.html'>Sitemap</a></li>
<li><a href='../blog/blog.html'>Blogs</a></li>
<li><a href='http://twitter.com/ravisagar'>Twitter</a></li>
<div class='footer'>Copyright © 2020. Created %d, Last updated %C, built with %c</div>"

(defun ravipro-format-entry (entry style project)
    (format "[[file:%s][%s]] --- %s"
            (org-publish-find-title entry project)
            (format-time-string "%Y-%m-%d" (org-publish-find-date entry project))))

(setq org-publish-project-alist
         :base-directory "~/ravi.pro/"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/"
          :recursive t
          :exclude "level-.*\\|.*\.draft\.org"
          :publishing-function org-html-publish-to-html
          :auto-sitemap t
          :sitemap-filename "sitemap.org"
          :sitemap-title "Sitemap"
          :sitemap-sort-files anti-chronologically
          :with-toc nil
          :html-head ,ravipro-html-head
          :html-link-up "/"
          :html-link-home "/"
          :html-preamble ,ravipro-html-preamble
          :html-postamble ,ravipro-html-postamble

          :base-directory "~/ravi.pro/blog/"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/blog/"
          :exclude "level-.*\\|.*\.draft\.org"
          :publishing-function org-html-publish-to-html
          :auto-sitemap t
          :sitemap-filename "blog.org"
          :sitemap-title "All Blogs"
          :sitemap-sort-files anti-chronologically
          :sitemap-format-entry ravipro-format-entry
          :html-head ,ravipro-html-blog-head
          :html-link-up "/"
          :html-link-home "/"
          :html-preamble ,ravipro-html-blog-preamble
          :html-postamble ,ravipro-html-blog-postamble


          :base-directory "~/ravi.pro/images/"
          :base-extension "png\\|jpg"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/images/"
          :recursive t
          :publishing-function org-publish-attachment

          :base-directory "~/ravi.pro/css/"
          :base-extension "css"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/css/"
          :recursive t
          :publishing-function org-publish-attachment

          :base-directory "~/ravi.pro/"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/"
          :base-extension "org"
          :html-link-home "https://www.ravi.pro/"
          :html-link-use-abs-url t
          :rss-extension "xml"
          :publishing-function (org-rss-publish-to-rss)
          :recursive t


         ("website" :components ("home" "blog" "images" "css"))


13.1.1 TODO So let us discuss this piece of code

13.2 Publishing commands

These commands will be used to publish the site into HTML format to a specific location that you set above in the .emacs file.

  • Publish: M-x org-publish
  • Shortcut: C-c C-e P x PROJECTNAME
  • Force publish (all files): C-u M-x org-publish

13.2.1 Issues you may encounter

  • Sitemap title not updating?: Clear the content of ~/.org-timestamps folder and export again.

13.3 CSS used on my site


    max-width: 70%;
    margin: auto;
    font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    color: #222222;

.nav {
    background: #aeaeae;
    padding: 10px;
.preamble {
    background: #330000;
    padding: 10px;
    color: #ffffff;

.preamble a:visited {
    color: #ffffff;

.preamble a:link {
    color: #ffffff;

13.4 Host your website

Here are the steps.

  1. First setup the repository with the correct name.

There are 2 main ways of doing it on GitLab.com. Refer to this page.

  • Under your username user create a project user.gitlab.io and enable the GitLab pages and your website will be published under https://user.gitlab.io
  • Under your group group create a project group.gitlab.io and enable the GitLab pages and your website will be published under https://group.gitlab.io

Make sure pages can be viewed by everyone.

  1. Create a file called .gitlab-ci.yml in your repository root with the following content.
  stage: deploy
    - mkdir .public
    - cp -r * .public
    - mv .public public
      - public
    - master

I use GitLab.com to host my site. I manage the directory where I publish my HTML in my Git repository on GitLab. I also made a video about it.

  1. Add CNAME record that points to user.gitlab.io
  2. Verify your domain

Go to your repository settings and add both example.com and www.example.com. You will then get a TXT record that you need to add for your domain. Wait for the verification to finish and you now have a site hosted for free on GitLab. Cool isn't it?

14 Execute code - Literate Programming

You can insert code snippets in your document.

  • C-c C-c – Execute the code

When you export to HTML you will be asked to export all the code blocks one by one. However you can execute them without your confirmation.

Two ways to do it.

  1. Set this in your .emacs file.
(setq org-confirm-babel-evaluate nil)
  1. Add this on top of your file, close and open the file again.
# -*- org-confirm-babel-evaluate: nil -*-

15 Open a website in Emacs

Emacs Web Wowser - eww can be used to open sites.

  • M-x-eww then type in the url.

16 Presentations using Org Mode using Org Tree Slide

Now earlier in this document we talked about Narrowing and Widening which is great and works wonderfully well but not only focussed work but also for presentations.

16.1 Presentations in Org Mode

There are various packages available for making proper presentations and I will dive into them as well but in case you are like me and want to present within org file that can be edited live there is a nice way of doing it using org-tree-slide package.

16.2 Install org-tree-slide package

Just install this packages from the MELPA repository and then let us get started.

16.3 How to get started?

Open any org file with headers and then start the presentation using org-tree-slide-mode

16.4 Navigate slides

How to navigate? Well if you are on mac then C-< and C-> will not work I think but you can always add your keybindings in the emacs configuration file.

(with-eval-after-load "org-tree-slide"
  (define-key org-tree-slide-mode-map (kbd "<f5>") 'org-tree-slide-move-previous-tree)
  (define-key org-tree-slide-mode-map (kbd "<f6>") 'org-tree-slide-move-next-tree)

16.5 Profiles

There are profiles that you can turn on before you start the presentation.

  • M-x org-tree-slide-simple-profile

Display slides without header

  • M-x org-tree-slide-presentation-profile

Display slides with header, default profile

  • M-x org-tree-slide-narrowing-control-profile

Present only subtrees with TODO

16.6 You will love org-tree-slide :) I promise

Cool isn't it?

17 Spreadsheets in Org Mode

We discussed briefly how to create a table but we can do more with them like some calculations. Let us take a look at a simple example. Track days until

End date Event Days left
<2021-10-31 Sun> Apply for college 92.239803
<2022-10-31 Mon> Major event 457.23980
<2021-01-26 Tue> Republic day -185.76020

You have to use this #+END_SRC $3=(date($1) - date(now())), you can do lot of other things but I wanted to give you a quick idea about how to get started with calculations.

18 How I organise my Org Mode files

main.org: Date involved

  • Project 1

– sub project 1 – sub project 2

  • Project 2

misc.org: No date involved

  • Buy milk
  • Car service

bills.org: Date involved, recurring

  • pay bill 1
  • pay bill 2

tickler.org: Reminders

  • reminder 1
  • reminder 2

inbox.org: All the ideas will go here

  • task 1
  • task 2
  • random idea

journal.org: Writing regular

  • journal entries

19 Good external resources



Thanks Robert Davis for the tip: https://youtu.be/C2ZSa9RshbU