Templates

Plan: Developer Foundations

Lesson 6 of 16 · 45 min

Introduction

Understanding the core conventions of templates is key to effectively customizing a Stencil theme. In this section, you’ll learn about the critical syntax and concepts used in template files throughout the theme.

Blocks, Pages, and Layouts

You’ve seen that templates are categorized into three main types, which are used together to build the final content of a rendered page: components, pages, and layouts.

A template can call or “embed” another template using a specialized syntax referencing that template’s path:

{{> components/products/product-view}}

You can think of page templates as the main “entry point” for the rendering of a specific page type. These templates use the syntax above to call the layout template that should be applied, as well as to embed component templates responsible for major sections of the page. It’s common for component templates to call other, more specific component templates as well.

A specialized helper expression - partial - is also key to the organization of page and layout templates. This expression allows for the definition of named slots and their content, for final rendering elsewhere.

{{#partial "page"}}
{{> components/common/breadcrumbs ...}}
...
{{/partial}}

Content within a partial is not output immediately where it appears in the template, but rather is stored to be output wherever a corresponding block expression is used.

{{#block "page"}} {{/block}}

This allows one template to define content that will be output within the markup of another template.

Putting these concepts together, a typical structure in Cornerstone involves the following:

  1. A layout template defines basic outer HTML structure and global elements and uses the block expression to output key page sections. Some of these block expressions appear directly in the layout template, while others appear in global component templates called by the layout.
  2. A page template uses the partial expression to define the content of the major sections, usually calling individual component templates within these.
  3. The page template then calls the appropriate layout template, kicking off the actual rendering of the full page.

Example Layout Component:

<!DOCTYPE html>
<html>
<head>
<title>{{ head.title }}</title>
{{#block "head"}} {{/block}}
</head>
<body>
{{#block "page"}} {{/block}}
</body>
</html>

Example Page Component:

{{#partial "page"}}
{{> components/common/breadcrumbs ...}}
<main class="page">
...
</main>
{{/partial}}
{{> layout/base}}

Handlebars

The expressions you saw previously for calling other templates and defining partial sections are examples of Handlebars expressions. Handlebars is a JavaScript-based templating language offering simple syntax for dynamic logic and dealing with dynamic data within your templates.

Handlebars expressions are one of the most critical concepts for building out the logic you need in your templates. Available expressions include the simple ability to directly output a dynamic value:

{{product.brand.name}}

They also include expressions for conditional logic:

{{#if product.brand}}
<h2 class="productView-brand">
...
</h2>
{{/if}}

There are also expressions for looping through lists of data:

{{#each products}}
<li class="product">
...
</li>
{{/each}}

See the Handlebars documentation for full details on the built-in expressions available.

Stencil also implements a number of custom Handlebars helpers to simplify common formatting or parsing tasks. See the documentation for a full list of these custom expressions.

Stencil Objects

You’ve seen that Handlebars expressions allow you to work with dynamic data within your templates. But what data is actually available to use with those expressions?

Each unique page type has access to specific JavaScript objects related to that page’s function. For example, the template templates/pages/product.html is for the product detail page and has access to a product object representing the specific product being browsed. product can be directly referenced in Handlebars within the product.html template or templates it calls.

<span>{{product.sku}}</span>

Certain objects are also available to all pages. For example, the products object allows access to the store’s new, featured, or top-selling products from any page, using syntax like products.new. The customer object contains data about the currently logged-in customer. Sometimes the availability of these global objects depends on explicitly “opting in” using YAML front matter, which you’ll learn about shortly.

Review the full reference in the BigCommerce documentation for the objects available on different page types.

Also note that when running your local server using the Stencil CLI, you can append the querystring parameter debug to any URL to print out the full object data being loaded for that page:

http://localhost:3000/?debug=context

The context value will result in a JSON response being returned instead of the rendered page, while the bar value will print the object data along with the rendered page.

You may notice in some templates that the objects referenced in Handlebars expressions don’t seem to correspond with any of the objects in the documentation. Keep in mind that the “context” of a template can be changed with arguments when it is first called, changing the values it has access to.

{{> components/products/example product}}

A template called from the product page like in the example above would receive the product object as its own context, meaning that template could include references to values like sku, name, and price directly instead of referencing product.sku, product.name, and product.price.

Front Matter

At the top of most page templates (and only page templates), you will find a section of code in YAML syntax, which is known as the template’s front matter.

---
products:
new:
limit: {{theme_settings.homepage_new_products_count}}
featured:
limit: {{theme_settings.homepage_featured_products_count}}
top_sellers:
limit: {{theme_settings.homepage_top_products_count}}
carousel: {{theme_settings.homepage_show_carousel}}
blog:
recent_posts:
limit: {{theme_settings.homepage_blog_posts_count}}
---

Front matter directly references global or page-specific Stencil objects as discussed - products, carousel, and blog in the above example. Using front matter, it’s possible to exercise a degree of control over certain data available to your templates.

Configuration available in front matter often takes the form of declaring how many items to load in a list, such as in the limit attributes in the example above, or opting in or out of loading certain objects, such as with the boolean value being passed to carousel. See the full documentation on front matter.

Another important feature front matter offers is the ability to define a custom query for the BigCommerce GraphQL Storefront API using the gql attribute, the results of which will be available to access within your templates via gql.data. Specific page types support certain values automatically available as GraphQL variables. See the full documentation of front matter GraphQL attributes.

Regions

A common Handlebars helper you will encounter in various templates within Cornerstone is the region expression.

{{{region name="header_bottom"}}}

While we will not be digging further into their use here, note that these expressions define regions where a store admin user can place and configure visual widgets in the Page Builder interface.

Resources