Although Markdown is good for writing, it isn't great when you need write inline HTML to add some styling for example.

To solve this, Zola borrows the concept of shortcodes from WordPress. In our case, a shortcode corresponds to a template defined in the templates/shortcodes directory or a built-in one that can be used in a Markdown file. If you want to use something similar to shortcodes in your templates, try Tera macros.

Writing a shortcode

Let's write a shortcode to embed YouTube videos as an example. In a file called youtube.html in the templates/shortcodes directory, paste the following:

<div {% if class %}class="{{class}}"{% endif %}>
    <iframe
        src="https://www.youtube.com/embed/{{id}}{% if autoplay %}?autoplay=1{% endif %}"
        webkitallowfullscreen
        mozallowfullscreen
        allowfullscreen>
    </iframe>
</div>

This template is very straightforward: an iframe pointing to the YouTube embed URL wrapped in a <div>. In terms of input, this shortcode expects at least one variable: id. Because the other variables are in an if statement, they are optional.

That's it. Zola will now recognise this template as a shortcode named youtube (the filename minus the .html extension).

The Markdown renderer will wrap an inline HTML node such as <a> or <span> into a paragraph. If you want to disable this behaviour, wrap your shortcode in a <div>.

Shortcodes are rendered before the Markdown is parsed so they don't have access to the table of contents. Because of that, you also cannot use the get_page/get_section/get_taxonomy global functions. It might work while running zola serve because it has been loaded but it will fail during zola build.

Using shortcodes

There are two kinds of shortcodes:

In both cases, the arguments must be named and they will all be passed to the template.

Lastly, a shortcode name (and thus the corresponding .html file) as well as the argument names can only contain numbers, letters and underscores, or in Regex terms [0-9A-Za-z_]. Although theoretically an argument name could be a number, it will not be possible to use such an argument in the template.

Argument values can be of one of five types:

Malformed values will be silently ignored.

Both types of shortcode will also get either a page or section variable depending on where they were used and a config variable. These values will overwrite any arguments passed to a shortcode so these variable names should not be used as argument names in shortcodes.

Shortcodes without body

Simply call the shortcode as if it was a Tera function in a variable block. All the examples below are valid calls of the YouTube shortcode.

Here is a YouTube video:

{{ youtube(id="dQw4w9WgXcQ") }}

{{ youtube(id="dQw4w9WgXcQ", autoplay=true) }}

An inline {{ youtube(id="dQw4w9WgXcQ", autoplay=true, class="youtube") }} shortcode

Note that if you want to have some content that looks like a shortcode but not have Zola try to render it, you will need to escape it by using {{/* and */}} instead of {{ and }}.

Shortcodes with body

Let's imagine that we have the following shortcode quote.html template:

<blockquote>
    {{ body }} <br>
    -- {{ author}}
</blockquote>

We could use it in our Markdown file like so:

As someone said:

{% quote(author="Vincent") %}
A quote
{% end %}

The body of the shortcode will be automatically passed down to the rendering context as the body variable and needs to be on a new line.

If you want to have some content that looks like a shortcode but not have Zola try to render it, you will need to escape it by using {%/* and */%} instead of {% and %}. You won't need to escape anything else until the closing tag.

Built-in shortcodes

Zola comes with a few built-in shortcodes. If you want to override a default shortcode template, simply place a {shortcode_name}.html file in the templates/shortcodes directory and Zola will use that instead.

YouTube

Embed a responsive player for a YouTube video.

The arguments are:

Usage example:

{{ youtube(id="dQw4w9WgXcQ") }}

{{ youtube(id="dQw4w9WgXcQ", autoplay=true) }}

{{ youtube(id="dQw4w9WgXcQ", autoplay=true, class="youtube") }}

Result example:

Vimeo

Embed a player for a Vimeo video.

The arguments are:

Usage example:

{{ vimeo(id="124313553") }}

{{ vimeo(id="124313553", class="vimeo") }}

Result example:

Streamable

Embed a player for a Streamable video.

The arguments are:

Usage example:

{{ streamable(id="92ok4") }}

{{ streamable(id="92ok4", class="streamble") }}

Result example:

Gist

Embed a Github gist.

The arguments are:

Usage example:

{{ gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57") }}

{{ gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57", class="gist") }}

Result example: