Claude
Skills
Sign in
Back

shopify-theme-development

Included with Lifetime
$97 forever

Build and customize Shopify themes using Liquid templating, JSON sections, dynamic blocks, and theme app extensions for added functionality

platform-shopifyshopifyliquidthemesectionsblocksdawntheme-app-extensions

What this skill does


# Shopify Theme Development

## Overview

Build and customize Shopify themes using Liquid templating, JSON templates, sections and blocks for merchant-customizable layouts, and theme app extensions for app integrations. This skill covers the Shopify theme architecture (Online Store 2.0), the Shopify CLI development workflow, performance optimization with lazy loading and critical CSS, and patterns for building flexible sections that merchants can configure through the theme editor.

## When to Use This Skill

- When building a new Shopify theme from scratch or forking Dawn
- When creating custom sections and blocks for the theme editor
- When implementing product pages, collection grids, or cart functionality in Liquid
- When optimizing a Shopify theme for Core Web Vitals and speed
- When building theme app extensions to inject app content into themes

## Core Instructions

1. **Set up the development environment with Shopify CLI**

   ```bash
   # Install Shopify CLI
   npm install -g @shopify/cli @shopify/theme

   # Initialize a new theme (or clone Dawn)
   shopify theme init my-theme

   # Start development server with hot reload
   shopify theme dev --store=your-store.myshopify.com
   ```

   Theme directory structure (Online Store 2.0):
   ```
   my-theme/
   ├── assets/          # CSS, JS, images
   ├── config/          # settings_schema.json, settings_data.json
   ├── layout/          # theme.liquid (main layout)
   ├── locales/         # Translation files
   ├── sections/        # Sections (reusable, merchant-configurable)
   ├── snippets/        # Partials (reusable Liquid fragments)
   └── templates/       # JSON templates referencing sections
       ├── product.json
       ├── collection.json
       └── index.json
   ```

2. **Create a JSON template with sections**

   ```json
   // templates/product.json
   {
     "sections": {
       "main": {
         "type": "main-product",
         "settings": {}
       },
       "recommendations": {
         "type": "product-recommendations",
         "settings": {
           "heading": "You may also like",
           "products_to_show": 4
         }
       },
       "reviews": {
         "type": "product-reviews",
         "settings": {}
       }
     },
     "order": ["main", "recommendations", "reviews"]
   }
   ```

3. **Build a customizable product section with blocks**

   ```liquid
   {% comment %}
     sections/main-product.liquid
   {% endcomment %}

   <section class="product-section" data-section-id="{{ section.id }}">
     <div class="product-grid">
       <div class="product-media">
         {% for media in product.media %}
           {% case media.media_type %}
             {% when 'image' %}
               <div class="product-media-item {% if forloop.first %}active{% endif %}">
                 {{ media | image_url: width: 800 | image_tag:
                   loading: 'lazy',
                   widths: '200,400,600,800,1000',
                   sizes: '(min-width: 768px) 50vw, 100vw',
                   class: 'product-image'
                 }}
               </div>
             {% when 'video' %}
               <div class="product-media-item">
                 {{ media | video_tag: autoplay: false, controls: true }}
               </div>
           {% endcase %}
         {% endfor %}
       </div>

       <div class="product-info">
         {% for block in section.blocks %}
           {% case block.type %}
             {% when 'title' %}
               <h1 class="product-title" {{ block.shopify_attributes }}>
                 {{ product.title }}
               </h1>

             {% when 'price' %}
               <div class="product-price" {{ block.shopify_attributes }}>
                 {% if product.compare_at_price > product.price %}
                   <s class="price-compare">{{ product.compare_at_price | money }}</s>
                 {% endif %}
                 <span class="price-current">{{ product.price | money }}</span>
                 {% if product.compare_at_price > product.price %}
                   <span class="price-badge">Sale</span>
                 {% endif %}
               </div>

             {% when 'variant_picker' %}
               <div class="variant-picker" {{ block.shopify_attributes }}>
                 {% for option in product.options_with_values %}
                   <fieldset class="option-group">
                     <legend>{{ option.name }}</legend>
                     {% for value in option.values %}
                       <label class="option-label">
                         <input
                           type="radio"
                           name="{{ option.name }}"
                           value="{{ value }}"
                           {% if option.selected_value == value %}checked{% endif %}
                         >
                         <span>{{ value }}</span>
                       </label>
                     {% endfor %}
                   </fieldset>
                 {% endfor %}
               </div>

             {% when 'buy_buttons' %}
               <div class="buy-buttons" {{ block.shopify_attributes }}>
                 {% form 'product', product %}
                   <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
                   <div class="quantity-selector">
                     <label for="quantity">Quantity</label>
                     <input type="number" id="quantity" name="quantity" value="1" min="1">
                   </div>
                   <button
                     type="submit"
                     class="btn btn-primary add-to-cart"
                     {% unless product.selected_or_first_available_variant.available %}disabled{% endunless %}
                   >
                     {% if product.selected_or_first_available_variant.available %}
                       Add to cart — {{ product.selected_or_first_available_variant.price | money }}
                     {% else %}
                       Sold out
                     {% endif %}
                   </button>
                 {% endform %}
               </div>

             {% when 'description' %}
               <div class="product-description" {{ block.shopify_attributes }}>
                 {{ product.description }}
               </div>

             {% when 'custom_text' %}
               <div class="custom-text" {{ block.shopify_attributes }}>
                 {{ block.settings.text }}
               </div>
           {% endcase %}
         {% endfor %}
       </div>
     </div>
   </section>

   {% schema %}
   {
     "name": "Product Page",
     "tag": "section",
     "class": "section-product",
     "blocks": [
       {
         "type": "title",
         "name": "Title",
         "limit": 1
       },
       {
         "type": "price",
         "name": "Price",
         "limit": 1
       },
       {
         "type": "variant_picker",
         "name": "Variant Picker",
         "limit": 1
       },
       {
         "type": "buy_buttons",
         "name": "Buy Buttons",
         "limit": 1
       },
       {
         "type": "description",
         "name": "Description",
         "limit": 1
       },
       {
         "type": "custom_text",
         "name": "Custom Text",
         "settings": [
           {
             "type": "richtext",
             "id": "text",
             "label": "Text"
           }
         ]
       }
     ],
     "presets": [
       {
         "name": "Product Page",
         "blocks": [
           { "type": "title" },
           { "type": "price" },
           { "type": "variant_picker" },
           { "type": "buy_buttons" },
           { "type": "description" }
         ]
       }
     ]
   }
   {% endschema %}
   ```

4. **Implement AJAX cart with the Cart API**

   ```javascript
   // assets/cart.js
   class CartManager {
     async addItem(variantId, quantity = 1) {
       const response = await fetch('/cart/add.js', {
         method: 'POST',
      

Related in platform-shopify