BigCommerce Stencil Theme Development
Before writing code
Fetch live docs:
- Fetch
https://developer.bigcommerce.com/docs/storefront/stencilfor Stencil overview - Fetch
https://developer.bigcommerce.com/docs/storefront/stencil/themes/context/object-referencefor theme object reference - Web-search
site:developer.bigcommerce.com stencil handlebars helpersfor Handlebars helper reference
Architecture
How Stencil Works
Stencil is BigCommerce's server-rendered theme engine:
- Template files (Handlebars
.html) define page structure - Front matter (YAML) at the top of each template declares what data to fetch
- BigCommerce injects theme objects (product, category, cart, settings, etc.) into the template context
- Handlebars helpers and partials render the data
- SCSS compiles to CSS, JS bundles with webpack
- Stencil CLI provides local development with hot reload
Template Hierarchy
templates/
├── layout/
│ ├── base.html # Master layout — header, footer, body
│ └── empty.html # Minimal layout (checkout, etc.)
├── pages/
│ ├── home.html # Homepage
│ ├── product.html # Product detail page
│ ├── category.html # Category listing
│ ├── cart.html # Cart page
│ ├── checkout.html # Checkout page
│ ├── account/ # Customer account pages
│ └── ...
├── components/
│ ├── common/ # Header, footer, navigation
│ ├── products/ # Product cards, options, gallery
│ ├── cart/ # Cart items, totals
│ └── ...
└── ...
Front Matter
What It Does
YAML block at the top of template files that declares data requirements:
---
product:
videos:
limit: {{theme_settings.product_videos_count}}
reviews:
limit: {{theme_settings.product_reviews_count}}
related_products:
limit: {{theme_settings.related_products_count}}
similar_by_views:
limit: {{theme_settings.similar_by_views_count}}
---
How It Works
- BigCommerce reads the front matter before rendering
- Fetches the specified data from its APIs
- Injects results into the Handlebars template context
- Controls what data is available on each page
Common Front Matter Resources
product— product details, images, videos, reviews, related productscategory— category info, products in categorycart— cart items, totalscustomer— logged-in customer datashop_by_brand— brand listingnew_products,featured_products,top_products— product collections
Theme Objects
Key Objects
| Object | Available On | Contains |
|---|---|---|
product | Product page | name, price, images, options, variants, description, reviews |
category | Category page | name, description, products, subcategories |
cart | Cart page | items, subtotal, taxes, grand_total |
customer | When logged in | name, email, addresses, orders |
settings | All pages | store name, currency, logo, URLs |
theme_settings | All pages | config.json setting values |
breadcrumbs | Most pages | navigation breadcrumbs |
page | CMS pages | title, content, URL |
Accessing Data
{{product.title}}
{{product.price.without_tax.formatted}}
{{#each product.images}}
<img src="{{getImage this 'product_size'}}" alt="{{this.alt}}">
{{/each}}
Handlebars Helpers
Control Flow
{{#if condition}}...{{else}}...{{/if}}— conditional{{#unless condition}}...{{/unless}}— inverse conditional{{#each collection}}...{{/each}}— iteration{{#with object}}...{{/with}}— context shifting
BigCommerce Custom Helpers
{{getImage image 'size_name'}}— generate image URL at specific size{{cdn 'path/to/asset'}}— CDN-prefixed asset URL{{stylesheet 'path/to/css'}}— include stylesheet{{inject 'variable' value}}— pass data to JavaScript context{{jsContext}}— output injected variables as JSON for JS consumption{{lang 'translation_key'}}— internationalization{{money price}}— format currency{{truncate text length}}— truncate string{{any collection}}— check if collection has items{{all condition1 condition2}}— logical AND{{compare a '===' b}}— comparison
Partials
Include reusable template fragments:
{{> components/products/card product}}— render a partial with context{{> components/common/header}}— include a component- Partials live in
templates/components/
Styling (SCSS)
Structure
assets/scss/
├── settings/ # Variables, mixins
│ ├── foundation/
│ └── citadel/
├── components/ # Component styles
├── layouts/ # Layout styles
├── tools/ # Utility mixins
└── theme.scss # Main entry point
Theme Settings in SCSS
Access config.json values: stencilColor("primary"), stencilNumber("font-size"), stencilString("font-family")
JavaScript
Module System
Stencil uses webpack for JS bundling:
- ES6 module imports
- Entry point in
assets/js/app.js - Page-specific modules loaded conditionally
- jQuery available globally (Cornerstone ships with it)
Accessing Theme Data in JS
Use {{inject}} in templates and {{jsContext}} to pass server data to client JS:
{{inject 'productId' product.id}}
<script>{{jsContext}}</script>
Access in JS via this.context in PageManager subclasses.
PageManager
Cornerstone's page lifecycle manager:
- Extend
PageManagerfor page-specific JS onReady()— DOM ready, initialize functionality- Registered per page type in
assets/js/app.js
Configuration
config.json
Theme configuration with settings and variations:
settings— default values for all theme settingsvariations— named presets (Light, Bold, Warm, etc.)read_only_files— files that cannot be edited in Theme Editor
schema.json
Defines the Theme Editor UI:
- Sections, groups, and fields that appear in the visual editor
- Field types:
color,font,select,checkbox,text,range,imageDimension - Maps to
config.jsonsettings keys
Best Practices
- Fork Cornerstone as your starting point — don't start from scratch
- Use front matter to control data loading — don't over-fetch
- Use
{{inject}}to pass data to JS — don't scrape the DOM - Use
{{cdn}}for all asset URLs — ensures CDN delivery - Define schema.json entries for all customizable settings
- Use SCSS variables linked to config.json for consistent theming
- Escape user content:
{{{sanitize html}}}for HTML,{{variable}}auto-escapes - Test across theme variations
- Keep bundle size small — conditionally load JS per page
Fetch the Stencil documentation and theme object reference for exact helper syntax, front matter keys, and object structure before implementing.