Liquid Fundamentals for Modern Themes
Liquid is Shopify's templating language that bridges the gap between your store's data and the HTML rendered to customers. Understanding its core concepts is essential for building performant, maintainable themes.
Modern Shopify themes (Online Store 2.0) have fundamentally changed how we write Liquid. The shift to JSON templates and enhanced section architecture means developers need to think differently about code organization.
Objects, Tags, and Filters
Liquid consists of three main building blocks: Objects output data (like {{ product.title }}), Tags create logic and control flow ({% if %}, {% for %}), and Filters modify output ({{ title | upcase }}).
{% comment %} Good: Using filters for formatting {% endcomment %}
{{ product.price | money_with_currency }}
{% comment %} Better: Combining multiple filters {% endcomment %}
{{ product.description | strip_html | truncatewords: 30 }}
Online Store 2.0 Architecture
OS 2.0 introduced JSON templates that define which sections appear on a page. This allows merchants to customize pages without developer intervention while keeping your Liquid code focused on component rendering.
Optimal File Structure & Organization
A well-organized theme structure reduces cognitive load and makes onboarding new developers significantly easier. Here's the file structure we use at Shugert for all custom Shopify builds:
theme/ ├── assets/ # CSS, JS, images ├── config/ # theme settings ├── layout/ # theme.liquid, password.liquid ├── locales/ # translations ├── sections/ # reusable page sections ├── snippets/ # small reusable components ├── templates/ # JSON page templates └── templates/customers/ # account pages
Naming Conventions
Consistent naming prevents confusion and makes code searchable. We recommend:
- Sections: feature-name.liquid (hero-banner.liquid, product-grid.liquid)
- Snippets: component-name.liquid (icon-cart.liquid, price-display.liquid)
- CSS Classes: BEM methodology (block__element--modifier)
- Variables: snake_case for Liquid variables
Sections and Blocks Architecture
Sections are the building blocks of Shopify themes. Each section should be self-contained with its own schema, styles, and JavaScript when needed.
Schema Design Principles
A well-designed schema makes content editing intuitive for merchants:
{% schema %} { "name": "Featured Collection", "tag": "section", "class": "featured-collection", "settings": [ { "type": "text", "id": "title", "label": "Heading", "default": "Featured Products" }, { "type": "collection", "id": "collection", "label": "Collection" }, { "type": "range", "id": "products_to_show", "min": 4, "max": 12, "step": 2, "default": 8, "label": "Products to show" } ], "presets": [ { "name": "Featured Collection" } ] } {% endschema %}
Block Patterns
Blocks allow merchants to add, remove, and reorder content within sections. Use them for flexible content areas like testimonials, FAQs, or feature lists.
Creating Reusable Snippets
Snippets are small, reusable Liquid files that can be included in sections and templates. They're perfect for components used across multiple pages.
When to Use Snippets
- Product cards displayed on collection, search, and recommendation sections
- Price display logic with sale prices and compare-at prices
- Icon systems with consistent sizing and colors
- Social sharing buttons used across product and blog pages
- Loading spinners and skeleton loaders
Passing Variables to Snippets
{% comment %} Calling snippet with variables {% endcomment %} {% render 'product-card', product: product, show_vendor: true, image_size: 'medium' %} {% comment %} Inside snippets/product-card.liquid {% endcomment %} <div class="product-card"> <img src="{{ product.featured_image | image_url: width: 400 }}" alt="{{ product.title | escape }}"> {% if show_vendor %} <p class="vendor">{{ product.vendor }}</p> {% endif %} <h3>{{ product.title }}</h3> {% render 'price', product: product %} </div>
Performance Optimization Patterns
Liquid executes on Shopify's servers before sending HTML to the browser. Inefficient Liquid code can significantly slow your time-to-first-byte (TTFB).
Cache with Assign and Capture
Avoid calling the same object properties multiple times. Use assign to cache values:
{% comment %} Bad: Multiple calls to the same property {% endcomment %} {% if product.metafields.custom.badge %} <span>{{ product.metafields.custom.badge }}</span> {% endif %} {% if product.metafields.custom.badge == 'sale' %}...{% endif %} {% comment %} Good: Cache the value {% endcomment %} {% assign badge = product.metafields.custom.badge %} {% if badge %} <span>{{ badge }}</span> {% endif %} {% if badge == 'sale' %}...{% endif %}
Minimize Loop Complexity
Nested loops multiply execution time. Flatten data structures where possible:
- Limit products per page (12-24 is typically optimal)
- Use pagination instead of loading all products
- Avoid nested for loops inside product loops
- Use limit and offset filters strategically
Lazy Load Non-Critical Content
Use JavaScript to load secondary content after the initial page render. This improves Core Web Vitals scores significantly.
Working with Metafields
Metafields extend Shopify's data model, allowing custom data on products, collections, customers, and more. They're essential for complex stores with unique data requirements.
Metafield Access Patterns
{% comment %} Accessing product metafields {% endcomment %} {{ product.metafields.custom.care_instructions }} {% comment %} With fallback for missing metafields {% endcomment %} {% assign care = product.metafields.custom.care_instructions | default: 'See product label for care instructions' %} {% comment %} JSON metafields (list or JSON type) {% endcomment %} {% assign features = product.metafields.custom.features.value %} {% for feature in features %} <li>{{ feature }}</li> {% endfor %}
Metafield-Driven Sections
Connect metafields to section settings using dynamic sources. This allows merchants to create product-specific content without custom coding.
Debugging and Testing Strategies
Efficient debugging saves hours of development time. Here are the techniques we use daily:
Debug Output Patterns
{% comment %} Output object structure for debugging {% endcomment %} <pre style="display:none">{{ product | json }}</pre> {% comment %} Conditional debugging {% endcomment %} {% if request.host contains 'preview' %} <div class="debug"> Product ID: {{ product.id }}<br> Variants: {{ product.variants.size }} </div> {% endif %}
Theme Inspector
Shopify's Theme Inspector Chrome extension shows Liquid render times for each section, helping identify performance bottlenecks.
Common Mistakes to Avoid
❌ Mistakes We See Often
- Hardcoding text: Always use section settings or translation files
- Ignoring edge cases: Test with products that have no images, no variants, etc.
- Inline styles: Use CSS classes instead of inline style attributes
- Not escaping output: Use {{ value | escape }} for user-generated content
- Complex conditionals: Break into multiple simpler conditions
- Forgetting mobile: Test responsive layouts with real devices
This isn't for most stores. If it's right for yours, let's scope it properly.
We build custom apps, headless storefronts, and complex theme architectures for stores doing $500K+/yr where off-the-shelf solutions hit a ceiling. We'll give you a scope and number – not a pitch deck.
Published starting point: From $5,000 · Typical delivery window: 4–24 weeks
Start a custom build quoteFinal scope and price are confirmed after technical discovery.
Frequently Asked Questions
What's the biggest Liquid performance mistake?
Should I use sections, blocks, or snippets?
Are Liquid filters faster than JavaScript on the client?
How do I avoid breaking the theme editor with custom code?
Shopify Engineering
Related Articles
Themes, Liquid, custom apps, headless architecture, B2B and platform implementation.
Shopify Development Cost Guide
Realistic cost drivers for theme builds, apps, integrations, migrations and advanced Shopify work.
Read articleCustom Shopify App Development
When custom app development is justified and how to structure the build.
Read articleTechnical SEO for Shopify
Shopify-specific crawlability, metadata, schema, indexation and architecture controls.
Read article