Roq Advanced Stuff
| If you find any issue or missing info, be awesome and edit this document to help others Roqers. |
Built-in features
Roq and its themes include several built-in features for SEO, feeds, and discoverability. The base theme provides the essential tags (SEO, favicon, Web Bundler), while the default theme builds on top of it with a full layout, dark mode, sidebar, and more. If you are using either theme, most of these features are already enabled. Configure them through your site index frontmatter or by adding content files.
Pagination
Adding pagination to your Roq site is an easy way to improve content navigation. Let’s walk through how to implement pagination and customize its behavior in your site.
Step 1: Iterate on the paginated collection
First, include the following in your FrontMatter header on the page which will iterate on the paginated collection:
paginate: posts
Next, in your template, loop through the paginated posts using:
{#for post in site.collections.posts.paginated(page.paginator)} (1)
<article class="post">
...
</article>
{/for}
{#include partials/pagination.html/}
| 1 | Calling .paginated(page.paginator) will resolve to the posts for the computed page. |
Step 2: Including Pagination Controls
To add pagination controls, use the provided fm/pagination.html in your own partials/pagination.html:
{#include fm/pagination.html}
{#newer}<i class="fa fa-long-arrow-left" aria-hidden="true"></i>{/newer}
{#older}<i class="fa fa-long-arrow-right" aria-hidden="true"></i>{/older}
{/include}
| If you want to write your own controls, find inspiration in the FM sources fm/pagination.html. |
Just by doing so, Roq will generate a bunch of pages based on the pagination setting. For example with a pagination size of 4 and with 9 posts, you would get:
-
index.html(posts 1 to 4) -
posts/page-2(posts 5 to 8) -
posts/page-3(post 9)
| the first page uses the declaring page link. |
You can further customize your pagination by setting the page size and link format:
paginate:
size: 4
collection: posts
link: posts/page-:page
With these steps, you can create a flexible pagination system to improve your site’s navigation.
Themes
Browse all available themes in the Plugins & Themes directory.
Overriding theme
In Roq, you can override theme partials or layouts.
To override a theme partial, it is very simple, you just need to add the same template in your site.
For example, adding your own templates/partials/roq-default/pagination.html
will override the one from the default Roq theme
To override a theme layout, you need to insert an extra layout layer. This allows you to override only specific sections of the theme layout, without duplicating the entire layout structure.
Roq layouts leverage Qute include under the hood.
It is possible to define insert sections that provide overridable default content.
|
Example
Let’s override the roq-default theme’s main layout so that our customizations apply everywhere it is used.
---
theme-layout: main (1)
---
{#insert /} (2)
{#description} (3)
Here I can override the description section
{/}
{#footer}
<footer>
And here the footer
</footer>
{/}
| 1 | Inherits from the theme layout: theme-layout: main explicitly targets the theme’s main layout as a base. |
| 2 | Inheritance mechanism: {#insert /} ensures that this layout will inherit sections defined in the theme layout. |
| 3 | Override specific sections: You can override individual sections such as description and footer without affecting other parts of the layout. |
Now, everywhere layout: main is used (even in the theme), your override will be used.
How it Works Internally
Roq handles theme layouts in two layers:
-
The original theme layouts are always kept under
theme-layouts/…. These are the base templates that overrides can extend for partial customization. -
Roq also produces corresponding site layouts for each theme layout. Site layouts are the versions that your pages actually reference.
When Roq builds your site, it checks for overrides:
-
If you provide an override: Roq uses your override as the site layout, while still keeping the theme’s original layout under
theme-layouts/…for inheritance. -
If you don’t provide an override: Roq copies the theme layout as the site layout, so it can be used directly.
This mechanism ensures you only need to override the parts you want to customize, everything else automatically falls back to the theme.
Developing a theme
To develop a theme, create a Maven module which will contain the theme layouts, partials, scripts and styles.
.
└── main
├── resources
│ ├── application.properties
│ └── templates
│ ├── partials
│ │ └── roq-default (1)
│ │ ├── head.html
│ │ ├── pagination.html
│ │ ├── sidebar-about.html
│ │ ├── sidebar-contact.html
│ │ ├── sidebar-copyright.html
│ │ └── sidebar-menu.html
│ └── theme-layouts (2)
│ └── roq-default
│ ├── default.html
│ ├── index.html
│ ├── main.html
│ ├── page.html
│ ├── post.html
│ └── tag.html
└── web
├── roq.js
├── roq.scss
| 1 | You can add partials for your theme, they need to be located in a directory with the theme name templates/partials/{theme-name}/. |
| 2 | Layouts need to be declared in theme-layouts/ using a directory with the theme name templates/theme-layouts/{theme-name}/. |
Same as for a site, scripts and styles can either be added to src/main/resources/META-INF/resources or bundled using Maven esbuild plugin:
<plugin>
<groupId>io.mvnpm</groupId>
<artifactId>esbuild-maven-plugin</artifactId>
<version>0.0.2</version>
<executions>
<execution>
<id>esbuild</id>
<goals>
<goal>esbuild</goal>
</goals>
</execution>
</executions>
<configuration>
<entryPoint>roq.js</entryPoint> (1)
</configuration>
<dependencies> (2)
<dependency>
<groupId>org.mvnpm.at.fortawesome</groupId>
<artifactId>fontawesome-free</artifactId>
<version>6.6.0</version>
</dependency>
<dependency>
<groupId>org.mvnpm.at.fontsource</groupId>
<artifactId>pt-serif</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</plugin>
| 1 | Add your esbuild entrypoint from src/main/resources/web |
| 2 | Add mvnpm or webjars dependencies |
This bundle will be available in /static/bundle/roq.js and /static/bundle/roq.css which can be used in your theme html <head>
You need to create an application.properties:
site.theme=roq-default (1)
| 1 | This allows site referencing the theme to default to this theme. |
Links & Urls
The output location of pages and documents is determined by the FrontMatter link key. This link value can include placeholders, which will be dynamically replaced with relevant values for routing.
| Those links are also available in the Qute data to allow Creating links between your pages. |
Link placeholders
| Type of page | Placeholder | Description | Example Output |
|---|---|---|---|
All |
|
The file path of the page, slugified (converted to a URL-friendly format) without the extension. If a |
|
All |
|
The raw file path of the page without the extension. |
|
All |
|
The directory portion of the page’s file path, slugified. For index files (directory pages), this is the grandparent directory (since the slug already captures the directory name). Empty for files at the content root. Use :dir[N] to skip the first N path segments — for example, :dir[2] drops the first two folders, giving a link of |
|
All |
|
The slugified title of the page, derived from the title. Defaults to the |
|
All |
|
The case-preserving slugified title of the page, derived from the title. Defaults to the |
|
All |
|
The slugified name of the file (or directory if index). If the filename contains a date (e.g., '2025-08-21-My-Blog-Post.md'), the date portion will be stripped away. This behavior mimics that found in Jekyll builds, making any migrations simpler. |
|
All |
|
The case-preserving slugified name of the file (or directory if index). If the filename contains a date (e.g., '2025-08-21-My-Blog-Post.md'), the date portion will be stripped away. This behavior mimics that found in Jekyll builds, making any migrations simpler. |
|
All |
|
The file extension with the dot. Empty for all files with html output (md, asciidoc, html, …). |
|
All |
|
Force the output file extension. |
|
All |
|
The year of the page’s date or the current year if the date is not available. |
|
All |
|
The month (formatted as two digits) of the page’s date or the current month if the date is not available. |
|
All |
|
The day (formatted as two digits) of the page’s date or the current day if the date is not available. |
|
Document |
|
Represents the collection to which the document belongs, such as a specific category or folder name. |
|
Paginated |
|
Represents the current page. |
|
The slug derivation replaces all non-alphanumeric characters by - to make them url friendly.
|
Default link value:
-
for pages:
/:path:ext(configurable viasite.page-link). -
for documents in collections:
/:collection/:slug/(configurable viasite.collections.<name>.link). -
for paginated page:
/:collection/page:page/.
Global link template configuration
Instead of setting link in the frontmatter of every page, you can configure default link templates globally in application.properties:
# Default link template for non-collection pages
site.page-link=/:slug/
# Default link template for a specific collection
site.collections.posts.link=/:collection/:year/:month/:name/
These global defaults apply to all pages or collection documents that don’t have an explicit link in their frontmatter or layout. A frontmatter link always takes precedence over the global configuration.
You can also define link in a layout to affect all the pages using that layout.
|
Creating links between your pages
The pages links are automatically converted to urls by Roq, they are available in the site.url and the page.url variables. This makes creating links very easy:
<a href="{=site.url}">Back to main page</a>
or to get the next page url in a document:
<a href="{=page.next.url}">{=page.next.title}</a>
or when iterating on documents:
{#for post in site.collections.posts}
<a href="{=post.url}">{=post.title}</a>
{/for}
or also to manually retrieve a page url with site.page(sourcePath):
<a href="{=site.page('foo.html').url}">{=site.page('foo.html').title}</a>
By default, url will be rendered as the path from the site root. You can also get the full absolute url (i.e. from http(s)://) by using absolute on any url (e.g. {=site.url.absolute}).
|
Alternative expression syntax
Qute supports an alternative expression syntax where output expressions use {=expr} instead of {expr}. This makes templates safer when content contains curly braces (e.g. code samples, JSON) since only {=…} and {#…} are interpreted as Qute expressions, everything else is plain text.
| Standard Qute syntax is still the default, but this will change in a future version. New projects already have alt syntax enabled via the generated config. We recommend setting the config explicitly so your project is ready. All examples in this documentation use the alternative expression syntax. |
To enable it, add to your configuration:
quarkus.qute.alt-expr-syntax=true
With this enabled, templates use {=page.title} for expressions and {#for …} / {#include …} for sections (sections are unaffected). Regular {foo} is treated as plain text.
Escaping pages content
There are cases where you might not want your page content to be parsed by Qute, to avoid conflicts with the content. You have different options:
-
Configure it globally via
site.escaped-pages(globs are allowed):config/application.propertiessite.escaped-pages=posts/escaped**,my-page.html -
Set it in FrontMatter by adding
escape: truein your page data (not working with layouts). -
Escape inline content by wrapping the section with
{|and|}, or by manually escaping Qute expressions using\{.
Setting the Root Path for your site (base-path)
When the entire Roq site is under a root path such as mysite.io/foo/, configure quarkus.http.root-path in the Quarkus configuration:
quarkus.http.root-path=/foo
Environment variable: QUARKUS_HTTP_ROOT_PATH
| For GitHub Pages, this is already detected and handled by the Roq GitHub Action, no need to do anything. |
Data (advanced)
For basic data usage (data files, directories, and template access), see the Data section in the basics guide.
Type-safe mapping
Use @DataMapping on a record to create a typed CDI bean from a data file:
import io.quarkiverse.roq.data.runtime.annotations.DataMapping;
@DataMapping("mountain") (1)
public record Mountain(String name, Integer elevation) {}
| 1 | The value must match the data filename (without extension). |
Then use it in templates:
{=cdi:mountain.name}: {=cdi:mountain.elevation}
Array data files
For data files where the root element is a JSON/YAML array, use Type.ARRAY_FILE:
@DataMapping(value = "mountains", type = DataMapping.Type.ARRAY_FILE)
public record Mountains(List<Mountain> list) {} (1)
| 1 | The record must have a single List<T> constructor parameter. |
{#for mountain in cdi:mountains.list}
{=mountain.name}: {=mountain.elevation}
{/for}
Directory mapping
For type-safe access to data directories, use ARRAY_DIR or OBJECT_DIR with @DataMapping:
@DataMapping(value = "heroes", type = DataMapping.Type.ARRAY_DIR) (1)
public record HeroList(List<Hero> list) {
public record Hero(String name, String city) {}
}
| 1 | The value must match the data directory name |
{#for hero in cdi:heroList.list}
{=hero.name} from {=hero.city}
{/for}
@DataMapping(value = "heroes", type = DataMapping.Type.OBJECT_DIR)
public record HeroMap(Map<String, Hero> map) {
public record Hero(String name, String city) {}
}
{=cdi:heroMap.map.batman.name}
Type reference
| Type | Source | Constructor | Description |
|---|---|---|---|
|
Single file |
Direct fields |
Default. Maps a file to a typed object |
|
Single file (array) |
|
Maps a root-level array file to a list |
|
Directory |
|
Maps each file in a directory to a list item |
|
Directory |
|
Maps each file to a map entry (filename as key) |
Collections from data
While plain data files let you display a list of items in an existing page, a data collection goes further: it generates a dedicated page for each entry in the data, rendered with a specified layout.
This is useful when each item deserves its own URL (e.g. one page per event, per team member, or per link-tree).
data/events.yml)- id: hello-lads
name: "First event"
description: "This is the first event"
- id: roq-and-roll
name: "SSG FTW"
description: "Static site generation with Roq"
site.collections.events.layout=page-event
site.collections.events.from-data.id-key=id
data/events/first.yml, data/events/second.yml)site.collections.events.layout=page-event
site.collections.events.from-data.id-key=_key
The id-key field specifies which data field to use as the page identifier (like a filename for content-based collections). For data directories, _key is the object key (filename without extension).
The id-key value is slugified (e.g. Hello lads ! becomes hello-lads).
By default, the data source name matches the collection id (e.g. the events collection looks for data/events.yml or data/events/). Use from-data.name to point to a different data source:
site.collections.highlights.layout=page-highlight
site.collections.highlights.from-data.id-key=id
site.collections.highlights.from-data.name=events (1)
| 1 | The highlights collection generates pages from the events data source. |
This lets multiple collections share the same data source with different layouts.
The layout template accesses data fields via page.data:
<h1>{=page.data.name}</h1>
<p>{=page.data.description}</p>
Data configuration
| Property | Default | Description |
|---|---|---|
|
|
Location of data files relative to the Roq root directory |
|
|
When true, only data files with a matching |
|
|
Log registered data beans during build |
Debugging
To debug errors, you may print debug information in the logs:
roq -Dquarkus.log.category.\"io.quarkiverse.roq.frontmatter\".level=DEBUG
Testing
All templates will be validated at generation. Sometimes, for example on Pull-Request, you want to detect issues before actual generation. Roq provides a way to generate the full site during the test phase.
First, include the quarkus-roq-testing test dependency in your pom.xml.
<dependency>
<groupId>io.quarkiverse.roq</groupId>
<artifactId>quarkus-roq-testing</artifactId>
<version>2.1.6</version>
<scope>test</scope>
</dependency>
Test Site Generation
Once you’ve added the dependency, you can easily ensure all pages are generated without errors:
@QuarkusTest
@RoqAndRoll
public class RoqSiteTest {
@Test
public void testGen() {
// All pages will be generated/validated during test setup
}
}
That’s it! This basic test already verifies that your site generation is error-free.
You can also add checks on the actual generated content as it is served using a static file server:
@QuarkusTest
@RoqAndRoll
public class RoqSiteTest {
@Test
public void testIndex() {
RestAssured.when().get("/")
.then()
.statusCode(200)
.body(containsString(
"Ready to Roq my world!"
));
}
}
The RestAssured port will automatically use the Roq static test server, running on port 8082 by default.
The Roq test server port could be modified by an annotation parameter like this @RoqAndRoll(port=9090).
|
Using standard Quarkus test
It’s possible to use the standard Quarkus test support (Testing Your Application) to check the content, but then pages will be rendered dynamically on demand at runtime:
@QuarkusTest
public class QuteWebSiteTest {
@Test
public void testIndex() {
RestAssured.when().get("/")
.then()
.statusCode(200)
.body(containsString(
"Ready to Roq my world!"
));
}
}
In this case the RestAssured port will automatically use the Quarkus dynamic test server, running on port 8081 by default.
Roq CLI
The Roq CLI wraps common Quarkus commands with Roq-specific defaults. See the Getting Started guide for installation instructions.
roq create
Create a new Roq site:
roq create my-site
roq create my-site -x theme:base
roq create my-site -x plugin:tagging,plugin:sitemap
| Option | Description |
|---|---|
|
Extensions to add, comma-separated. Prefixes: |
|
Maven group ID (default: |
|
Skip example content from codestarts |
|
Use Gradle instead of Maven |
|
Pin a specific Roq version |
roq start
Start dev mode with live reload:
roq start
roq start -p 8081
| Option | Description |
|---|---|
|
HTTP port (default: 8080, use |
Press w to open the browser, s to force a restart, m to open the editor.
roq add
Add extensions to an existing project:
roq add plugin:tagging plugin:sitemap
roq add theme:resume
roq add web:tailwindcss
roq add rest-jackson
Extension prefixes:
| Prefix | Description |
|---|---|
|
Roq plugin (e.g. |
|
Roq theme (e.g. |
|
Web Bundler extension (e.g. |
|
Any Quarkus extension (e.g. |
|
Full GAV coordinate |
Other commands
-
roq generate— Generate the static site output. -
roq serve— Serve a previously generated static site directory. -
roq update— Update the Quarkus and Roq versions. See Updating Roq.
Editor
| Preview feature, configuration and behavior may change in future releases. |
Roq ships a browser-based content editor in Quarkus Dev UI, available in dev mode. Create and edit pages, posts, and docs, including FrontMatter, with a live preview, no IDE required.
Availability
Included in the core quarkus-roq extension, no extra dependency needed. Dev mode only, never part of the generated site or a production build.
Opening the editor
Start dev mode (roq start or mvn quarkus:dev), then:
-
Click the Roq Editor card in the Dev UI (
/q/dev-ui). -
Press
min the dev console ("Manage content").
The editors
Roq picks the right editor per file:
- Visual editor
-
Block (WYSIWYG) editor for Markdown: slash commands, bubble menu, tables, images. Default for supported files.
- Simple editor
-
Plain source editor with syntax highlighting, for AsciiDoc, HTML, and anything the visual editor can’t handle.
Safe mode (default) opens Markdown files with Qute or HTML blocks in the simple editor, so existing content is never altered. Configure:
# Always use the simple editor
editor.visual-editor.enabled=false
# Keep the visual editor even on files with Qute/HTML blocks (advanced)
editor.visual-editor.safe=false
FrontMatter, images, and tags
A FrontMatter panel lets you edit title, date, layout, tags, and other keys alongside the content. An image picker manages page and site images; a tag manager handles tagged collections.
AI content generation
With the Quarkus Assistant configured, a prompt widget generates content straight into the current document. Steer tone and topic with a custom context:
editor.ai.context=This is a tech blog about Quarkus. Write in a friendly, concise tone.
| Requires the Quarkus Assistant; otherwise the prompt widget is hidden. |
Default markup for new files
New pages and docs default to Markdown. Change the default per content type:
editor.page-markup=asciidoc
editor.doc-markup=markdown
Supported values: markdown, asciidoc, html.
File naming conventions
New file names are derived from a link-style pattern per collection. Default for posts and docs: :date-:slug~7 (date + first seven slug words). Placeholders: :date, :slug, :Slug, :name, :Name, :year, :month, :day; ~W truncates to W words.
# Custom file name pattern for the "posts" collection
editor.collections.posts.name=:year/:month/:slug~5
# Keep the file name in sync when the title or date changes (default: true)
editor.collections.posts.sync-name=true
Git sync (commit, push, pull)
Commit, push, and pull content from the UI. Disabled by default; enable:
editor.sync.enabled=true
Then configure auto-sync and the default commit message:
# Automatically pull from the remote on an interval (seconds)
editor.sync.auto-sync.enabled=true
editor.sync.auto-sync.interval-seconds=60
# Automatically commit + push content changes on an interval (seconds)
editor.sync.auto-publish.enabled=true
editor.sync.auto-publish.interval-seconds=300
# Default commit message
editor.sync.commit-message.template=Update content via Roq Editor
Push/pull use your existing SSH key. If it’s passphrase-protected and no SSH agent is running, provide the passphrase via the EDITOR_SYNC_SSH_PASSPHRASE environment variable.
|
Never put an SSH passphrase in |
Editor configuration reference
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
|---|---|---|
Markup to use for new pages Environment variable: |
|
|
Markup to use for new docs Environment variable: |
|
|
When true, use the visual editor on supported files (Markdown). When false, always use the simple editor Environment variable: |
boolean |
|
Use simple editor if the file contains qute or html blocks without data-type="raw" to make sure we don’t break existing content Environment variable: |
boolean |
|
File name pattern using link-style placeholders. Supported: :date, :slug, :Slug, :name, :Name, :year, :month, :day. Use ~W to truncate to W hyphen-separated words (e.g., :slug~7). Environment variable: |
string |
|
If enabled, auto-sync file names when they match the convention and the title/date changes. Environment variable: |
boolean |
|
Enable Git sync feature (commit, push, pull via the Editor UI) Environment variable: |
boolean |
|
Optional SSH passphrase used as a fallback when no SSH agent is available to unlock a passphrase-protected key for remote operations. Most users do not need this: JGit uses the system SSH agent (macOS Keychain, For security, provide it via the Environment variable: |
string |
|
Enable automatic sync (pull) from remote Environment variable: |
boolean |
|
Auto-sync interval in seconds Environment variable: |
int |
|
Enable automatic publish (commit + push) on content changes Environment variable: |
boolean |
|
Auto-publish interval in seconds Environment variable: |
int |
|
Default commit message template Environment variable: |
string |
|
Custom context to include in every AI content generation request. Use this to set the tone, topic, or style for your blog. For example: "This is a tech blog about Quarkus. Write in a friendly, concise tone." Environment variable: |
string |
Updating Roq
Run the update command from your project directory:
$ roq update
This will update the Quarkus version and extensions (including Roq) and make sure they are compatible together.
The releases and migration info can be found here.
Site Configuration
Site configuration is done in config/application.properties (or src/main/resources/application.properties):
In a multi-module Maven project, use src/main/resources/application.properties instead. The config/application.properties location is resolved relative to the JVM working directory, which may not match the module directory when building from the reactor root.
|
Configuration property fixed at build time - All other configuration properties are overridable at runtime
Configuration property |
Type |
Default |
|---|---|---|
the base hostname & protocol for your site, e.g. http://example.com Environment variable: |
string |
|
The order of the route which handles the templates. <p> By default, the route is executed before the default routes (static resources, etc.). Environment variable: |
int |
|
Add new ignored files to the default list. The ignored files (relative to the site directory). Only the Environment variable: |
list of string |
|
The default ignored files (relative to the site directory) include:
These patterns are additional to the scanner’s own OS-level defaults (e.g. Environment variable: |
list of string |
|
Pages whose content should be escaped— i.e., included in Qute rendering but not parsed for Qute expressions. This is based on the page’s relative path from the content directory. This applies only to pages (not layouts or partials). Supports glob expressions. Environment variable: |
list of string |
|
The layout to use for normal html pages if not specified in FM. When empty, the page will not use a layout when it doesn’t specify it in FM. Resolves local layout first, then theme layout as fallback. Environment variable: |
string |
|
The directory which contains content (pages and collections) in the Roq site directory. Environment variable: |
string |
|
The directory (dir name) which contains static files to be served (with 'static/' prefix). Environment variable: |
string |
|
The directory which contains public static files to be served without processing (dir name) Environment variable: |
string |
|
The path containing static images (in the public directory) Environment variable: |
string |
|
When enabled it will select all FrontMatter pages in Roq Generator Environment variable: |
boolean |
|
Show future documents Environment variable: |
boolean |
|
The theme name. Used to resolve theme layouts when using Environment variable: |
string |
|
Show draft pages Environment variable: |
boolean |
|
Directory name used to mark collection documents as draft when frontmatter does not define attribute Environment variable: |
string |
|
Format for dates Environment variable: |
string |
|
The default timezone Environment variable: |
string |
|
The default language to use when no language is specified in the frontmatter. This language will be used as a fallback for articles that don’t have a 'locale' property. Environment variable: |
string |
|
Indicates whether file names in the public directory and files attached to pages should be slugified (converted to a URL-friendly format). When enabled, file names will automatically be transformed into a URL-safe format. Additionally, Environment variable: |
boolean |
|
If this collection is enabled Environment variable: |
boolean |
|
Show future documents (overrides global future for this collection) Environment variable: |
boolean |
|
If true, the collection won’t be available on path but consumable as data. Environment variable: |
boolean |
|
The layout to use if not specified in FM data. When empty, the document will not use a layout when it doesn’t specify it in FM. Resolves local layout first, then theme layout as fallback. Environment variable: |
string |
|
Default link template for documents in this collection. Can be overridden per-page using the frontmatter Environment variable: |
string |
|
The data attribute to use as the page identifier. The value is slugified. Environment variable: |
string |
required |
The name of the data source (file or directory in data/). Defaults to the collection id. Environment variable: |
string |
|
The directory where the generated templates should be created inside the output directory. Environment variable: |
string |
|
READ CAREFULLY: Environment variable: |
string |
|
Default link template for non-collection pages. Can be overridden per-page using the frontmatter Environment variable: |
string |
|