Org Reveal

I started using org-reveal for presentations. It's not perfect, but it succeeds at combining the editing ease of org-mode with good-looking and portable html/js presentations.


Setting up org-reveal within Doom Emacs is straightforward.

  1. Add these lines to your packages.el:

    ;; ~/.doom.d/packages.el
    (package! org-reveal)
    (package! ox-reveal)
  2. Add some optional configuration to your config.el.

    ;; ~/.doom.d/config.el
    (after! org
      (load-library "ox-reveal")
      (setq org-reveal-root "file:///path/to/reveal.js-master"))

    NOTE: If you omit this, you must specify a URL at the top of each org-mode file, so org-reveal can find the javascript.

It may not be necessary to include ox-reveal in your config, this is just what I ended up with after some trial and error.


In Doom with Vim keybindings, exporting is SPC m e R B to export as html and then open the page in your default web browser. After the first export, you can do SPC m e R R to rewrite the existing html and refresh the page manually.

If you like the default settings, that's all you need! But if you want customizations, read on.

Custom Styling

Org-reveal comes with 11 themes:

  • beige
  • black
  • blood
  • league
  • moon
  • night
  • serif
  • simple
  • sky
  • solarized
  • white

You can specify one of these themes by adding this line to your org-mode file:


Sometimes, a theme is almost what you want but not quite, or you want to make a change just for one particular presentation. Thankfully, the org-reveal authors thought of this and provide a way for you to add your own custom CSS without having to write a whole new theme. Add a line like this to your org-mode file:

#+REVEAL_EXTRA_CSS: ./org-example.css

In this example, my custom CSS (org-example.css) is in the same directory as my org-mode file, but relative paths also work.

Custom JavaScript

It's also possible to add inline JavaScript. This will be appended to the last <script> tag in the document, and so will execute after the document loads.

For my purposes, I wanted to add a CSS class to the parent of a particular element. Because CSS does not have a parent selector, this had to be done in JS.

#+REVEAL_EXTRA_SCRIPT: for(let e of document.getElementsByClassName("figure-number")){e.parentElement.classList.add("fig-caption");}

Custom Title Slide

Org-reveal can extract the values from the org-mode doc to include in the title slide, using printf-like % specifiers:

#+REVEAL_TITLE_SLIDE: <h1 class="title">%t</h1><em>%s</em><br><br>%a<br>%d

The above wraps the org-mode's TITLE variable (denoted %t) in an h1 tag, for example.

Full Example

Below is an example org-mode file using all of the above tricks.

#+TITLE: example slideshow
#+SUBTITLE: this is the subtitle
#+AUTHOR: Alex Shroyer
#+DATE: August 13, 2021
#+OPTIONS: toc:nil num:nil html-postamble:nil ^:{} reveal_title_slide:nil
#+REVEAL_EXTRA_CSS: ./org-example.css
#+REVEAL_INIT_OPTIONS: slideNumber:"c/t", transition:"none", transitionSpeed:"fast", controlsTutorial:false, minScale:1.0, maxScale:1.5
#+REVEAL_EXTRA_SCRIPT: for(let e of document.getElementsByClassName("figure-number")){e.parentElement.classList.add("fig-caption");}
#+REVEAL_TITLE_SLIDE: <h1 class="title">%t</h1><em>%s</em><br><br>%a<br>%d

* This is the first slide
  It has some content
* This is a second slide
** It has sub-sections
   these render as other slides
** last sub-section
   - you can navigate main sections using left/right
   - or navigate sub-sections with up/down
* The End

Here's the org-example.css file:

.reveal h1 {
    text-shadow: 0 10px 10px blue;
.reveal ul {
    list-style-type: lower-greek;


The example looks like this after exporting.