Basics
Features
Best Practices
Addon Development
Related Docs
Dark Mode

#Templating

One of the most powerful features of MercuryCMS is its Templating system. Templating allows you to put whatever data you want anywhere to be able to create a very dynamic and easy to maintain website.

To effectively template values, you'll need to understand the details of different interpolation styles and contexts, but before we dive into complexities, we can start with a simple example.

#Markup Interpolation

When writing markup, you have a lot of choices for interpolation that work in different ways. Within HTML markup, you have access to MercuryCMS' {{ }} syntax. Note that you can use any valid JavaScript when interpolating. For example:

<div class="home-page">
  <h1>Welcome to {{ site.name }}!</h1>
  <p>Copyright {{ new Date().getFullYear() }}</p>
</div>

Will produce:

<div class="home-page">
  <h1>Welcome to My Site!</h1>
  <p>Copyright 2022</p>
</div>

Within Pug markup, you have the benefit of all of Pug's interpolation syntax. Here's an example that includes all of Pug's syntax options:

.blog-post-page
  h1 Welcome to #{ page.title }!
  p We have #{ blogPostList.length } Blog Posts on the site!
  each blogPost in blogPostList
    a(href=`/blog/${blogPost.slug}`)
      h2 #{ blogPost.title }
    .body !{ blogPost.bodyHtml }

It's beyond the scope of this documentation to explain all of Pug's syntax and capabilities, so it's recommended you read about it yourself. Pug is capable of a lot of amazing things.

It is however, within the scope of this documentation to explain all of the individual objects and values available for interpolation, which will be covered later.

Note that you can pass entire objects and arrays into Component attributes and elsewhere in the markup. They will be JSON-encoded during interpolation. You can also write these values directly in markup. For example <some-component items=['a', 'b', 'c']></some-component>.

Vue Components have a special {{{ }}} markup described in Vue Components.

#Style Interpolation

Style interpolation is possible within CSS and Stylus. They both use MercuryCMS' {{ }} syntax. This is very useful in combination with Stylus' built-in functions. For example:

.button
  color white
  background {{ theme.mainColor }}
  transition background 0.2s
  &:hover
    background lighten({{ theme.mainColor }}, 10%)

As with Pug, it's outside the scope of this documentation to explain all of Stylus' features. It's recommended you read about Stylus to see what it's capable of.

#Script Interpolation

MercuryCMS provides script interpolation using {{ }} syntax. This syntax within scripts allows you to dynamically generate code. This is most useful for getting values into Vue Components, which is described in the Vue Components documentation.

Objects and arrays interpolated using {{ }} syntax are JSON encoded, but all other values are transcribed directly. This means you need to use quotes around strings. For example:

// this will cause an error: let siteName = My Site
let siteName = {{ site.name }}

// this is valid: let siteName = "My Site"
let siteName = "{{ site.name }}"

// this is valid: let blogPost = {title: "My First Post", ...}
let blogPost = {{ blogPost }}

#Field Interpolation

There are many input fields throughout MercuryCMS that support interpolation, such as creating dynamic Page paths or templating values into SEO fields. Collections also have Computed Values described in Collections. In all of these instances, {{ }} syntax is used.

#Contexts

Each place you can use templated values is called a "Context". To use them effectively, you will need to know when the field you're templating into is calculated and what values you have access to.

For example, on a Page, you have access to site and page, but not attr since that's part of Components.

The easiest way to understand this is to simply list all of the available objects and explain where you can use them.

#Site

The site object is available in all contexts.

KeyDescription
nameA string containing the name of the Site set in the Site Settings.
envEither "staging" or "production" depending on which environment the site is being built for. You can use this to show things like debug information only on the staging site.
fqdnThe Fully Qualified domain name as specified in Site Settings. This will automatically be the correct value for staging or production environments. ex: example.com
timezoneThe Site's timezone as specified in Site Settings. Ex: "America/New_York"
urlThe Site's URL as specified in Site Settings. This will automatically be the correct value for staging or production environments. ex: https://example.com
isTrailingSlashEnabledTrue if "Use Trailing Slash on Page URLs" is on.
pagesA list of all Normal Pages (not Special Pages like 404s). Each page has a path and title. This is useful for generating sitemap pages.

#Page

Information about the Page is available when generating the Page. This is available within the Page's own markup, style, and script, its parent Layout, and any contained Components.

KeyDescription
titleThe page's computed title
pathThe page's computed path
bodyThe page's body as HTML. This is only available within the Layout and determines where the page's generated body goes

#Collections

Collections are also available in most contexts. Any Collections you define are available in camelCase. For example, a Collection called "Blog Post" would be available as blogPostList. This is an array containing every Blog Post in order.

Each Entry in the array has camelCase keys for each of its fields. For example, "Title", "Featured Image", and "Published At" would become blogPost.title, blogPost.featuredImage, and blogPost.publishedAt.

Each Entry also has the special fields _createdAt, _createdAtDate, _updatedAt, and _updatedAtDate added to them. These are Javascript Dates representing the time the Entry was created/updated and a Day.js object representing that same time used for easy formatting within markup. Day.js objects support the AdvancedFormat, Duration, and RelativeTime plugins.

To get an Entry by its _id, it's highly recommended to use the built-in getById function rather than Array.find for performance. For example, rather than using blogPostList.find(blogPost => blogPost._id == attr.blogPostId) within a Component, use blogPostList.getById(attr.blogPostId). This method also works for Media.

#Media

Media is available in any context that Collections are, as mediaList. Media objects have the following keys:

KeyDescription
_idThe Media's automatically assigned ID
_createdAtA JavaScript Date representing the time the Media was uploaded
_createdAtDateA Day.js object representing the time the Media was uploaded. Day.js objects support the AdvancedFormat, Duration, and RelativeTime plugins.
_updatedAtA JavaScript Date representing the time the Media was updated
_updatedAtDateA Day.js object representing the time the Media was uploaded. Day.js objects support the AdvancedFormat, Duration, and RelativeTime plugins.
type"image", "video", or "audio"
nameThe Media's name set in the Media Library
altTextThe Media's Alt Text set in the Media Library
captionThe Media's caption set in the Media Library
sizesAn array of objects describing the different image sizes available
videoSizesAn array of objects describing the different video sizes available
durationThe Media's duration in milliseconds (for video and audio)

#Dynamic Page Data

When creating dynamic Page paths, you specify a dynamic route such as /blog/{{ blogPost.slug }}. In this special instance, the route itself determines that blogPost is needed. This Collection Entry is available within the Page's markup, style, script, SEO, title, and path.

Data provided by the Page's Data script is also available in the same places.

#Component Attributes and Data

When you pass data into a Component, it becomes available anywhere within that Component by using the attr object. All attributes get mapped to the attr object as camelCase as described in the Components documentation.

You can template values into attribute default values as well. For example, you could make a "Main Color" attribute and set its default value to {{ theme.mainColor }}. Templating this value into the attribute makes it easier to maintain than individually templating {{ theme.mainColor }} many times into the Component's style, instead using {{ attr.mainColor }}.

Note that in the Component's Data script, you access attr directly, not by using {{ }}.

Component Data scripts also have access to a data object which they can put data into to be used in its markup, style, and script.

#Manual Templating

Templating automatically occurs when you build Pages. In some instances, you may need to put data into a .json file or use data in a script and need to template values outside of the context of a Page. In these instances, you can use the fillTemplate function. For example, you can run fillTemplate('Welcome to {{ site.name }}.') to convert the value to Welcome to My Site..