Mustache is a logic-less templating language that Quickbutik uses to create dynamic storefronts. This guide covers the core syntax and fundamental concepts you need to get started with Mustache templates.

Why Mustache?

  • Simple, readable syntax
  • Logic-less design prevents complex business logic in templates
  • Cross-platform compatibility
  • Secure by design - prevents code injection

Template Syntax Overview

All Mustache templates use double curly braces {{}} to denote dynamic content. Here are the basic patterns:

Variables

{{variable}} - Outputs the value of a variable

Sections

{{#section}}...{{/section}} - Conditional blocks or loops

Inverted Sections

{{^section}}...{{/section}} - Shows content when condition is false

Comments

{{! This is a comment }} - Not rendered in output

Variables and Output

The simplest Mustache tag outputs a variable’s value:

<!-- Display product information -->
<h1>{{product.title}}</h1>
<p>Price: {{product.price}} {{product.currency}}</p>
<p>SKU: {{product.sku}}</p>

<!-- Display store information -->
<footer>© {{shop.name}}</footer>

HTML Escaping

By default, Mustache escapes HTML characters for security. Use {{{variable}}} or {{&variable}} to render unescaped HTML:

<!-- Escaped HTML (safe) -->
<div>{{product.description}}</div>

<!-- Unescaped HTML (renders HTML tags) -->
<div>{{&product.description}}</div>
<div>{{{product.description}}}</div>

Security Note: Only use unescaped output ({{&}} or {{{}}}) with trusted content like product descriptions that you control. Never use it with user-generated content.

Basic Sections and Conditionals

Sections are the core of Mustache’s logic. They render content based on the truthiness of a value:

<!-- Show content if product is on sale -->
{{#product.has_before_price}}
    <div class="sale-badge">SALE!</div>
    <span class="original-price">{{product.before_price}}</span>
{{/product.has_before_price}}

<!-- Show content if product is NOT sold out -->
{{^product.soldOut}}
    <button class="add-to-cart">Add to Cart</button>
{{/product.soldOut}}

<!-- Show content if product IS sold out -->
{{#product.soldOut}}
    <div class="sold-out-notice">Sorry, this item is sold out</div>
{{/product.soldOut}}

Basic Loops

When a section’s value is an array, Mustache loops through each item:

<!-- Loop through product images -->
<div class="product-gallery">
    {{#product.images}}
        <img src="{{image}}" alt="{{alttext}}" class="product-image">
    {{/product.images}}
</div>

<!-- Loop through navigation items -->
<nav>
    {{#linklist.main}}
        <a href="{{url}}">{{name}}</a>
    {{/linklist.main}}
</nav>

<!-- Handle empty arrays -->
{{#basket.items}}
    <div class="cart-item">{{item.title}} - {{qty}}</div>
{{/basket.items}}
{{^basket.items}}
    <p>Your cart is empty</p>
{{/basket.items}}

Basic Object Access

Use dot notation to access object properties:

<!-- Simple object properties -->
{{product.title}}
{{product.price}}
{{shop.name}}

<!-- Nested object properties -->
{{order.customer.firstname}}
{{order.customer.lastname}}
{{order.customer.ship_address}}

Understanding Context

Inside a section, the context changes to that object:

<!-- Outside any section, we're in global context -->
<h1>Welcome to {{shop.name}}</h1>

{{#basket.items}}
    <!-- Inside this section, context is each basket item -->
    <div class="cart-item">
        <h3>{{item.title}}</h3>  <!-- item.title, not basket.items.item.title -->
        <p>Quantity: {{qty}}</p>  <!-- qty, not basket.items.qty -->
        <p>Price: {{item.price}}</p>
    </div>
{{/basket.items}}

{{#product}}
    <!-- Inside this section, context is the product object -->
    <h1>{{title}}</h1>  <!-- product.title is now just title -->
    <p>{{description}}</p>  <!-- product.description is now just description -->
{{/product}}

Helper Functions Overview

Quickbutik provides special wrapper functions for common tasks:

<!-- Image resizing -->
<img src="{{#img}}{{product.firstimage}}_400x400{{/img}}" alt="{{product.title}}">

<!-- Text translation -->
<button>{{#lang}}Add to Cart{{/lang}}</button>

<!-- Asset linking -->
<link rel="stylesheet" href="{{#assets}}css/styles.css{{/assets}}">

Learn More: Helper functions are covered in detail in the Wrappers and Functions guide.

Best Practices

Keep It Simple

Mustache is designed to be logic-less. Keep business logic in your data, not your templates.

Use Descriptive Names

Use clear, descriptive variable names in your templates for better maintainability.

Handle Empty States

Always provide fallbacks for empty arrays and missing data.

Escape User Content

Use default (escaped) output for any user-generated content.

Template Organization

<!-- Clear sections with comments -->
{{! Product Gallery Section }}
<div class="product-gallery">
    {{#product.images}}
        <img src="{{#img}}{{image}}_600x600{{/img}}" alt="{{alttext}}">
    {{/product.images}}
</div>

{{! Product Information Section }}
<div class="product-info">
    <h1>{{product.title}}</h1>
    
    {{! Price Display }}
    <div class="price">
        {{#product.has_before_price}}
            <span class="was-price">{{product.before_price}}</span>
        {{/product.has_before_price}}
        <span class="current-price">{{product.price}}</span>
    </div>
</div>

Common Mistakes to Avoid

Testing Your Templates

1

Use the preview function

Always test your templates using Quickbutik’s preview feature before publishing

2

Test edge cases

Test with products that have no images, are sold out, or have no variants

3

Check different page types

Make sure your templates work across different contexts (product pages, category pages, etc.)

4

Validate HTML output

Use browser developer tools to ensure your templates generate valid HTML

Next Steps

Now that you understand the basics, dive deeper into specific aspects: