Examples

Functions

Built-in functions for retrieving data and generating URLs in templates.

Data Retrieval

get_page()

Retrieve any page by path or URL:

{% set about = get_page(path="about.md") %}
{% if about %}
<a href="{{ about.url }}">{{ about.title }}</a>
{% endif %}

Parameters:

Name Type Description
path String Relative source path (e.g. about.md) or URL path (e.g. /about/)

Returns: Page? (nil if not found)

Returned Properties:

Property Type
title String
description String?
url String
date String?
section String
draft Bool
weight Int
summary String?
word_count Int
reading_time Int

Examples:

{# Page in root #}
{% set contact = get_page(path="contact.md") %}

{# Page in section #}
{% set intro = get_page(path="docs/introduction.md") %}

{# Match by URL #}
{% set intro_by_url = get_page(path="/docs/introduction/") %}

get_section()

Retrieve a section by section name, source path, or URL:

{% set blog = get_section(path="blog") %}
{% if blog %}
<h2>{{ blog.title }}</h2>
<ul>
{% for p in blog.pages %}
  <li><a href="{{ p.url }}">{{ p.title }}</a></li>
{% endfor %}
</ul>
{% endif %}

Parameters:

Name Type Description
path String Section name (blog), path (blog/_index.md), or URL (/blog/)

Returns: Section? (nil if not found)

Returned Properties:

Property Type
title String
description String?
url String
path String
name String
pages Array<Page>
pages_count Int
assets Array<String>

Examples:

{# Top-level section #}
{% set docs = get_section(path="docs") %}

{# Nested section #}
{% set guides = get_section(path="docs/guides") %}

{# Match by URL #}
{% set blog = get_section(path="/blog/") %}

{# Display count #}
<p>{{ docs.pages_count }} articles</p>

get_taxonomy()

Access taxonomy terms and their pages:

{% set tags = get_taxonomy(kind="tags") %}
{% if tags %}
<ul class="tag-cloud">
{% for term in tags.items %}
  <li>
    <a href="/tags/{{ term.slug }}/">
      {{ term.name }} ({{ term.count }})
    </a>
  </li>
{% endfor %}
</ul>
{% endif %}

Parameters:

Name Type Description
kind String Taxonomy name (e.g., "tags", "categories")

Returns: Taxonomy? (nil if not found)

Returned Properties:

Property Type
name String
items Array<Term>

Term Properties:

Property Type
name String
slug String
pages Array<Page>
count Int

get_taxonomy_url()

Generate URL for a taxonomy term:

<a href="{{ get_taxonomy_url(kind='tags', term='crystal') }}">
  Crystal articles
</a>

Parameters:

Name Type Description
kind String Taxonomy name
term String Term name

Returns: String (absolute URL)


Data Loading

load_data()

Load external data files (JSON, TOML, YAML, CSV):

{% set menu = load_data(path="data/menu.json") %}
{% for item in menu %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% endfor %}

Parameters:

Name Type Description
path String Path to data file

Returns: Parsed data or nil

Supported Formats:

Extension Format
.json JSON
.toml TOML
.yaml, .yml YAML
.csv CSV (array of arrays)

Examples:

JSON (data/team.json):

[
  {"name": "Alice", "role": "Developer"},
  {"name": "Bob", "role": "Designer"}
]
{% set team = load_data(path="data/team.json") %}
<ul>
{% for member in team %}
  <li>{{ member.name }} - {{ member.role }}</li>
{% endfor %}
</ul>

TOML (data/social.toml):

[[links]]
name = "Twitter"
url = "https://twitter.com/example"
{% set social = load_data(path="data/social.toml") %}
{% for link in social.links %}
<a href="{{ link.url }}">{{ link.name }}</a>
{% endfor %}

Environment

env()

Read environment variables in templates:

{{ env("ANALYTICS_ID") }}
{{ env("API_KEY", default="none") }}

Parameters:

Name Type Description
name String Environment variable name
default String? Fallback value if variable is unset (optional)

Returns: String (env var value, default, or empty string)

If the variable is not set and no default is provided, an empty string is returned and a build warning is logged.

Examples:

{# Google Analytics #}
{% if env("GA_ID") %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ env("GA_ID") }}"></script>
{% endif %}

{# API endpoint with fallback #}
<script>
  const API = "{{ env("API_URL", default="https://api.example.com") }}";
</script>

URL Functions

url_for()

Generate URL with base_url:

<a href="{{ url_for(path='/about/') }}">About</a>
<img src="{{ url_for(path='/images/logo.png') }}">

Parameters:

Name Type Description
path String Path to convert

Returns: String (absolute URL)


get_url()

Alias for url_for(). You can use either name:

<a href="{{ get_url(path='/about/') }}">About</a>

asset()

Resolve a bundled or fingerprinted asset to its final URL. When the asset pipeline is enabled, the input name is looked up in the build manifest so you always get the hashed filename.

<link rel="stylesheet" href="{{ asset(name='main.css') }}">
<script src="{{ asset(name='app.js') }}"></script>

Parameters:

Name Type Description
name String Bundle or asset name (e.g. main.css, app.js)

Returns: String — absolute URL under base_url. When no manifest entry is found, the name is returned as a path under base_url unchanged, so templates keep working before you turn the pipeline on.


asset_url()

Alias for asset(). Use whichever reads better in your templates.


now()

Get current datetime:

{# Default format #}
<p>Generated: {{ now() }}</p>

{# Custom format #}
<p>Year: {{ now(format="%Y") }}</p>
<p>Date: {{ now(format="%B %d, %Y") }}</p>

Parameters:

Name Type Description
format String? Date format string (optional)

Returns: String

Format Codes:

Code Description Example
%Y Year 2025
%m Month (01-12) 01
%d Day (01-31) 15
%B Month name January
%b Month abbr Jan
%H Hour (00-23) 14
%M Minute 30
%S Second 45

Media Functions

resize_image()

Returns a resized image variant. When image processing is enabled, this returns the URL to an automatically generated resized image. Otherwise, it returns the original URL.

{% set img = resize_image(path="/images/hero.jpg", width=640) %}
<img src="{{ img.url }}" width="{{ img.width }}">

Parameters:

Name Type Description
path String Image path (e.g., /images/photo.jpg)
width Int Requested width in pixels (0 = original)
height Int Requested height in pixels (0 = original)

Returns: Object with properties:

Property Type Description
url String URL to the resized variant (or original if unavailable)
width Int Requested width
height Int Requested height
lqip String Base64 data URI of a tiny JPEG placeholder (empty if LQIP disabled)
dominant_color String Hex color string of the image's dominant color, e.g. #a3b2c1 (empty if LQIP disabled)

The function selects the closest available width from the configured widths. If you request width=500 and the configured widths are [320, 640, 1024], it returns the 640px variant (smallest width >= requested). If nothing is large enough, it falls back to the largest available.

The lqip and dominant_color properties require [image_processing.lqip] to be enabled. When disabled, they return empty strings.

Examples:

{# Single resized image #}
{% set img = resize_image(path="/images/hero.jpg", width=800) %}
<img src="{{ img.url }}" alt="Hero">

{# Responsive srcset #}
{% set sm = resize_image(path="/images/hero.jpg", width=320) %}
{% set md = resize_image(path="/images/hero.jpg", width=640) %}
{% set lg = resize_image(path="/images/hero.jpg", width=1024) %}
<img
  src="{{ md.url }}"
  srcset="{{ sm.url }} 320w, {{ md.url }} 640w, {{ lg.url }} 1024w"
  sizes="(max-width: 640px) 320px, (max-width: 1024px) 640px, 1024px"
>

{# With page image from front matter #}
{% if page.image %}
  {% set thumb = resize_image(path=page.image, width=320) %}
  <img src="{{ thumb.url }}" alt="{{ page_title }}">
{% endif %}

{# LQIP blur-up placeholder #}
{% set img = resize_image(path="/images/hero.jpg", width=1024) %}
<img
  src="{{ img.url }}"
  style="background-image: url({{ img.lqip }}); background-size: cover;"
  loading="lazy"
  alt="Hero"
>

{# Dominant color placeholder #}
{% set img = resize_image(path="/images/photo.jpg", width=640) %}
<img
  src="{{ img.url }}"
  style="background-color: {{ img.dominant_color }}"
  loading="lazy"
  alt="Photo"
>

Requires [image_processing] to be enabled in config.toml. See Image Processing for setup details.


Best Practices

Always Check for nil

{% set page = get_page(path="featured.md") %}
{% if page %}
{{ page.title }}
{% else %}
<p>Coming soon</p>
{% endif %}

Cache Function Results

{# Good: Single lookup #}
{% set blog = get_section(path="blog") %}
<h2>{{ blog.title }}</h2>
<p>{{ blog.pages_count }} posts</p>

{# Avoid: Multiple lookups #}
<h2>{{ get_section(path="blog").title }}</h2>
<p>{{ get_section(path="blog").pages_count }} posts</p>

Organize Data Files

data/
├── navigation/
│   ├── main.json
│   └── footer.json
├── team.yaml
└── products.toml

See Also