> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# 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:

```text showLineNumbers={false}
{{> 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.

```text showLineNumbers={false}
{{#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.

```text showLineNumbers={false}
{{#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:

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

## Example Page Component:

```html showLineNumbers={false}
{{#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](https://handlebarsjs.com/) 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:

```text showLineNumbers={false}
{{product.brand.name}}
```

They also include expressions for conditional logic:

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

There are also expressions for looping through lists of data:

```html showLineNumbers={false}
{{#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](/developer/docs/storefront/stencil/themes/context/handlebars-reference) 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.

```html showLineNumbers={false}
<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](/developer/docs/storefront/stencil/themes/context/frontmatter-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:

```text showLineNumbers={false}
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.

> **Info**
>
> 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.

```yaml showLineNumbers={false}
---
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](/developer/docs/storefront/stencil/themes/context/frontmatter) 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](/developer/docs/storefront/stencil/themes/context/frontmatter-reference).

## Regions

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

```text showLineNumbers={false}
{{{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 content in a visual editor:

* **[Widgets](/developer/docs/admin/widgets-and-scripts/overview#widgets)** in the Page Builder interface.
* **Content** in the Makeswift editor.

## Resources

* [Handlebars](https://handlebarsjs.com/)
* [Stencil Handlebars Reference](/developer/docs/storefront/stencil/themes/context/handlebars-reference)
* [Front Matter Object Reference](/developer/docs/storefront/stencil/themes/context/frontmatter-reference)
* [Using Front Matter](/developer/docs/storefront/stencil/themes/context/frontmatter)
* [Front Matter GraphQL Attributes](/developer/docs/storefront/stencil/themes/context/frontmatter-reference)
* [Widgets](/developer/docs/admin/widgets-and-scripts/overview#widgets)