shopify liquid fundamentals

Shopify Liquid Fundamentals

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "shopify liquid fundamentals" with this command: npx skills add sarojpunde/shopify-dev-toolkit-claude-plugins/sarojpunde-shopify-dev-toolkit-claude-plugins-shopify-liquid-fundamentals

Shopify Liquid Fundamentals

Core Principles

Whitespace Control

  • Use {%- -%} to trim whitespace around Liquid tags

  • Prefer {% render %} over deprecated {% include %}

  • Use {% liquid %} for multi-line logic blocks

Example:

{%- liquid assign product_available = product.available | default: false assign product_price = product.price | default: 0

if product == blank assign error_message = 'Product not found' endif -%}

Performance Optimization

  • Minimize Liquid logic in templates

  • Use assign for complex calculations instead of inline logic

  • Cache expensive operations

  • Use snippets for reusable code

Good:

{%- assign discounted_price = product.price | times: 0.9 | money -%} <p>Sale: {{ discounted_price }}</p>

Bad:

<p>Sale: {{ product.price | times: 0.9 | money }}</p> <p>Save: {{ product.price | times: 0.1 | money }}</p>

Error Handling

Always provide defaults and handle empty states:

{%- liquid assign heading = section.settings.heading | default: 'Default Heading' assign show_vendor = section.settings.show_vendor | default: false

if product == blank assign error_message = 'Product unavailable' endif -%}

{%- if error_message -%} <p class="error">{{ error_message }}</p> {%- else -%} <!-- Normal content --> {%- endif -%}

Liquid Syntax Essentials

Output

{{ variable }} # Output variable {{ variable | escape }} # Escape HTML {{ variable | default: 'fallback' }} # Provide default {{- variable -}} # Trim whitespace

Logic

{% if condition %} {% elsif other_condition %} {% else %} {% endif %}

{% unless condition %} {% endunless %}

{% case variable %} {% when 'value1' %} {% when 'value2' %} {% else %} {% endcase %}

Loops

{% for item in collection %} {{ item.title }} {% endfor %}

{% for item in collection limit: 4 %} {{ item.title }} {% endfor %}

{% for i in (1..5) %} Item {{ i }} {% endfor %}

Variables

{% assign name = 'value' %} {% capture variable %} Content here {% endcapture %}

Common Filters

String Filters

{{ 'hello' | capitalize }} # Hello {{ 'HELLO' | downcase }} # hello {{ 'hello' | upcase }} # HELLO {{ 'hello world' | truncate: 8 }} # hello... {{ '<p>test</p>' | escape }} # &lt;p">&gt;test&lt;/p">&gt; {{ 'hello world' | remove: 'world' }} # hello {{ 'hello' | append: ' world' }} # hello world

Array Filters

{{ collection | size }} # Number of items {{ collection | first }} # First item {{ collection | last }} # Last item {{ collection | join: ', ' }} # Join with comma {{ collection | reverse }} # Reverse order {{ collection | sort: 'title' }} # Sort by property

Math Filters

{{ 10 | plus: 5 }} # 15 {{ 10 | minus: 5 }} # 5 {{ 10 | times: 5 }} # 50 {{ 10 | divided_by: 5 }} # 2 {{ 10.5 | ceil }} # 11 {{ 10.5 | floor }} # 10 {{ 10.5 | round }} # 11

Money Filters

{{ 1000 | money }} # $10.00 {{ 1000 | money_with_currency }} # $10.00 USD {{ 1000 | money_without_currency }} # 10.00

Image Filters

{{ image | image_url: width: 400 }} {{ image | image_url: width: 400, height: 400 }} {{ image | image_tag }} {{ image | image_tag: alt: 'Description' }}

Shopify Objects

Global Objects

{{ shop.name }} # Store name {{ shop.email }} # Store email {{ cart.item_count }} # Cart items {{ customer.name }} # Customer name (if logged in) {{ settings.color_primary }} # Theme setting

Product Objects

