Shortcodes are shorthand to make managing content easier. They can be used in content or templates.

In content they are as follows.

<sc>figure('A bald eagle observes', 'Eagle', '/assets/images/eagle.jpg')</sc>

Or they can be used in templates like so.

<% f = (shortcodes['figure'](site, page, 'A bald eagle observes', 'Eagle', '/assets/images/eagle.jpg')) %>

The shortcode figure will generate the following HTML.

<img src="/assets/images/eagle.jpg" alt="Eagle">
<figcaption>A bald eagle observes</figcaption>

Which looks like this:

A bald eagle observes

Creating new shortcodes

Shortcodes are Python functions(def) defined in, in the site root directory. Shortcode functions must:

The figure shortcode above could be written in as follows. Remember that all shortcode functions must accept site and page arguments.

def figure(site, page, caption, alternative_text, src_path):

    html = '<figure>\n'
    html += '<img src="' + src_path + '" alt="' + alternative_text + '">\n'
    html += '<figcaption>' + caption + '</figcaption>\n'
    html += '</figure>\n'

    return html

Site and page

Most shortcodes will want access to either the site or page attributes that Pagegen creates. To give a shortcode access to them, they are automatically passed to the shortcode function. This happens automatically from the <sc> tag, but need to be explicitly used when calling shortcodes in the templates.

These variables are automatically available in all templates. The trade off to this inconsistency, between <sc> tag and template arguments, is to keep the tags more succinct.

Return reStructuredText or Markdown?

Shortcodes are run before the page is converted to html, meaning the shortcode return value is evaluated as either reStructuredText or Markdown, dependant on the page. Therefore shortcodes need to return strings that are compatible with the markup engine that will process them further.

The example above will work with Markdown, but to make it compatible with reStructuredText additional markup needs to be added.

def figure(site, page, caption, alternative_text, src_path):

    html = '.. raw:: html\n\n'
    html = '    <figure>\n'
    html += '   <img src="' + src_path + '" alt="' + alternative_text + '">\n'
    html += '   <figcaption>' + caption + '</figcaption>\n'
    html += '   </figure>\n'

    return html

Shortcodes to handle the different markups

The figure shortcode example can be updated to use the page object to determine if it should return markup for reStructuredText or Markdown.

def figure(site, page, caption, alternative_text, src_path):

    if page.markup == 'rst':
        html_prefix = '.. raw:: html\n\n\t'
        indent = '\t'
    else: # Markdown
        html_prefix = ''
        indent = ''

    html = html_prefix + '<figure>\n'
    html += indent + '<img src="' + src_path + '" alt="' + alternative_text + '">\n'
    html += indent + '<figcaption>' + caption + '</figcaption>\n'
    html += indent + '</figure>\n'

    return html

Built in shortcodes

Pagegen ships with ready to use built in shortcodes. Built in shortcodes will be overridden if a shortcode defined in has the same name.


When using <sc> tag, omit the site and page arguments, they get passed automatically. For instance, use <sc>categories()</sc> to call the categories shortcode, no need to specify site and page, they are passed implicitly.

Shortcode nameDescription
categories(site, page)List page categories
image(site, page, image_source, alt_attribute, target_dir=None, image_class=None, image_size=None)Return img tag and optionally resize image using image_class settings from site.conf or image_size(XxY) argument. Maintains aspect ration by cropping with center gravity and resize to dimensions
list_authors(site, page)List authors
list_posts(site, page, posts_dir, max_posts_limit)List posts found in posts_dir
menu(site, page)Generate fully recursive site menu
page_url(site, page, page_path)Return url to page, taking into account if default extension.
tags(site, page)List page tags

In addition pagegen --init will include shortcodes.py_example to illustrate further.