Examples

Shortcodes

Shortcodes are reusable template snippets you can use in Markdown content. Custom shortcodes are Jinja2 templates placed in templates/shortcodes/ — see Template Syntax for the templating language reference.

Using Shortcodes

Two syntax patterns work in content files:

{%raw%}{{ shortcode_name(arg1="value", arg2="value") }}{%endraw%}

Or explicitly:

{%raw%}{{ shortcode("shortcode_name", arg1="value") }}{%endraw%}

Built-in Shortcodes

Hwaro ships with built-in shortcodes that work out of the box — no template files needed.

youtube

Embed a YouTube video.

{%raw%}{{ youtube(id="dQw4w9WgXcQ") }}
{{ youtube(id="dQw4w9WgXcQ", width="800", height="450") }}{%endraw%}
Param Default Description
id (required) YouTube video ID
width 560 Player width
height 315 Player height
title YouTube Video Accessible title

vimeo

Embed a Vimeo video.

{%raw%}{{ vimeo(id="123456789") }}{%endraw%}
Param Default Description
id (required) Vimeo video ID
width 560 Player width
height 315 Player height
title Vimeo Video Accessible title

gist

Embed a GitHub Gist.

{%raw%}{{ gist(user="octocat", id="abc123") }}
{{ gist(user="octocat", id="abc123", file="hello.rb") }}{%endraw%}
Param Default Description
user (required) GitHub username
id (required) Gist ID
file (none) Specific file to show

alert / callout

Display an alert box. Use as a block shortcode to wrap content.

{%raw%}{% alert(type="warning", title="Caution") %}Be careful with this!{% end %}
{% callout(type="tip") %}Here is a helpful tip.{% end %}{%endraw%}
Param Default Description
type info info, warning, danger, tip, success
title (none) Optional title

figure

Image with optional caption.

{%raw%}{{ figure(src="/img/photo.jpg", alt="A photo", caption="My caption") }}{%endraw%}
Param Default Description
src (required) Image URL
alt "" Alt text
caption (none) Caption below image
width (none) Image width
height (none) Image height

tweet

Embed a tweet.

{%raw%}{{ tweet(user="jack", id="20") }}{%endraw%}
Param Default Description
user (required) Twitter username
id (required) Tweet ID

codepen

Embed a CodePen.

{%raw%}{{ codepen(user="chriscoyier", id="gfdDu") }}
{{ codepen(user="chriscoyier", id="gfdDu", tab="css,result", height="400") }}{%endraw%}
Param Default Description
user (required) CodePen username
id (required) Pen ID
tab result Default tab(s)
height 300 Embed height
title CodePen Embed Accessible title

To override any built-in shortcode, create a file with the same name in templates/shortcodes/ (e.g., templates/shortcodes/youtube.html). User templates always take priority.

Creating Custom Shortcodes

Shortcode templates live in templates/shortcodes/.

Example: Alert Box

Create templates/shortcodes/alert.html:

{% if type and message %}
<div class="alert alert-{{ type }}">
  {{ message | safe }}
</div>
{% endif %}

Use in content:

{%raw%}{{ alert(type="warning", message="This is important!") }}{%endraw%}

Output:

<div class="alert alert-warning">
  This is important!
</div>

Example: YouTube Embed

Create templates/shortcodes/youtube.html:

{% if id %}
<div class="video-container">
  <iframe 
    src="https://www.youtube.com/embed/{{ id }}"
    frameborder="0"
    allowfullscreen>
  </iframe>
</div>
{% endif %}

Use in content:

{%raw%}{{ youtube(id="dQw4w9WgXcQ") }}{%endraw%}

Example: Figure with Caption

Create templates/shortcodes/figure.html:

<figure>
  <img src="{{ src }}" alt="{{ alt | default(value='') }}">
  {% if caption %}
  <figcaption>{{ caption }}</figcaption>
  {% endif %}
</figure>

Use in content:

{%raw%}{{ figure(src="/images/photo.jpg", alt="A photo", caption="My caption") }}{%endraw%}

You can create a gallery that automatically lists images found in the same directory as the page (Page Bundle).

Create templates/shortcodes/gallery.html:

<div class="gallery">
{% for asset in page.assets -%}
  {%- if asset is matching("[.](jpg|png)$") -%}
    {% set image = resize_image(path=asset, width=240, height=180) %}
    <a href="{{ get_url(path=asset) }}" target="_blank">
      <img src="{{ image.url }}" alt="{{ asset }}" />
    </a>
  {%- endif %}
{%- endfor %}
</div>

Use in content (inside a Page Bundle directory):

{%raw%}{{ gallery() }}{%endraw%}

This will render a grid of all JPG and PNG images found alongside the Markdown file.

Block Shortcodes

Block shortcodes wrap content between opening and closing tags:

{%raw%}{% note() %}
This is the **body** content of the shortcode.
{% end %}{%endraw%}

The body is passed to the shortcode template as the body variable. Markdown conversion is not applied automatically — use the markdownify filter in your template if needed:

<div class="note">
  {{ body | markdownify | safe }}
</div>

Or use the body as-is for raw content:

<div class="note">{{ body }}</div>

Nested Shortcodes

Block shortcodes can be nested up to 5 levels deep:

{%raw%}{% outer() %}
  Some text with {{ inner(type="info") }} inside.
{% end %}{%endraw%}

Argument Syntax

Named Arguments

Arguments support multiple quote styles:

{%raw%}{{ alert(type="warning", message="Double quotes") }}
{{ alert(type='info', message='Single quotes') }}
{{ alert(type=danger, message=No quotes for simple values) }}{%endraw%}

Positional Arguments

When no key=value syntax is used, arguments are assigned as _0, _1, etc.:

{%raw%}{{ youtube("dQw4w9WgXcQ") }}{%endraw%}

In the shortcode template, access via {{ _0 }}:

<iframe src="https://www.youtube.com/embed/{{ _0 }}"></iframe>

Built-in Variables

Shortcodes have access to:

{# In shortcode template #}
<a href="{{ site.base_url }}/{{ url }}">{{ text }}</a>

Tips

Validate Arguments

Always check for required arguments:

{% if not url %}
<p class="error">Missing url parameter</p>
{% else %}
<a href="{{ url }}">{{ text | default(value="Link") }}</a>
{% endif %}

Use Safe Filter for HTML

When passing HTML content:

{{ content | safe }}

Organize Shortcodes

Group related shortcodes:

templates/shortcodes/
├── alert.html
├── youtube.html
├── figure.html
├── code/
│   ├── tabs.html
│   └── snippet.html
└── social/
    ├── twitter.html
    └── github.html

See Also