{{ product.title }} {{ product.price }} {{ product.compare_at_price }} {{ product.available }} {{ product.vendor }} {{ product.type }} {{ product.featured_image }} {{ product.url }}

Collection Objects

{{ collection.title }} {{ collection.description }} {{ collection.products }} {{ collection.products_count }} {{ collection.url }}

Best Practices

  1. Always Escape User Input

<h1>{{ product.title | escape }}</h1> <p>{{ customer.name | escape }}</p>

  1. Provide Defaults

{%- assign heading = section.settings.heading | default: 'Default Title' -%} {%- assign image = product.featured_image | default: blank -%}

  1. Check for Blank Values

{%- if heading != blank -%} <h2>{{ heading | escape }}</h2> {%- endif -%}

  1. Use Liquid Tag for Multi-line Logic

{%- liquid assign is_sale = false if product.compare_at_price > product.price assign is_sale = true endif

assign discount_percent = product.compare_at_price | minus: product.price | times: 100 | divided_by: product.compare_at_price -%}

  1. Minimize Nested Conditions

{%- # Bad -%} {% if product.available %} {% if product.compare_at_price > product.price %} <span>On Sale</span> {% endif %} {% endif %}

{%- # Good -%} {%- liquid assign is_on_sale = false if product.available and product.compare_at_price > product.price assign is_on_sale = true endif -%}

{%- if is_on_sale -%} <span>On Sale</span> {%- endif -%}

Common Patterns

Conditional Class Names

<div class="product{% if product.available %} in-stock{% else %} out-of-stock{% endif %}"> <!-- Content --> </div>

Loop with Index

{%- for product in collection.products -%} <div class="product-{{ forloop.index }}"> {%- if forloop.first -%} <span>Featured</span> {%- endif -%} {{ product.title }} </div> {%- endfor -%}

Empty State Handling

{%- if collection.products.size > 0 -%} {%- for product in collection.products -%} <!-- Product markup --> {%- endfor -%} {%- else -%} <p>No products available.</p> {%- endif -%}

Responsive Images

{%- if product.featured_image -%} <img srcset=" {{ product.featured_image | image_url: width: 400 }} 400w, {{ product.featured_image | image_url: width: 800 }} 800w, {{ product.featured_image | image_url: width: 1200 }} 1200w " sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw" src="{{ product.featured_image | image_url: width: 800 }}" alt="{{ product.featured_image.alt | escape }}" loading="lazy" width="800" height="{{ 800 | divided_by: product.featured_image.aspect_ratio | ceil }}"

{%- endif -%}

Rendering Snippets

Basic Rendering

{% render 'product-card' %}

With Parameters

{% render 'product-card', product: product, show_vendor: true %}

With Multiple Parameters

{% render 'button', text: 'Add to Cart', url: product.url, style: 'primary', size: 'large' %}

Performance Tips

  • Limit loops - Use limit parameter when possible

  • Cache expensive operations - Assign to variables

  • Minimize API calls - Don't call same object property multiple times

  • Use snippets wisely - Balance between reusability and overhead

  • Optimize images - Use appropriate sizes with image filters

Common Mistakes to Avoid

❌ Don't repeat expensive operations:

<p>{{ product.price | times: 1.1 | money }}</p> <p>{{ product.price | times: 1.1 | money }}</p>

✅ Do assign to variable:

{%- assign price_with_tax = product.price | times: 1.1 | money -%} <p>{{ price_with_tax }}</p> <p>{{ price_with_tax }}</p>

❌ Don't forget to escape:

<h1>{{ product.title }}</h1>

✅ Do escape user input:

<h1>{{ product.title | escape }}</h1>

❌ Don't use deprecated include:

{% include 'snippet-name' %}

✅ Do use render:

{% render 'snippet-name' %}

Follow these fundamentals for clean, performant, maintainable Shopify Liquid code.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

shopify workflow & tools

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

polaris-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shopify-api-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shopify section patterns

No summary provided by upstream source.

Repository SourceNeeds Review