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
post
object.
key type size config dict 204 current_time datetime 2025-09-30 23:58:13.299937-05: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 0x7f0d61bc8220>)], 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.