Hugo Themes
reveal-hugo
- Author: Josh Dzielak
- GitHub Stars: 683
- Updated: 2024-09-07
- License: MIT
reveal-hugo
A Hugo theme for Reveal.js that makes authoring and customization a breeze. With it, you can turn any properly-formatted Hugo content into a HTML presentation.
⚠️ The latest version of this theme requires hugo version >= v0.93.0. If you need compatibility with an earlier version, try a previous release.
Example
Using reveal-hugo, presentations with multiple slides can be created with just one markdown file, like so:
+++
title = "How to say hello"
+++
# English
Hello.
---
# Français
Salut.
---
# Español
Hola.
Just use ---
surrounded by blank lines to split content into different slides.
Documentation
Visit reveal-hugo.dzello.com to see a presentation created with this theme and learn about all of the different functionality available to you.
For a full-length blog post about reveal-hugo, checkout Harness the Power of Static Site Generators to Create Presentations on the Forestry.io blog.
Demos
Jump to the exampleSite folder in this repository to see the source code for the above presentation and several more. Here are links to those presentations live:
- logo-example - Shows how to add a logo to your presentation
- custom-theme-example - Uses Hugo pipes to compile and use a custom Reveal.js SCSS theme (recommended!)
- section-example - Very basic example that shows how to create a presentation for a Hugo section
- plugin-example - Shows how to add additional Reveal.js plugins to your presentation, for example an image gallery
- template-example - An example of using the slide shortcode with powerful templates
- bundle-example - An example of creating a presentation from one or more markdown files in a leaf bundle
- hugo-hl-example - An example of using Hugo’s compile-time syntax highlighter
- highlightjs-linenumbers-example - An example of using the multiline and multi-step capabilities of highlight.js
- blank Reveal-Hugo template - A templated skeleton site to get started quickly
Starter repository
If you want to start creating a presentation right away, clone the programming-quotes repository and start hacking.
Tutorial: Create your first presentation
You should be able to complete this section with no prior knowledge of Hugo or Reveal.js. At the end, you’ll have a working presentation with instant reloading.
Create a hugo skeleton site
To start, install Hugo and create a new Hugo site:
hugo new site my-presentation
Change into the directory of the new site:
cd my-presentation
Initialize a git repository:
git init
Get the reveal-hugo
theme
Method 1 (recommended): use theme as hugo module
Turn your new skeleton site into a hugo module by issuing this command from site root:
hugo mod init github.com/me/my-presentation
- Declare the
reveal-hugo
theme module as a dependency of your site:
hugo mod get github.com/dzello/reveal-hugo
Open hugo.toml
and add the following line:
theme = ["github.com/dzello/reveal-hugo"]
Method 2 (traditional): use theme as git submodule
Add the reveal-hugo
theme as a submodule in the themes directory:
git submodule add git@github.com:dzello/reveal-hugo.git themes/reveal-hugo
Open hugo.toml
and add the following line:
theme = ["reveal-hugo"]
Configure your presentation
Add some more contents to your hugo.toml
:
[markup.goldmark.renderer]
unsafe = true
[outputFormats.Reveal]
baseName = "index"
mediaType = "text/html"
isHTML = true
This tells Hugo to use the reveal-hugo theme and it registers a new output format called “Reveal”.
Next, create a file in content/_index.md
and add the following:
+++
title = "My presentation"
outputs = ["Reveal"]
+++
# Hello world!
This is my first slide.
Back on the command line, run:
$ hugo server
Navigate to http://localhost:1313/ and you should see your presentation.
To add more slides, just add content to _index.md
or create new markdown files in content/home
. Remember that each slide must be separated by ---
with blank lines above and below.
# Hello world!
This is my first slide.
---
# Hello Mars!
This is my second slide.
Cloning an existing repository (method 2 only)
If you have an existing repository that was setup with the above steps, you have to pull in the theme submodule after cloning your repository using the following command:
git submodule update --init
Theme update (method 1 only)
When making use of reveal-hugo
theme as hugo module, updating your theme is really easy:
At the command prompt, change to the root directory of your existing site.
cd /path/to/my-presentation
Then invoke hugo’s module get
subcommand with the update flag -u
:
hugo mod get -u github.com/dzello/reveal-hugo
Hugo will automatically pull in the latest theme version. That’s it, your update is done!
Usage
The Usage guide is contained in the example presentation that lives in this repository in the exampleSite directory. You can access a live version at reveal-hugo.dzello.com.
Root vs. section presentations
Here’s what the folder structure would look like with one root presentation and one section presentation.
- content
- home # special section for appending to root presentation
- body.md # appends to the root presentation
- conclusion.md # appends to the root presentation
- _index.md # beginning of the root presentation
- ted-talk
- _index.md # beginning of the ted talk presentation
- body.md # appends to the ted talk presentation
- conclusion.md # appends to the ted talk presentation
This will create two presentations, one at /
and one at /ted-talk/
. The order that slides are appended to each can be controlled by the weight
parameter specified in each file’s front matter. The slides in _index.md
will always come first, though you don’t have to put any slides in there if you want to.
Shortcodes
reveal-hugo comes with a variety of shortcodes that help you take advantage of some very useful Reveal.js features.
fragment shortcode
Wrap any content in the fragment shortcode and it will appear incrementally. Great for bulleted lists where you want one bullet point at a a time to appear.
- {{% fragment %}}One{{% /fragment %}}
- {{% fragment %}}Two{{% /fragment %}}
- {{% fragment %}}Three{{% /fragment %}}
frag shortcode
Like fragment but more terse - content is placed inline in a self-closing shortcode.
- {{< frag c="One" >}}
- {{< frag c="Two" >}}
- {{< frag c="Three" >}}
slide shortcode
The slide shortcode lets you set custom HTML and Reveal.js attributes for each slide - things like id, class, transition, background just to name a few. The names are the same as Reveal.js but without the ‘data-’ prefix.
Add the shortcode above the slide content, below the ---
separator. Do not place content inside of the shortcode.
---
{{< slide id="hello" background="#FFF" transition="zoom" transition-speed="fast" >}}
# Hello, world!
---
Here’s a list of documented slide attributes from the Reveal.js docs:
autoslide
state
background
background-color
background-image
background-size
background-position
background-repeat
background-opacity
(Opacity is on a 0-1 scale, by decimal. 0=transparent, 1=opaque.)background-video
background-video-loop
background-video-muted
background-interactive
background-iframe
background-transition
transition
(can have different in and out transitions)transition-speed
notes
(can also use the note shortcode)timing
Additional data attributes
Check MDN for information about how these attributes work.
- data-background-image - URL of the image to show. GIFs restart when the slide opens.
- data-background-size
- data-background-position
- data-background-repeat
- data-background-opacity
You can also pass through your own, a data-
prefix will be added automatically to each one (except for id
and class
).
section shortcode
To create groups of slides that can be navigated vertically, surround your markdown with the section shortcode.
{{% section %}}
# Vertical slide 1
---
# Vertical slide 2
{{% /section %}}
note shortcode
Add speaker notes for each slide with the note shortcode.
{{% note %}}
Don't forget to thank the audience.
{{% /note %}}
💡 Tip: you can also add notes by adding a note
attribute to the slide shortcode.
markdown shortcode
Markdown surrounded by the markdown shortcode will not be rendered by Hugo but by Reveal.js itself. This is useful if you want to use some native Reveal.js markdown syntax that isn’t supported by reveal-hugo.
{{% markdown %}}
# I'm rendered...
...by Reveal.js
{{% /markdown %}}
Maths and equations (via MathJax
)
Option 1: math
code block
You can author your equation inside a math
code block:
```math
\tag*{(1)} P(E) = {n \choose k} p^k (1-p)^{n-k}
```
Use of the code block will automatically activate needed MathJax
script for equation display.
If you want to use inline equations (like $E=mc^2$) wrap your math content in two single-$:
Albert Einstein's famous formula: $E=mc^2$
If you want to use inline equations and no math
code block for auto activation is present in your slides, you need to manually enable MathJax
by setting the parameter math
to true
in your page frontmatter.
Option 2: math
shortcode
Alternatively, you can author your equation inside a math
shortcode:
{{< math >}}
\tag*{(1)} \frac{n!}{k!(n-k)!} = \binom{n}{k}
{{< /math >}}
Use of the shortcode will automatically activate needed MathJax
script for equation display.
For inline equations (like $E=mc^2$) use the self closing form of the math
shortcode:
Albert Einstein's famous formula: {{< math "E=mc^2" />}}
For the sake of brevity, the inline content can be given as unnamed first shortcode parameter, as in the code fragment above. In a more concise form, the math content can also be assigned to a named shortcode parameter inline
: {{< math inline="E=mc^2" />}}
.
HTML slides
If you need to create fancier HTML for a slide than you can do with markdown, just add data-noprocess
to the <section> element.
<section data-noprocess>
<h1>Hello, world!</h1>
</section>
Reusable slides and sections
Sometimes you need to reuse a slide in the same presentation or across different presentations. reveal-hugo makes use of Hugo data templates to make both cases easy.
To create reusable slides, create a TOML (or JSON or YAML) file in your site’s data directory. Give it a name that reflects its content or just slides.toml
. In that file, add a key for each reusable slide. The name should reflect the slide’s content and the value should be the slide’s markdown.
thankyou = '''
# Thank you!
Any questions?
'''
💡 Tip: TOML’s multiline string syntax comes in handy here, note the ‘’’.
Each key can contain one or more slides separated by ---
and newlines. That way you can create reusable sections.
thankyou = '''
# Thank you!
---
Any questions?
'''
To render a slide from a data template, use the slide shortcode with a content attribute:
{{% slide content="slides.thankyou" /%}}
The part before the “.” is the name of the file in the data directory. The part after the dot is the key to look up in that file.
You can use all the additional slide shortcode attributes. They will be applied to every slide in the data template.
Configuration
Customize the Reveal.js presentation by setting these values in hugo.toml
or the front matter of any presentation’s _index.md
file.
reveal_hugo.theme
: The Reveal.js theme used; defaults to “black”reveal_hugo.custom_theme
: The path to a locally hosted Reveal.js theme in the static or assets folderreveal_hugo.custom_theme_compile
: If set to true, the theme will be compiled with Hugo pipes (and must live in the assets folder)reveal_hugo.custom_theme_options
: Provide a dictionary to customize theme compilation, see Hugo’s SCSS docs for a list of optionsreveal_hugo.highlight_theme
: The highlight.js theme used; defaults to “default”reveal_hugo.reveal_cdn
: The location to load Reveal.js files from; defaults to thereveal-js
folder in the static directory to support offline development. To load from a CDN instead, set this value tohttps://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0
or whatever CDN you prefer.reveal_hugo.highlight_cdn
: The location to load highlight.js files from; defaults to to thehighlight-js
folder in the static directory to support offline development. To load from a CDN instead, set this value tohttps://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0
or whatever CDN you prefer.reveal_hugo.load_default_plugins
: If set to true (default), the plugins included by default are loaded. These are markdown, highlight.js, notes and zoom.reveal_hugo.plugins
: (see below) An array of additional Reveal.js plugins to load. The appropriate files will need to have been copied into thestatic
or content directory. See here for a big list of plugins you can try. The original implementation used to accept an array of javascript files (e.g.["plugin/gallery/gallery.plugin.js"]
), but now reveal-hugo can fully load plugin javascript and css. To enable this mode, You need to provide an array of plugin definition objects withname
,source
and an optionalcss
,verbatim
andorder
fields. Reveal-hugo will try to load the plugins at the path specified bysource
. Ifverbatim=true
is used, the path is tried as-is. Otherwise, the path is resolved from the content dir orstatic
dir. Finally, thereveal_cdn
is prepended to the path if no other conditions are satisfied. Theorder
field controls the order of javascript loading and will seldomly used. See plugin-example for a plugin walkthrough.
This is how parameters will look in your hugo.toml
:
[params.reveal_hugo]
theme = "moon"
# the following supposes that menu is accessible in static dir
[[params.reveal_hugo.plugins]]
# Name the plugin. This should be the same name used to register a reveal-js plugin,
# for example: `RevealMenu`, `RevealNotes`
name = "RevealMenu"
source = "menu/menu.js"
css = "menu/menu.css"
# verbatim = true # should the css and source paths be used as-is ?
# order = 6 # control the order in which the plugin should be used.
Or in the front matter of an _index.md
file:
[reveal_hugo]
theme = "moon"
[[reveal_hugo.plugins]]
name = "gallery"
source = "plugin/gallery/gallery.plugin.js"
css = "plugin/gallery/gallery.css"
Include any other attributes in those sections that you’d like to be fed as arguments to Reveal.initialize
in snakecase, so slide_number
instead of slideNumber
. Params are converted from snakecase to camelcase before passing to Reveal.js. This is necessary to maintain the proper case of the parameters.
Here’s an example of configuring Reveal.js parameters alongside a theme and highlight.js theme:
[reveal_hugo]
theme = "moon"
highlight_theme = "solarized-dark"
slide_number = true
transition = "zoom"
See the extensive list of Reveal.js configuration options here.
Syntax highlighting
Syntax highlighting can be done with Hugo at compile-time or using Reveal.js with the pre-installed highlight.js plugin. Presentations can use both if they wish for different pieces of code.
To do highlighting with Hugo, use the highlight shortcode and check out the hugo-hl-example example presentation.
To see an example of highlighting with Reveal.js, check out the highlightjs-linenumbers-example presentation.
By default, markdown code fences will be processed with Hugo. To turn that off, add this to your hugo.toml
file:
[markup.highlight]
codeFences = false
Now, the code in the fences will be highlighted by highlight.js instead.
Custom Reveal.js themes
If you have a custom reveal theme to use (in .css form), place it in the static
folder and specify it in the configuration. For example, if your css file lives here:
| static
| stylesheets
- custom-theme.css
Then this is what you’ll put in hugo.toml
:
[params.reveal_hugo]
custom_theme = "stylesheets/custom-theme.css"
Compiling a custom Reveal.js theme with Hugo pipes
Reveal.js theme customization is easiest to do by overriding variables in the SCSS or PostCSS build process. You can take advantage of Hugo pipes to do the theme compilation. In this case, your SCSS, Saas or PostCSS file needs to live in assets:
| assets
| stylesheets
- custom-theme.scss
If you just wanted to change the presentation colors, here’s what you might put in custom-theme.scss
:
@import "../reveal-js/dist/theme/template/mixins";
@import "../reveal-js/dist/theme/template/settings";
$backgroundColor: rgb(3, 129, 45);
$mainColor: #fff;
$headingColor: #fff;
To learn more about Reveal.js theme customization, check out the Reveal.js theme docs.
This is what the front matter would look like:
[params.reveal_hugo]
custom_theme = "stylesheets/custom-theme.scss"
custom_theme_compile = true
You can also add options that will be passed to Hugo’s toCSS method:
[reveal_hugo.custom_theme_options]
targetPath = "css/custom-theme.css"
enableSourceMap = true
Check out the custom-theme-example presentation to see a working example.
Adding HTML to the layout
If you need to add something to the HTML layout, you can create partials that live at specific locations, depending on which presentation you want to customize and where you want the HTML inserted into the page.
Presentation | Before </head> | Before </body> | Before closing </div> of div.reveal |
---|---|---|---|
All | reveal-hugo/head.html | reveal-hugo/body.html | reveal-hugo/end.html |
Root | home/reveal-hugo/head.html | home/reveal-hugo/body.html | home/reveal-hugo/end.html |
Section | {section}/reveal-hugo/head.html | {section}/reveal-hugo/body.html | {section}/reveal-hugo/end.html |
This is the recommended way to add custom CSS and JavaScript to each presentation.
💡 Tip: In Hugo, partials live in the
layouts
folder:For example, if you have HTML that is to be placed before every presentation, this would be the structure:
- layouts - partials - reveal-hugo - head.html - body.html - end.html
Offline development
Offline-friendly development is the default. The Reveal.js and Highlight.js files are loaded from the static directory by default. (See above for how to use a CDN instead). If you need file:///
URLs to work, make sure to set relativeURLs
and uglyURLs
in your hugo.toml
.
relativeURLs = true
uglyURLs = true
Note: uglyURLs
isn’t strictly required, but it is useful if you’re loading against the filesystem as it makes sure that all URLs end in .html and links point directly at them instead of to a folder.
Tutorial: Add a Reveal.js presentation to an existing Hugo site
If your Hugo site already has a theme but you’d like to create a presentation from some of its content, that’s very easy.
Get the reveal-hugo
theme
Method 1 (recommended): use theme as hugo module
On your site root, check for the existence of a file go.mod
which marks your site as hugo module.
If this file is not present yet, create it by issuing this command from site root:
hugo mod init github.com/me/my-presentation
- Declare the
reveal-hugo
theme module as a dependency of your site:
hugo mod get github.com/dzello/reveal-hugo
Open hugo.toml
, look for the line theme = ...
and add reveal-hugo
to your site’s array of themes :
theme = ["your-current-theme", "github.com/dzello/reveal-hugo"]
Method 2 (traditional): use theme as git submodule
Add the reveal-hugo
theme as a submodule in the themes directory:
git submodule add git@github.com:dzello/reveal-hugo.git themes/reveal-hugo
Open hugo.toml
, look for the line theme = ...
and add reveal-hugo
to your site’s array of themes :
theme = ["your-current-theme", "reveal-hugo"]
Note: Use of Hugo versions below 0.42
With hugo < v0.42, you have to manually copy a few files out of this theme into a few of your site’s directories:
cd my-hugo-site
git clone https://github.com/dzello/reveal-hugo.git themes/reveal-hugo
cd themes/reveal-hugo
cp -r layouts static ../../
Files and directories are named such that they shouldn’t conflict with your existing content. Of course, you should double check before copying, especially the shortcodes which can’t be put under a directory.
Configure your site for presentations
Next, add the Reveal output format to your site’s hugo.toml
file
[outputFormats.Reveal]
baseName = "index"
mediaType = "text/html"
isHTML = true
Now you can add outputs = ["Reveal"]
to the front matter of any section’s _index.md
file and that section’s content will be combined into a presentation and written to index.html
. If you already have a index.html
page for that section, just change the baseName
above to reveal
and the presentation will be placed in a reveal.html
file instead.
Note: If you specify outputs = ["Reveal"]
for a single content file, you can prevent anything being generated for that file. This is handy if you other default layouts that would have created a regular HTML file from it. Only the list file is required for the presentation.
Recipes
Create a presentation from a leaf bundle or single page type
By default, reveal-hugo doesn’t create presentations for single pages (i.e. pages other than _index.md
) as it assumes those pages are pieces of a larger presentation in the section starting with _index.md
. This might not be the case if your content is structured in a leaf bundle (the main file is then index.md
with no underscore, which Hugo treats as a single page) or if you just want to put a presentation in a single file, say presentation.md
. In these cases, you just need to tell Hugo to use a different layout.
If you’re using a leaf page bundle, set the following in the front matter of the index.md
file:
layout = "bundle"
If you’re in a single page file like presentation.md
, set the following in the front matter:
layout = "list"
Create a page that lists out all presentations
See this issue for a template that you can use.
Reveal.js tips
These are some useful Reveal.js features and shortcuts.
- ’s’ - type ’s’ to enter speaker mode, which opens a separate window with a time and speaker notes
- ‘o’ - type ‘o’ to enter overview mode and scroll through slide thumbnails
- ‘f’ - type ‘f’ to go into full-screen mode
Here are a few useful Reveal.js-related tools:
- decktape for exporting a presentation as a PDF
- More revealjs themes including robot-lung and sunblind
Find many more on the Reveal.js wiki: Plugins, tools and hardware.
Implementations
Have you built something with reveal-hugo? Add a link to it here.
- dzello’s Paris Wedding Weekend Guide (source)
- DevOps Training (source)
Changelog
- 2018-08-03: The slide shortcode is now easier to use. An auto-closing version sits inside the slide instead of needing to surround its content and add a closing tag.
Contributing
Contributions are very welcome. See CONTRIBUTING.md for more details.