the long and the shortcodes of it
I've just spent a little time trying to learn how to use Nikola's "shortcodes", and I've learned enough delicate things that I want to write them down for later. Not least, there are descriptions of the shortcode syntax on two different very long and identically-formatted pages, the Nikola handbook and the guide to extending Nikola.
There's also some overlap between the Markdown-supported shortcodes versus a set of reStructuredText extensions.
Built-in shortcodes
The short version is that there are some magic words that you can
include in a Markdown content file, using something like Jinja's
template syntax, which do programmy things. One is raw, which
doesn't seem to be able to display itself because of some recursion
thing. But in general,
{{% name parameters %}}
makes things happen. There are a number of built-in shortcodes, whose examples in the manual I won't duplicate, but I'll list them here:
-
- chart
- This actually draws a graph in the page, which would be a fun thing to play with later.
-
- doc
- This seems to be the correct way to do internal linking, using the stub names. For example, My previous post was improbable units.
-
- emoji
- 😢
-
- listing
-
p-exam/poisson.py (Source)
-
- media
It doesn't seem to work magically for embedding a local video file.
-
- thumbnail
- I haven't messed with images, but I think there's some magic thumbnailing happening. Perhaps this is how I'll use it.
-
- template
- This lets you put jinja template code right in the document.
- The square of 6 is 36
- The square of 7 is 49
- The square of 8 is 64
- The square of 9 is 81
Custom template shortcodes
A template file named shortcodes/mycode.tmpl will be executed when
the source text contains
{{% foo bar=bla baz bux %}}
Here's a little template that implements foo:
This fragment should appear in the text. <ul> {% for number in range(6,10) %} <li>The square root of {{number}} is {{ '{:0.3f}'.format(number**0.5) }}</li> {% endfor %} </ul>
And here's what it does:
This fragment should appear in the text.
- The square root of 6 is 2.449
- The square root of 7 is 2.646
- The square root of 8 is 2.828
- The square root of 9 is 3.000
Exploration by introspection
shortcodes/introspection.tmpl (Source)
This template prints some information about the <code>post</code> object. <table style="font-family: monospace; font-size: xx-small;"> <tr> <th> key </th> <th> type </th> <th> size </th> </tr> {% for key in post.__dict__ %} <tr> <td>{{ key }}</td> <td>{{ post[key].__class__.__name__ }}</td> {% if post[key].__class__ == post['compile_html'].__class__ %} <td> callable method </td> {% elif post[key].__class__ == post['messages'].__class__ %} <td> [something complicated] </td> {% elif post[key].__class__ in (dict, list, tuple) %} <td>{{ post[key] | length }}</td> {% else %} <td>{{ post[key] }}</td> {% endif %} </tr> {% endfor %} </table>
This template prints some information about the
postobject.
key type size config dict 204 current_time datetime 2026-01-04 14:53:59.901412-06:00 base_url str https://mahurin.us/robtasm/ strip_indexes bool True index_file str index.html pretty_urls bool True default_lang str en translations dict 1 skip_untranslated bool False _default_preview_image NoneType None types_to_hide_title list [] source_path str posts/2025/07/03/the-long-and-the-shortcodes-of-it.md post_name str posts/2025/07/03/the-long-and-the-shortcodes-of-it base_path str cache/posts/2025/07/03/the-long-and-the-shortcodes-of-it.html _base_path str cache/posts/2025/07/03/the-long-and-the-shortcodes-of-it.html metadata_path str posts/2025/07/03/the-long-and-the-shortcodes-of-it.meta compiler CompileMarkdown is_post bool True messages Functionary [something complicated] _template_name str post.tmpl compile_html method callable method demote_headers int 1 _dependency_file_fragment defaultdict defaultdict( , {'en': [(True, .create_lambda. . at 0x7f3291fcbec0>)], None: []}) _dependency_file_page defaultdict defaultdict( , {'en': [], None: []}) _dependency_uptodate_fragment defaultdict defaultdict( , {'en': [], None: []}) _dependency_uptodate_page defaultdict defaultdict( , {'en': [], None: []}) _depfile defaultdict defaultdict( , {}) metadata_extractors_by dict 4 translated_to set {'en'} folder_relative str 2025/07/03 folder_base TranslatableSetting posts folders dict 1 folder str posts/2025/07/03 _is_two_file bool False meta Functionary [something complicated] used_extractor Functionary [something complicated] date datetime 2025-07-03 17:03:10-05:00 updated datetime 2025-07-03 17:03:10-05:00 data Functionary [something complicated] category_from_destpath bool False _tags dict 1 publish_later bool False use_in_feeds bool True url_type NoneType None _next_post Post _prev_post Post
Now that I know how to poke around on the inside of these things, I am much more likely to be able to figure out how they work.