Skip to main content
This tutorial will walk you through creating your first custom theme template. You’ll learn the core concepts by building a simple product page layout with dynamic content.
Prerequisites: Basic knowledge of HTML and CSS. Access to your Quickbutik Control Panel.

What we’ll build

By the end of this tutorial, you’ll have created a custom product page that:
  • ✅ Displays product information dynamically
  • ✅ Shows product images in a gallery
  • ✅ Handles product variants and stock status
  • ✅ Includes an add-to-cart button

Step 1: Access the Theme Editor

First, let’s access your theme files:
1

Open Control Panel

Log into your Quickbutik store and navigate to Appearance → Theme
2

Access Code Editor

Click “Under the hood” to open the theme code editor
3

Find Product Template

Look for the product.html file in the file list - this controls how individual product pages are displayed

Step 2: Understanding the Basic Structure

Let’s start with a simple product page template:
product.html
<!DOCTYPE html>
<html>
<head>
    <title>{{product.title}} - {{shop.name}}</title>
    <meta name="description" content="{{seo.description}}">
</head>
<body>
    <div class="product-page">
        <!-- We'll build our product content here -->
    </div>
</body>
</html>
  • {{product.title}} - Displays the product name
  • {{shop.name}} - Shows your store name
  • {{seo.description}} - SEO-optimized description for the page

Step 3: Add Product Information

