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
- Data Model — Site, Section, Page types
- Filters — Value transformation