Skip to main content
Version: 1.0.0

Create a Theme

Learn how to create a Shoplazza theme from scratch.

Prerequisites​

Before you start, make sure you have:

  • ✅ A Shoplazza Partner account
  • ✅ Basic knowledge of HTML, CSS, and JavaScript
  • ✅ Familiarity with Liquid templating language
  • ✅ Text editor or IDE (VS Code recommended)
  • ✅ Shoplazza CLI installed

Step 1: Set Up Development Environment​

Install Shoplazza CLI​

npm install -g @shoplazza/cli

Authenticate​

shoplazza login

Create Development Store​

  1. Log in to your Partner Dashboard
  2. Navigate to Stores > Add store
  3. Create a development store for testing

Step 2: Initialize Theme​

Create Theme Directory​

shoplazza theme init my-custom-theme
cd my-custom-theme

This creates a basic theme structure:

my-custom-theme/
├── assets/
│ ├── application.css
│ ├── application.js
│ └── theme.css
├── config/
│ ├── settings_data.json
│ └── settings_schema.json
├── layout/
│ └── theme.liquid
├── locales/
│ └── en.default.json
├── sections/
│ ├── header.liquid
│ ├── footer.liquid
│ └── product-template.liquid
├── snippets/
│ └── product-card.liquid
└── templates/
├── index.liquid
├── product.liquid
├── collection.liquid
└── page.liquid

Step 3: Build Your Layout​

Create Base Layout​

Edit layout/theme.liquid:

<!DOCTYPE html>
<html lang="{{ shop.locale }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page_title }}{% if current_page != 1 %} - {{ 'general.meta.page' | t: page: current_page }}{% endif %}</title>

{% if page_description %}
<meta name="description" content="{{ page_description | escape }}">
{% endif %}

{{ content_for_header }}

{{ 'application.css' | asset_url | stylesheet_tag }}
{{ 'theme.css' | asset_url | stylesheet_tag }}
</head>
<body class="template-{{ template.name }}">

{% section 'header' %}

<main role="main">
{{ content_for_layout }}
</main>

{% section 'footer' %}

{{ 'application.js' | asset_url | script_tag }}
</body>
</html>

Step 4: Create Templates​

Product Template​

Create templates/product.liquid:

{% assign current_variant = product.selected_or_first_available_variant %}

<div class="product-page">
<div class="product-gallery">
<img src="{{ current_variant.featured_image | img_url: '800x' }}"
alt="{{ product.title }}">
</div>

<div class="product-info">
<h1>{{ product.title }}</h1>

<div class="product-price">
<span class="price">{{ current_variant.price | money }}</span>
{% if current_variant.compare_at_price > current_variant.price %}
<span class="compare-price">{{ current_variant.compare_at_price | money }}</span>
{% endif %}
</div>

<div class="product-description">
{{ product.description }}
</div>

{% form 'product', product %}
<select name="id">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{% if variant == current_variant %}selected{% endif %}>
{{ variant.title }} - {{ variant.price | money }}
</option>
{% endfor %}
</select>

<button type="submit" name="add">
Add to Cart
</button>
{% endform %}
</div>
</div>

Collection Template​

Create templates/collection.liquid:

<div class="collection-page">
<header class="collection-header">
<h1>{{ collection.title }}</h1>
{% if collection.description != blank %}
<div class="collection-description">
{{ collection.description }}
</div>
{% endif %}
</header>

<div class="product-grid">
{% for product in collection.products %}
{% render 'product-card', product: product %}
{% endfor %}
</div>

{% if paginate.pages > 1 %}
{% render 'pagination', paginate: paginate %}
{% endif %}
</div>

Step 5: Create Sections​

Header Section​

Create sections/header.liquid:

<header class="site-header">
<nav class="main-navigation">
<a href="/" class="logo">
{% if section.settings.logo %}
<img src="{{ section.settings.logo | img_url: '200x' }}"
alt="{{ shop.name }}">
{% else %}
{{ shop.name }}
{% endif %}
</a>

<ul class="nav-menu">
{% for link in linklists[section.settings.menu].links %}
<li>
<a href="{{ link.url }}">{{ link.title }}</a>
</li>
{% endfor %}
</ul>