Now let’s add the core product information:
<div class="product-info">
    <h1 class="product-title">{{product.title}}</h1>
    
    <div class="product-price">
        {{#product.has_before_price}}
            <span class="before-price">{{product.before_price}}</span>
        {{/product.has_before_price}}
        <span class="current-price">{{product.price}}</span>
        <span class="currency">{{product.currency}}</span>
    </div>
    
    <div class="product-description">
        {{&product.description}}
    </div>
</div>

What’s happening here?

Price Display

We show both regular and sale prices, with the has_before_price conditional showing sale pricing only when relevant.

Stock Status

Using # and ^ operators to show different content based on whether the product is sold out.

Localization

The {{#lang}} wrapper automatically translates text based on your store’s language settings.

HTML Content

The & symbol in {{&product.description}} renders HTML content without escaping it.
Let’s create a dynamic image gallery:
Image Gallery
<div class="product-gallery">
    {{#product.images}}
        <div class="gallery-item">
            <img src="{{#img}}{{image}}_800x600{{/img}}" 
                 alt="{{alttext}}" 
                 data-id="{{image_id}}">
        </div>
    {{/product.images}}
    
    {{^product.images}}
        <!-- Fallback for products without images -->
        <div class="no-image">
            <span>{{#lang}}No image available{{/lang}}</span>
        </div>
    {{/product.images}}
</div>
The {{#img}} wrapper automatically optimizes images. The _800x600 suffix resizes the image to 800x600 pixels.

Step 5: Product Variants

If your product has variants (like size or color), let’s display them:
Product Variants
{{#product.hasOptions}}
<div class="product-options">
    <h3>{{#lang}}Options{{/lang}}</h3>
    
    {{#product.options}}
    <div class="option-group">
        <label>{{option_title}}</label>
        <select name="variant_{{option_title}}">
            {{#option_values}}
            <option value="{{id}}">{{name}}</option>
            {{/option_values}}
        </select>
    </div>
    {{/product.options}}
</div>
{{/product.hasOptions}}

Step 6: Add to Cart Button

Finally, let’s add a functional add-to-cart button:
Add to Cart
<div class="add-to-cart-section">
    {{^product.soldOut}}
        <form action="/cart/add" method="post">
            <input type="hidden" name="product_id" value="{{product.id}}">
            
            {{#product.hasOptions}}
                <!-- Include variant selection -->
                <div class="variant-selection">
                    <!-- Variant dropdowns will go here -->
                </div>
            {{/product.hasOptions}}
            
            <div class="quantity-selector">
                <label for="quantity">{{#lang}}Quantity{{/lang}}</label>
                <input type="number" name="quantity" value="1" min="1" id="quantity">
            </div>
            
            <button type="submit" class="btn-add-to-cart">
                {{#lang}}Add to Cart{{/lang}}
            </button>
        </form>
    {{/product.soldOut}}
    
    {{#product.soldOut}}
        <button class="btn-sold-out" disabled>
            {{#lang}}Out of Stock{{/lang}}
        </button>
    {{/product.soldOut}}
</div>

Step 7: Complete Example

Here’s your complete product page template:
<!DOCTYPE html>
<html>
<head>
    <title>{{product.title}} - {{shop.name}}</title>
    <meta name="description" content="{{seo.description}}">
    <style>
        /* Basic styling */
        .product-page { max-width: 1200px; margin: 0 auto; padding: 20px; }
        .product-gallery img { max-width: 100%; height: auto; }
        .before-price { text-decoration: line-through; color: #888; }
        .current-price { font-weight: bold; font-size: 1.2em; }
        .out-of-stock { color: #e74c3c; }
        .in-stock { color: #27ae60; }
        .btn-add-to-cart { background: #3498db; color: white; padding: 12px 24px; border: none; cursor: pointer; }
        .btn-sold-out { background: #95a5a6; color: white; padding: 12px 24px; border: none; }
    </style>
</head>
<body>
    <div class="product-page">
        <!-- Product Gallery -->
        <div class="product-gallery">
            {{#product.images}}
                <img src="{{#img}}{{image}}_800x600{{/img}}" alt="{{alttext}}">
            {{/product.images}}
        </div>
        
        <!-- Product Information -->
        <div class="product-info">
            <h1 class="product-title">{{product.title}}</h1>
            
            <div class="product-price">
                {{#product.has_before_price}}
                    <span class="before-price">{{product.before_price}}</span>
                {{/product.has_before_price}}
                <span class="current-price">{{product.price}}</span>
                <span class="currency">{{product.currency}}</span>
            </div>
            
            <div class="stock-status">
                {{#product.soldOut}}
                    <span class="out-of-stock">{{#lang}}Out of stock{{/lang}}</span>
                {{/product.soldOut}}
                {{^product.soldOut}}
                    <span class="in-stock">{{#lang}}In stock{{/lang}}</span>
                {{/product.soldOut}}
            </div>
            
            <div class="product-description">
                {{&product.description}}
            </div>
            
            <!-- Product Options -->
            {{#product.hasOptions}}
            <div class="product-options">
                {{#product.options}}
                <div class="option-group">
                    <label>{{option_title}}</label>
                    <select name="variant_{{option_title}}">
                        {{#option_values}}
                        <option value="{{id}}">{{name}}</option>
                        {{/option_values}}
                    </select>
                </div>
                {{/product.options}}
            </div>
            {{/product.hasOptions}}
            
            <!-- Add to Cart -->
            <div class="add-to-cart-section">
                {{^product.soldOut}}
                    <form action="/cart/add" method="post">
                        <input type="hidden" name="product_id" value="{{product.id}}">
                        <div class="quantity-selector">
                            <label for="quantity">{{#lang}}Quantity{{/lang}}</label>
                            <input type="number" name="quantity" value="1" min="1" id="quantity">
                        </div>
                        <button type="submit" class="btn-add-to-cart">
                            {{#lang}}Add to Cart{{/lang}}
                        </button>
                    </form>
                {{/product.soldOut}}
                
                {{#product.soldOut}}
                    <button class="btn-sold-out" disabled>
                        {{#lang}}Out of Stock{{/lang}}
                    </button>
                {{/product.soldOut}}
            </div>
        </div>
    </div>
</body>
</html>

Step 8: Test Your Template

1

Save your changes

Click Save in the theme editor
2

Preview the page

Use the preview function to see your changes on a test product
3

Test different scenarios

  • Products with/without images
  • Products with/without variants
  • Products that are in stock vs. sold out
4

Publish when ready

When you’re satisfied, publish your changes to make them live

🎉 Congratulations!

You’ve successfully created your first custom Quickbutik theme template! You now understand:
  • ✅ How to display product data dynamically
  • ✅ How to use conditionals for different states
  • ✅ How to handle product variants and options
  • ✅ How to create functional form elements

Next Steps

Common Issues

Make sure you clicked Save and try clearing your browser cache. Some changes may take a few minutes to appear.
Check that you’re viewing the template on a product page. Some data is only available on specific page types.
Remember that your theme’s CSS file controls the visual appearance. The template only handles the HTML structure and dynamic content.