> ## Documentation Index
> Fetch the complete documentation index at: https://quickbutik.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart Tutorial

> Build your first custom Quickbutik theme template in 15 minutes

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.

<Note>
  **Prerequisites**: Basic knowledge of HTML and CSS. Access to your Quickbutik Control Panel.
</Note>

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

<Steps>
  <Step title="Open Control Panel">
    Log into your Quickbutik store and navigate to **Appearance → Theme**
  </Step>

  <Step title="Access Code Editor">
    Click **"Under the hood"** to open the theme code editor
  </Step>

  <Step title="Find Product Template">
    Look for the `product.html` file in the file list - this controls how individual product pages are displayed
  </Step>
</Steps>

## Step 2: Understanding the Basic Structure

Let's start with a simple product page template:

```mustache product.html theme={null}
<!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>
```

<Accordion title="Understanding the template tags">
  * `{{product.title}}` - Displays the product name
  * `{{shop.name}}` - Shows your store name
  * `{{seo.description}}` - SEO-optimized description for the page
</Accordion>

## Step 3: Add Product Information

Now let's add the core product information:

<CodeGroup>
  ```mustache Basic Product Info theme={null}
  <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>
  ```

  ```mustache Stock Status theme={null}
  <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>
  ```
</CodeGroup>

### What's happening here?

<CardGroup cols={2}>
  <Card title="Price Display" icon="dollar-sign">
    We show both regular and sale prices, with the `has_before_price` conditional showing sale pricing only when relevant.
  </Card>

  <Card title="Stock Status" icon="boxes-stacked">
    Using `#` and `^` operators to show different content based on whether the product is sold out.
  </Card>

  <Card title="Localization" icon="language">
    The `{{#lang}}` wrapper automatically translates text based on your store's language settings.
  </Card>

  <Card title="HTML Content" icon="code">
    The `&` symbol in `{{&product.description}}` renders HTML content without escaping it.
  </Card>
</CardGroup>

## Step 4: Product Image Gallery

Let's create a dynamic image gallery:

```mustache Image Gallery theme={null}
<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>
```

<Tip>
  The `{{#img}}` wrapper automatically optimizes images. The `_800x600` suffix resizes the image to 800x600 pixels.
</Tip>

## Step 5: Product Variants

If your product has variants (like size or color), let's display them:

```mustache Product Variants theme={null}
{{#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:

```mustache Add to Cart theme={null}
<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:

<CodeGroup>
  ```mustache Complete Template theme={null}
  <!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>
  ```
</CodeGroup>

## Step 8: Test Your Template

<Steps>
  <Step title="Save your changes">
    Click **Save** in the theme editor
  </Step>

  <Step title="Preview the page">
    Use the preview function to see your changes on a test product
  </Step>

  <Step title="Test different scenarios">
    * Products with/without images
    * Products with/without variants
    * Products that are in stock vs. sold out
  </Step>

  <Step title="Publish when ready">
    When you're satisfied, publish your changes to make them live
  </Step>
</Steps>

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

<CardGroup cols={2}>
  <Card title="Mustache Basics" icon="code" href="/theme-development/mustache-basics">
    Learn more about the templating language fundamentals
  </Card>

  <Card title="Global Objects" icon="globe" href="/theme-development/global/shop">
    Explore store-wide data like navigation, cart, and settings
  </Card>

  <Card title="Advanced Usage" icon="rocket" href="/theme-development/advanced/dynamic-elements">
    Learn about dynamic elements and complex layouts
  </Card>

  <Card title="Best Practices" icon="star" href="/theme-development/advanced/best-practices">
    Discover performance tips and coding standards
  </Card>
</CardGroup>

## Common Issues

<AccordionGroup>
  <Accordion title="Template not updating">
    Make sure you clicked **Save** and try clearing your browser cache. Some changes may take a few minutes to appear.
  </Accordion>

  <Accordion title="Missing product data">
    Check that you're viewing the template on a product page. Some data is only available on specific page types.
  </Accordion>

  <Accordion title="Styling issues">
    Remember that your theme's CSS file controls the visual appearance. The template only handles the HTML structure and dynamic content.
  </Accordion>
</AccordionGroup>