<div class="header-icons">
<a href="/search">Search</a>
<a href="/account">Account</a>
<a href="/cart">Cart ({{ cart.item_count }})</a>
</div>
</nav>
</header>

{% schema %}
{
"name": "Header",
"settings": [
{
"type": "image_picker",
"id": "logo",
"label": "Logo"
},
{
"type": "link_list",
"id": "menu",
"label": "Menu",
"default": "main-menu"
}
]
}
{% endschema %}

Step 6: Create Snippets​

Product Card Snippet​

Create snippets/product-card.liquid:

<div class="product-card">
<a href="{{ product.url }}">
<div class="product-card__image">
{% if product.featured_image %}
<img src="{{ product.featured_image | img_url: '400x' }}"
alt="{{ product.title }}">
{% endif %}
</div>

<div class="product-card__info">
<h3 class="product-card__title">{{ product.title }}</h3>

<div class="product-card__price">
{{ product.price | money }}
{% if product.compare_at_price > product.price %}
<span class="compare-price">
{{ product.compare_at_price | money }}
</span>
{% endif %}
</div>
</div>
</a>
</div>

Step 7: Add Styling​

Main Stylesheet​

Edit assets/theme.css:

/* Variables */
:root {
--color-primary: #000;
--color-secondary: #666;
--color-background: #fff;
--spacing-unit: 1rem;
--max-width: 1200px;
}

/* Layout */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
color: var(--color-primary);
line-height: 1.6;
margin: 0;
padding: 0;
}

.container {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 var(--spacing-unit);
}

/* Header */
.site-header {
border-bottom: 1px solid #eee;
padding: 1rem 0;
}

.main-navigation {
display: flex;
align-items: center;
justify-content: space-between;
max-width: var(--max-width);
margin: 0 auto;
padding: 0 var(--spacing-unit);
}

.nav-menu {
display: flex;
gap: 2rem;
list-style: none;
margin: 0;
padding: 0;
}

.nav-menu a {
text-decoration: none;
color: var(--color-primary);
}

/* Product Grid */
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 2rem;
padding: 2rem 0;
}

.product-card {
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
transition: box-shadow 0.3s ease;
}

.product-card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}

.product-card__image img {
width: 100%;
height: auto;
display: block;
}

.product-card__info {
padding: 1rem;
}

.product-card__title {
margin: 0 0 0.5rem;
font-size: 1.1rem;
}

.product-card__price {
font-weight: bold;
}

/* Product Page */
.product-page {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
padding: 3rem 0;
max-width: var(--max-width);
margin: 0 auto;
}

@media (max-width: 768px) {
.product-page {
grid-template-columns: 1fr;
}
}

Step 8: Add JavaScript​

Edit assets/application.js:

// Cart functionality
function addToCart(variantId, quantity = 1) {
fetch('/cart/add.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: variantId,
quantity: quantity
})
})
.then(response => response.json())
.then(data => {
updateCartCount();
showNotification('Added to cart!');
})
.catch(error => {
console.error('Error:', error);
showNotification('Error adding to cart', 'error');
});
}

// Update cart count
function updateCartCount() {
fetch('/cart.js')
.then(response => response.json())
.then(cart => {
document.querySelector('.cart-count').textContent = cart.item_count;
});
}

// Initialize
document.addEventListener('DOMContentLoaded', () => {
// Handle add to cart forms
document.querySelectorAll('form[action="/cart/add"]').forEach(form => {
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
const variantId = formData.get('id');
addToCart(variantId);
});
});
});

Step 9: Test Your Theme​

Start Development Server​

shoplazza theme serve

Preview Your Theme​

Open the provided URL to see your theme in action.

Test Responsive Design​

Test on different devices and screen sizes.

Step 10: Deploy Your Theme​

Upload to Store​

shoplazza theme push

Publish Theme​

  1. Go to your store admin
  2. Navigate to Online Store > Themes
  3. Find your theme and click Publish

Best Practices​

  1. Performance: Optimize images and minimize CSS/JS
  2. Accessibility: Use semantic HTML and ARIA labels
  3. SEO: Include proper meta tags and structured data
  4. Mobile-First: Design for mobile devices first
  5. Testing: Test thoroughly before publishing

Next Steps​