Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:32:51 +08:00
commit 636e443771
13 changed files with 6987 additions and 0 deletions

View File

@@ -0,0 +1,345 @@
---
name: shopify-liquid
description: Complete Liquid templating language reference including syntax, filters, objects, control flow, loops, and conditionals for Shopify themes. Use when working with .liquid files, creating theme templates, implementing dynamic content, debugging Liquid code, working with sections and snippets, or rendering product/collection/cart data in Shopify stores.
---
# Shopify Liquid Templating
Expert guidance for Shopify's Liquid templating language including complete syntax reference, filters, objects, and best practices.
## When to Use This Skill
Invoke this skill when:
- Working with `.liquid`, `.css.liquid`, or `.js.liquid` files
- Creating or modifying theme templates (product, collection, cart, etc.)
- Implementing dynamic content rendering
- Using Liquid filters to format data (money, dates, strings)
- Accessing Shopify objects (product, collection, cart, customer)
- Writing conditional logic or loops in templates
- Debugging Liquid syntax errors or output issues
- Creating sections or snippets with Liquid logic
- Formatting prices, dates, or other data
## Core Capabilities
### 1. Liquid Syntax Fundamentals
Three core syntax types:
**Output (display values):**
```liquid
{{ product.title }}
{{ product.price | money }}
{{ collection.products.size }}
```
**Logic (conditionals and control):**
```liquid
{% if product.available %}
<button>Add to Cart</button>
{% else %}
<p>Sold Out</p>
{% endif %}
```
**Assignment (variables):**
```liquid
{% assign sale_price = product.price | times: 0.8 %}
{% capture full_title %}{{ collection.title }} - {{ product.title }}{% endcapture %}
```
**Whitespace control:**
```liquid
{%- if condition -%}
Content (strips whitespace)
{%- endif -%}
```
### 2. Control Flow Tags
**Conditionals:**
- `if/elsif/else/endif` - Standard conditionals
- `unless/endunless` - Negated if
- `case/when/else/endcase` - Switch statements
**Logical operators:**
- `and`, `or` - Combine conditions
- `==`, `!=`, `>`, `<`, `>=`, `<=` - Comparisons
- `contains` - Substring/array search
**Example:**
```liquid
{% if product.available and product.price < 100 %}
Affordable and in stock
{% elsif product.available %}
Available but pricey
{% else %}
Out of stock
{% endif %}
```
### 3. Iteration (Loops)
**for loop:**
```liquid
{% for product in collection.products %}
{{ product.title }}
{% endfor %}
{# With modifiers #}
{% for product in collection.products limit: 5 offset: 10 reversed %}
{{ product.title }}
{% endfor %}
```
**forloop object:**
```liquid
{% for item in array %}
{{ forloop.index }} {# 1-based index #}
{{ forloop.index0 }} {# 0-based index #}
{{ forloop.first }} {# Boolean: first item #}
{{ forloop.last }} {# Boolean: last item #}
{{ forloop.length }} {# Total items #}
{% endfor %}
```
**Pagination:**
```liquid
{% paginate collection.products by 12 %}
{% for product in paginate.collection.products %}
{% render 'product-card', product: product %}
{% endfor %}
{% if paginate.pages > 1 %}
{{ paginate | default_pagination }}
{% endif %}
{% endpaginate %}
```
### 4. Essential Filters
**Money formatting:**
```liquid
{{ 1000 | money }} {# $10.00 #}
{{ 1000 | money_without_currency }} {# 10.00 #}
{{ 1000 | money_without_trailing_zeros }} {# $10 #}
```
**String manipulation:**
```liquid
{{ "hello" | upcase }} {# HELLO #}
{{ "hello" | capitalize }} {# Hello #}
{{ "hello world" | truncate: 8 }} {# hello... #}
{{ "a,b,c" | split: "," }} {# ["a","b","c"] #}
{{ text | strip_html }} {# Remove HTML tags #}
```
**Array/collection:**
```liquid
{{ array | first }} {# First element #}
{{ array | last }} {# Last element #}
{{ array | size }} {# Count #}
{{ products | map: "title" }} {# Extract property #}
{{ products | where: "vendor", "Nike" }} {# Filter #}
{{ products | sort: "price" }} {# Sort #}
{{ array | join: ", " }} {# Join with separator #}
```
**Date formatting:**
```liquid
{{ order.created_at | date: '%B %d, %Y' }} {# November 10, 2025 #}
{{ order.created_at | date: '%m/%d/%Y' }} {# 11/10/2025 #}
{{ order.created_at | date: '%H:%M %p' }} {# 12:39 PM #}
```
**Image handling:**
```liquid
{{ product.image | img_url: '500x500' }} {# Resize image #}
{{ product.image | img_url: 'medium' }} {# Named size #}
{{ 'logo.png' | asset_url }} {# Theme asset CDN #}
```
**Math operations:**
```liquid
{{ 5 | plus: 3 }} {# 8 #}
{{ 5 | minus: 3 }} {# 2 #}
{{ 5 | times: 3 }} {# 15 #}
{{ 10 | divided_by: 2 }} {# 5 #}
{{ 1.567 | round: 2 }} {# 1.57 #}
```
**Chaining filters:**
```liquid
{{ collection.products | where: "available" | map: "title" | sort | first }}
```
### 5. Key Shopify Objects
**Product object:**
```liquid
{{ product.title }}
{{ product.price | money }}
{{ product.available }} {# Boolean #}
{{ product.vendor }}
{{ product.type }}
{{ product.images }} {# Array #}
{{ product.variants }} {# Array #}
{{ product.selected_variant }}
{{ product.metafields.custom.field }}
```
**Collection object:**
```liquid
{{ collection.title }}
{{ collection.products }} {# Array #}
{{ collection.products_count }}
{{ collection.all_tags }}
{{ collection.sort_by }}
{{ collection.filters }}
```
**Cart object (global):**
```liquid
{{ cart.item_count }}
{{ cart.total_price | money }}
{{ cart.items }} {# Array of line items #}
{{ cart.empty? }} {# Boolean #}
```
**Customer object:**
```liquid
{{ customer.name }}
{{ customer.email }}
{{ customer.orders_count }}
{{ customer.total_spent | money }}
{{ customer.default_address }}
```
**Global objects:**
```liquid
{{ shop.name }}
{{ shop.currency }}
{{ shop.url }}
{{ request.path }}
{{ request.page_type }} {# "product", "collection", etc. #}
{{ settings.color_primary }} {# Theme settings #}
```
### 6. Template Inclusion
**render (isolated scope - PREFERRED):**
```liquid
{% render 'product-card', product: product, show_price: true %}
{# Render for each item #}
{% render 'product-card' for collection.products as item %}
```
**include (shared scope - LEGACY):**
```liquid
{% include 'product-details' %}
```
**section (dynamic sections):**
```liquid
{% section 'featured-product' %}
```
## Common Patterns
### Product availability check
```liquid
{% if product.available %}
<button type="submit">Add to Cart</button>
{% elsif product.selected_variant.incoming %}
<p>Coming {{ product.selected_variant.incoming_date | date: '%B %d' }}</p>
{% else %}
<p class="sold-out">Sold Out</p>
{% endif %}
```
### Price display with sale
```liquid
{% if product.compare_at_price > product.price %}
<span class="sale-price">{{ product.price | money }}</span>
<span class="original-price">{{ product.compare_at_price | money }}</span>
<span class="savings">Save {{ product.compare_at_price | minus: product.price | money }}</span>
{% else %}
<span class="price">{{ product.price | money }}</span>
{% endif %}
```
### Loop through variants
```liquid
{% for variant in product.variants %}
<option
value="{{ variant.id }}"
{% unless variant.available %}disabled{% endunless %}
>
{{ variant.title }} - {{ variant.price | money }}
</option>
{% endfor %}
```
### Check collection tags
```liquid
{% if collection.all_tags contains 'sale' %}
<div class="sale-banner">Sale items available!</div>
{% endif %}
```
## Best Practices
1. **Use whitespace control** (`{%-` and `-%}`) to keep HTML clean
2. **Prefer `render` over `include`** for better performance and isolation
3. **Cache expensive operations** by assigning to variables
4. **Use descriptive variable names** for clarity
5. **Leverage filters** instead of complex logic when possible
6. **Check for existence** before accessing nested properties
7. **Use `default` filter** for fallback values: `{{ product.metafield | default: "N/A" }}`
## Detailed References
For comprehensive documentation:
- **[references/syntax.md](references/syntax.md)** - Complete syntax reference with all tags
- **[references/filters.md](references/filters.md)** - All 60+ filters with examples
- **[references/objects.md](references/objects.md)** - Complete object property reference
## Integration with Other Skills
- **shopify-theme-dev** - Use when working with theme file structure and sections
- **shopify-api** - Use when fetching data via Ajax or GraphQL to display in Liquid
- **shopify-debugging** - Use when troubleshooting Liquid rendering issues
- **shopify-performance** - Use when optimizing Liquid template performance
## Quick Syntax Reference
```liquid
{# Output #}
{{ variable }}
{{ product.title | upcase }}
{# Conditionals #}
{% if condition %}...{% elsif %}...{% else %}...{% endif %}
{% unless condition %}...{% endunless %}
{% case variable %}{% when value %}...{% endcase %}
{# Loops #}
{% for item in array %}...{% endfor %}
{% for item in array limit: 5 offset: 10 %}...{% endfor %}
{% break %} / {% continue %}
{# Variables #}
{% assign var = value %}
{% capture var %}content{% endcapture %}
{# Inclusion #}
{% render 'snippet', param: value %}
{% section 'section-name' %}
{# Comments #}
{% comment %}...{% endcomment %}
{# Single line #}
```

View File

@@ -0,0 +1,873 @@
# Liquid Filters - Complete Reference
Filters modify output using pipe syntax: `{{ value | filter: parameter }}`
## String Filters
### upcase
Convert to uppercase:
```liquid
{{ "hello world" | upcase }}
{# Output: HELLO WORLD #}
```
### downcase
Convert to lowercase:
```liquid
{{ "HELLO WORLD" | downcase }}
{# Output: hello world #}
```
### capitalize
Capitalize first letter only:
```liquid
{{ "hello world" | capitalize }}
{# Output: Hello world #}
```
### reverse
Reverse string or array:
```liquid
{{ "hello" | reverse }}
{# Output: olleh #}
{{ array | reverse }}
{# Reverses array order #}
```
### size
Get character count or array length:
```liquid
{{ "hello" | size }}
{# Output: 5 #}
{{ collection.products | size }}
{# Output: number of products #}
```
### remove
Remove all occurrences of substring:
```liquid
{{ "hello world world" | remove: "world" }}
{# Output: hello #}
```
### remove_first
Remove first occurrence only:
```liquid
{{ "hello world world" | remove_first: "world" }}
{# Output: hello world #}
```
### replace
Replace all occurrences:
```liquid
{{ "hello" | replace: "l", "L" }}
{# Output: heLLo #}
```
### replace_first
Replace first occurrence only:
```liquid
{{ "hello" | replace_first: "l", "L" }}
{# Output: heLlo #}
```
### split
Split string into array:
```liquid
{{ "a,b,c,d" | split: "," }}
{# Output: ["a", "b", "c", "d"] #}
{% assign tags = "sale,new,featured" | split: "," %}
{% for tag in tags %}
{{ tag }}
{% endfor %}
```
### strip
Remove leading and trailing whitespace:
```liquid
{{ " hello " | strip }}
{# Output: hello #}
```
### lstrip
Remove leading whitespace only:
```liquid
{{ " hello " | lstrip }}
{# Output: hello #}
```
### rstrip
Remove trailing whitespace only:
```liquid
{{ " hello " | rstrip }}
{# Output: hello #}
```
### truncate
Limit string length with ellipsis:
```liquid
{{ "hello world" | truncate: 8 }}
{# Output: hello... #}
{{ "hello world" | truncate: 10, "!" }}
{# Output: hello worl! #}
{{ "hello world" | truncate: 50 }}
{# Output: hello world (no truncation if shorter) #}
```
### truncatewords
Limit by word count:
```liquid
{{ "hello world testing" | truncatewords: 2 }}
{# Output: hello world... #}
{{ "hello world testing" | truncatewords: 2, "--" }}
{# Output: hello world-- #}
```
### append
Add string to end:
```liquid
{{ "hello" | append: " world" }}
{# Output: hello world #}
{% assign file_name = "image" | append: ".jpg" %}
{# file_name: image.jpg #}
```
### prepend
Add string to beginning:
```liquid
{{ "world" | prepend: "hello " }}
{# Output: hello world #}
```
### newline_to_br
Convert newlines to `<br>` tags:
```liquid
{{ product.description | newline_to_br }}
{# Converts \n to <br> #}
```
### strip_html
Remove all HTML tags:
```liquid
{{ "<p>Hello <strong>world</strong></p>" | strip_html }}
{# Output: Hello world #}
```
### escape
Escape HTML special characters:
```liquid
{{ "<div>Test</div>" | escape }}
{# Output: &lt;div&gt;Test&lt;/div&gt; #}
```
### escape_once
Escape HTML but don't double-escape:
```liquid
{{ "&lt;div&gt;" | escape_once }}
{# Output: &lt;div&gt; (not double-escaped) #}
```
### url_encode
URL-encode string:
```liquid
{{ "hello world" | url_encode }}
{# Output: hello+world #}
{{ "foo@bar.com" | url_encode }}
{# Output: foo%40bar.com #}
```
### url_decode
Decode URL-encoded string:
```liquid
{{ "hello+world" | url_decode }}
{# Output: hello world #}
```
### base64_encode
Encode to base64:
```liquid
{{ "hello" | base64_encode }}
{# Output: aGVsbG8= #}
```
### base64_decode
Decode from base64:
```liquid
{{ "aGVsbG8=" | base64_decode }}
{# Output: hello #}
```
### slice
Extract substring or array slice:
```liquid
{{ "hello" | slice: 0, 3 }}
{# Output: hel #}
{{ "hello" | slice: -3, 3 }}
{# Output: llo #}
```
## Numeric Filters
### abs
Absolute value:
```liquid
{{ -5 | abs }}
{# Output: 5 #}
{{ 5 | abs }}
{# Output: 5 #}
```
### ceil
Round up to nearest integer:
```liquid
{{ 1.2 | ceil }}
{# Output: 2 #}
{{ 1.9 | ceil }}
{# Output: 2 #}
```
### floor
Round down to nearest integer:
```liquid
{{ 1.9 | floor }}
{# Output: 1 #}
{{ 1.1 | floor }}
{# Output: 1 #}
```
### round
Round to specified decimal places:
```liquid
{{ 1.5 | round }}
{# Output: 2 #}
{{ 1.567 | round: 2 }}
{# Output: 1.57 #}
{{ 1.234 | round: 1 }}
{# Output: 1.2 #}
```
### plus
Addition:
```liquid
{{ 5 | plus: 3 }}
{# Output: 8 #}
{{ product.price | plus: 1000 }}
{# Add $10.00 (prices in cents) #}
```
### minus
Subtraction:
```liquid
{{ 5 | minus: 3 }}
{# Output: 2 #}
```
### times
Multiplication:
```liquid
{{ 5 | times: 3 }}
{# Output: 15 #}
{{ product.price | times: 0.8 }}
{# 20% discount #}
```
### divided_by
Integer division:
```liquid
{{ 10 | divided_by: 2 }}
{# Output: 5 #}
{{ 10 | divided_by: 3 }}
{# Output: 3 (integer division) #}
{{ 10.0 | divided_by: 3 }}
{# Output: 3.33... (float division) #}
```
### modulo
Get remainder:
```liquid
{{ 10 | modulo: 3 }}
{# Output: 1 #}
{# Check if even #}
{% if forloop.index | modulo: 2 == 0 %}
Even row
{% endif %}
```
### at_least
Ensure minimum value:
```liquid
{{ 1 | at_least: 5 }}
{# Output: 5 #}
{{ 10 | at_least: 5 }}
{# Output: 10 #}
```
### at_most
Ensure maximum value:
```liquid
{{ 100 | at_most: 50 }}
{# Output: 50 #}
{{ 10 | at_most: 50 }}
{# Output: 10 #}
```
## Array/Collection Filters
### first
Get first element:
```liquid
{{ collection.products | first }}
{# Returns first product #}
{{ "a,b,c" | split: "," | first }}
{# Output: a #}
```
### last
Get last element:
```liquid
{{ collection.products | last }}
{# Returns last product #}
```
### join
Join array with separator:
```liquid
{{ product.tags | join: ", " }}
{# Output: sale, new, featured #}
```
### map
Extract property from each object:
```liquid
{{ collection.products | map: "title" }}
{# Returns array of product titles #}
{{ collection.products | map: "title" | join: ", " }}
{# Output: Product 1, Product 2, Product 3 #}
```
### sort
Sort array by property:
```liquid
{{ collection.products | sort: "price" }}
{# Sort by price ascending #}
{{ collection.products | sort: "title" }}
{# Sort alphabetically #}
```
### sort_natural
Case-insensitive sort:
```liquid
{{ collection.products | sort_natural: "title" }}
{# Sorts: Apple, banana, Cherry (natural order) #}
```
### where
Filter array by property value:
```liquid
{{ collection.products | where: "vendor", "Nike" }}
{# Only Nike products #}
{{ collection.products | where: "available", true }}
{# Only available products #}
{{ collection.products | where: "type", "shoes" | map: "title" }}
{# Combine with map #}
```
### uniq
Remove duplicates:
```liquid
{{ collection.all_vendors | uniq }}
{# Unique vendor names #}
```
### limit
Limit array to N items:
```liquid
{{ collection.products | limit: 5 }}
{# First 5 products #}
```
### offset
Skip first N items:
```liquid
{{ collection.products | offset: 10 }}
{# Products from 11th onward #}
```
### concat
Merge two arrays:
```liquid
{% assign array1 = "a,b,c" | split: "," %}
{% assign array2 = "d,e,f" | split: "," %}
{{ array1 | concat: array2 | join: ", " }}
{# Output: a, b, c, d, e, f #}
```
### compact
Remove nil values from array:
```liquid
{{ array | compact }}
{# Removes nil/null elements #}
```
## Shopify-Specific Filters
### money
Format as currency with symbol:
```liquid
{{ 1000 | money }}
{# Output: $10.00 #}
{{ 1599 | money }}
{# Output: $15.99 #}
```
### money_without_currency
Format without currency symbol:
```liquid
{{ 1000 | money_without_currency }}
{# Output: 10.00 #}
```
### money_without_trailing_zeros
Remove unnecessary decimals:
```liquid
{{ 1000 | money_without_trailing_zeros }}
{# Output: $10 #}
{{ 1050 | money_without_trailing_zeros }}
{# Output: $10.50 #}
```
### weight_with_unit
Add weight unit:
```liquid
{{ 500 | weight_with_unit }}
{# Output: 500 g #}
{{ product.variants.first.weight | weight_with_unit }}
```
### asset_url
Get theme asset CDN URL:
```liquid
{{ 'logo.png' | asset_url }}
{# Output: //cdn.shopify.com/s/files/1/0000/0000/t/1/assets/logo.png #}
```
### img_url
Generate image URL with size:
```liquid
{{ product.featured_image | img_url: '500x500' }}
{# Resize to 500x500 #}
{{ product.featured_image | img_url: 'large' }}
{# Named size: pico, icon, thumb, small, compact, medium, large, grande, 1024x1024, 2048x2048 #}
{{ product.featured_image | img_url: '500x500', crop: 'center' }}
{# With crop #}
```
### link_to_type
Create link to product type collection:
```liquid
{{ product.type | link_to_type }}
{# Output: <a href="/collections/types?q=Shoes">Shoes</a> #}
```
### link_to_vendor
Create link to vendor collection:
```liquid
{{ product.vendor | link_to_vendor }}
{# Output: <a href="/collections/vendors?q=Nike">Nike</a> #}
```
### link_to_tag
Create link to tag filter:
```liquid
{{ tag | link_to_tag: tag }}
{# Output: <a href="/collections/all/sale">sale</a> #}
```
### highlight
Highlight search terms:
```liquid
{{ product.title | highlight: search.terms }}
{# Wraps search terms in <strong class="highlight"> tags #}
```
### highlight_active_tag
Highlight current tag:
```liquid
{{ tag | highlight_active_tag: tag }}
{# Wraps current tag in <span class="active"> #}
```
### payment_type_img_url
Get payment icon URL:
```liquid
{{ 'visa' | payment_type_img_url }}
{# Returns Shopify-hosted Visa icon URL #}
```
### placeholder_svg_tag
Generate placeholder SVG:
```liquid
{{ 'product-1' | placeholder_svg_tag }}
{# Generates placeholder product image SVG #}
{{ 'collection-1' | placeholder_svg_tag: 'custom-class' }}
{# With custom CSS class #}
```
### color_to_rgb
Convert hex to RGB:
```liquid
{{ '#ff0000' | color_to_rgb }}
{# Output: rgb(255, 0, 0) #}
```
### color_to_hsl
Convert hex to HSL:
```liquid
{{ '#ff0000' | color_to_hsl }}
{# Output: hsl(0, 100%, 50%) #}
```
### color_extract
Extract color component:
```liquid
{{ '#ff0000' | color_extract: 'red' }}
{# Output: 255 #}
```
### color_brightness
Calculate brightness:
```liquid
{{ '#ff0000' | color_brightness }}
{# Output: brightness value 0-255 #}
```
### color_modify
Modify color properties:
```liquid
{{ '#ff0000' | color_modify: 'alpha', 0.5 }}
{# Adjust alpha channel #}
```
## Date Filters
### date
Format date using strftime:
```liquid
{{ order.created_at | date: '%B %d, %Y' }}
{# Output: November 10, 2025 #}
{{ order.created_at | date: '%m/%d/%Y' }}
{# Output: 11/10/2025 #}
{{ order.created_at | date: '%Y-%m-%d %H:%M:%S' }}
{# Output: 2025-11-10 14:30:00 #}
```
**Common format codes:**
- `%Y` - 4-digit year (2025)
- `%y` - 2-digit year (25)
- `%m` - Month number (11)
- `%B` - Full month (November)
- `%b` - Short month (Nov)
- `%d` - Day of month (10)
- `%e` - Day without leading zero (10)
- `%A` - Full weekday (Monday)
- `%a` - Short weekday (Mon)
- `%H` - Hour 24-hour (14)
- `%I` - Hour 12-hour (02)
- `%M` - Minutes (30)
- `%S` - Seconds (45)
- `%p` - AM/PM
- `%z` - Timezone offset (+0000)
**Examples:**
```liquid
{{ "now" | date: "%Y-%m-%d" }}
{# Current date: 2025-11-10 #}
{{ article.published_at | date: "%B %d, %Y at %I:%M %p" }}
{# November 10, 2025 at 02:30 PM #}
```
## URL Filters
### url_for_type
Get collection URL for product type:
```liquid
{{ product.type | url_for_type }}
{# Output: /collections/types?q=Shoes #}
```
### url_for_vendor
Get collection URL for vendor:
```liquid
{{ product.vendor | url_for_vendor }}
{# Output: /collections/vendors?q=Nike #}
```
### within
Scope URL within collection:
```liquid
{{ product.url | within: collection }}
{# Output: /collections/sale/products/product-handle #}
```
### default_pagination
Generate pagination HTML:
```liquid
{{ paginate | default_pagination }}
{# Outputs complete pagination HTML #}
```
## Utility Filters
### default
Provide fallback value:
```liquid
{{ product.metafield | default: "N/A" }}
{# If metafield is nil, outputs "N/A" #}
{{ variant.title | default: "Default" }}
```
### json
Convert to JSON:
```liquid
{{ product | json }}
{# Outputs product object as JSON string #}
<script>
var productData = {{ product | json }};
</script>
```
## Filter Chaining
Filters execute left-to-right and can be chained:
```liquid
{{ "hello world" | upcase | replace: "WORLD", "SHOPIFY" }}
{# Output: HELLO SHOPIFY #}
{{ collection.products | where: "available" | map: "title" | sort | join: ", " }}
{# Filter → extract → sort → join #}
{{ product.price | times: 0.8 | round: 2 | money }}
{# Calculate 20% discount, round, format as money #}
{{ product.description | strip_html | truncatewords: 50 | escape }}
{# Strip HTML → truncate → escape for safety #}
```
## Performance Tips
1. **Cache filtered results** if used multiple times:
```liquid
{# ❌ Inefficient: #}
{% for i in (1..10) %}
{{ collection.products | where: "available" | size }}
{% endfor %}
{# ✅ Efficient: #}
{% assign available_products = collection.products | where: "available" %}
{% for i in (1..10) %}
{{ available_products.size }}
{% endfor %}
```
2. **Use `limit` and `offset` filters** instead of manual iteration control
3. **Combine filters intelligently** to reduce operations:
```liquid
{# ❌ Less efficient: #}
{% assign titles = collection.products | map: "title" %}
{% assign sorted = titles | sort %}
{% assign limited = sorted | limit: 5 %}
{# ✅ More efficient: #}
{% assign limited_titles = collection.products | map: "title" | sort | limit: 5 %}
```

View File

@@ -0,0 +1,695 @@
# Liquid Objects - Complete Reference
## Global Objects (Available Everywhere)
### shop
Store-level information:
```liquid
{{ shop.name }} {# Store name #}
{{ shop.url }} {# Store URL (https://...) #}
{{ shop.description }} {# Store tagline/description #}
{{ shop.currency }} {# ISO currency code: USD, GBP, EUR #}
{{ shop.money_format }} {# Money format string: ${{amount}} #}
{{ shop.permanent_domain }} {# Domain: store.myshopify.com #}
{{ shop.domain }} {# Primary domain #}
{{ shop.email }} {# Support email #}
{{ shop.phone }} {# Support phone #}
{{ shop.address }} {# Store address object #}
{{ shop.address.city }}
{{ shop.address.province }}
{{ shop.address.country }}
{{ shop.address.zip }}
{{ shop.enabled_payment_types }} {# Array of enabled payment methods #}
{{ shop.checkout.privacy_policy_url }}
{{ shop.checkout.terms_of_service_url }}
{{ shop.checkout.refund_policy_url }}
```
### request
Request context and routing:
```liquid
{{ request.path }} {# Current URL path: /products/handle #}
{{ request.host }} {# Current domain #}
{{ request.origin }} {# Protocol + host #}
{{ request.page_type }} {# "product", "collection", "index", etc. #}
{{ request.locale.iso_code }} {# Language: "en", "fr", "es" #}
{{ request.locale.root_url }} {# Root URL for locale #}
{{ request.design_mode }} {# Boolean: theme editor active #}
{{ request.visual_preview_mode }} {# Boolean: theme preview active #}
{# Query parameters #}
{{ request.query_string }} {# Full query string #}
{# Build canonical URL #}
{{ request.canonical_url }} {# Full canonical URL #}
{{ request.path_with_query }} {# Path + query string #}
```
### settings
Theme settings (from settings_schema.json):
```liquid
{# Colors #}
{{ settings.color_primary }}
{{ settings.color_secondary }}
{{ settings.color_body_bg }}
{# Typography #}
{{ settings.type_header_font }}
{{ settings.type_body_font }}
{# Layout #}
{{ settings.layout_container_width }}
{{ settings.layout_sidebar_enabled }}
{# Media #}
{{ settings.logo }} {# Image object #}
{{ settings.logo.src }}
{{ settings.logo.width }}
{{ settings.logo.height }}
{{ settings.logo.alt }}
{# Text content #}
{{ settings.announcement_text }}
{{ settings.footer_text }}
{# Boolean settings #}
{% if settings.show_breadcrumbs %}
{# Render breadcrumbs #}
{% endif %}
{# URL settings #}
{{ settings.social_twitter_link }}
{{ settings.social_facebook_link }}
```
### routes
URL routes to standard pages:
```liquid
{{ routes.root_url }} {# / #}
{{ routes.account_url }} {# /account #}
{{ routes.account_login_url }} {# /account/login #}
{{ routes.account_logout_url }} {# /account/logout #}
{{ routes.account_register_url }} {# /account/register #}
{{ routes.account_addresses_url }} {# /account/addresses #}
{{ routes.collections_url }} {# /collections #}
{{ routes.all_products_collection_url }} {# /collections/all #}
{{ routes.search_url }} {# /search #}
{{ routes.cart_url }} {# /cart #}
{{ routes.cart_add_url }} {# /cart/add #}
{{ routes.cart_change_url }} {# /cart/change #}
{{ routes.cart_clear_url }} {# /cart/clear #}
{{ routes.cart_update_url }} {# /cart/update #}
```
### section
Current section context (within sections):
```liquid
{{ section.id }} {# Unique ID: "section-1234567890" #}
{{ section.settings.title }} {# Section setting #}
{{ section.settings.background_color }}
{{ section.index }} {# Position on page #}
{{ section.location }} {# Where section appears #}
{# Blocks #}
{{ section.blocks }} {# Array of blocks #}
{{ section.blocks.size }} {# Number of blocks #}
{% for block in section.blocks %}
{{ block.id }}
{{ block.type }}
{{ block.settings.text }}
{{ block.shopify_attributes }} {# Required for theme editor #}
{% endfor %}
{# Blocks by type #}
{{ section.blocks_by_type }} {# Organized by type #}
```
### block
Current block context (within section blocks):
```liquid
{{ block.id }} {# Unique ID: "block-9876543210" #}
{{ block.type }} {# Block type name #}
{{ block.settings.text }} {# Block setting #}
{{ block.shopify_attributes }} {# Required for theme editor #}
{# Example usage in section #}
{% for block in section.blocks %}
<div {{ block.shopify_attributes }}>
{% case block.type %}
{% when 'heading' %}
<h2>{{ block.settings.title }}</h2>
{% when 'text' %}
<p>{{ block.settings.content }}</p>
{% endcase %}
</div>
{% endfor %}
```
## Page Context Objects
### product
Product object (on product pages):
```liquid
{# Core properties #}
{{ product.id }} {# Numeric ID #}
{{ product.title }} {# Product name #}
{{ product.handle }} {# URL slug #}
{{ product.description }} {# Full HTML description #}
{{ product.vendor }} {# Brand/manufacturer #}
{{ product.type }} {# Category #}
{{ product.url }} {# Product URL #}
{{ product.available }} {# Boolean: any variant in stock #}
{{ product.published_at }} {# Publication timestamp #}
{{ product.created_at }} {# Creation timestamp #}
{{ product.updated_at }} {# Last modified timestamp #}
{# Pricing (in cents) #}
{{ product.price }} {# Current variant price #}
{{ product.price_min }} {# Cheapest variant #}
{{ product.price_max }} {# Most expensive variant #}
{{ product.price_varies }} {# Boolean: different prices #}
{{ product.compare_at_price }} {# Original price for sales #}
{{ product.compare_at_price_min }}
{{ product.compare_at_price_max }}
{{ product.compare_at_price_varies }}
{# Images #}
{{ product.featured_image }} {# Primary image object #}
{{ product.featured_image.src }}
{{ product.featured_image.width }}
{{ product.featured_image.height }}
{{ product.featured_image.alt }}
{{ product.featured_image | img_url: '500x500' }}
{{ product.images }} {# Array of all images #}
{{ product.images.size }} {# Image count #}
{% for image in product.images %}
<img src="{{ image | img_url: '300x300' }}" alt="{{ image.alt }}">
{% endfor %}
{{ product.media }} {# Array of all media (images, videos, 3D) #}
{# Variants #}
{{ product.variants }} {# Array of variants #}
{{ product.variants.size }} {# Variant count #}
{{ product.selected_variant }} {# Currently selected variant #}
{{ product.selected_or_first_available_variant }}
{{ product.first_available_variant }}
{{ product.has_only_default_variant }} {# Boolean: single variant #}
{# Options #}
{{ product.options }} {# Array: ["Size", "Color"] #}
{{ product.options_with_values }} {# Array of option objects #}
{% for option in product.options_with_values %}
<label>{{ option.name }}</label>
<select>
{% for value in option.values %}
<option>{{ value }}</option>
{% endfor %}
</select>
{% endfor %}
{# Collections #}
{{ product.collections }} {# Array of collections #}
{{ product.collections.size }}
{# Tags #}
{{ product.tags }} {# Array of tags #}
{{ product.tags | join: ", " }}
{# Custom data #}
{{ product.metafields.namespace.key }}
{{ product.metafields.custom.field_name }}
{# Template #}
{{ product.template_suffix }} {# Template variant: "alternate" #}
```
### variant
Variant object (product.variants, product.selected_variant):
```liquid
{{ variant.id }} {# Variant ID #}
{{ variant.product_id }} {# Parent product ID #}
{{ variant.title }} {# "Red / Medium" #}
{{ variant.price }} {# Price in cents #}
{{ variant.compare_at_price }} {# Original price #}
{{ variant.sku }} {# SKU code #}
{{ variant.barcode }} {# Barcode #}
{{ variant.weight }} {# Weight in grams #}
{{ variant.weight_unit }} {# "kg", "lb", etc. #}
{{ variant.weight_in_unit }} {# Weight in configured unit #}
{# Availability #}
{{ variant.available }} {# Boolean: in stock #}
{{ variant.inventory_quantity }} {# Current stock level #}
{{ variant.inventory_policy }} {# "continue" or "deny" #}
{{ variant.inventory_management }} {# "shopify" or null #}
{# Options #}
{{ variant.option1 }} {# First option value: "Red" #}
{{ variant.option2 }} {# Second option value: "Medium" #}
{{ variant.option3 }} {# Third option value #}
{{ variant.options }} {# Array: ["Red", "Medium"] #}
{# Image #}
{{ variant.featured_image }} {# Variant-specific image #}
{{ variant.image }} {# Same as featured_image #}
{# URL #}
{{ variant.url }} {# Product URL with variant param #}
{# Metafields #}
{{ variant.metafields.namespace.key }}
```
### collection
Collection object (on collection pages):
```liquid
{# Core properties #}
{{ collection.id }} {# Numeric ID #}
{{ collection.title }} {# Collection name #}
{{ collection.handle }} {# URL slug #}
{{ collection.description }} {# HTML description #}
{{ collection.url }} {# Collection URL #}
{{ collection.published_at }} {# Publication date #}
{# Image #}
{{ collection.image }} {# Featured image object #}
{{ collection.image.src }}
{{ collection.image | img_url: '1024x1024' }}
{# Products #}
{{ collection.products }} {# Array of products #}
{{ collection.products_count }} {# Current page count #}
{{ collection.all_products_count }}{# Total count #}
{# Filtering & sorting #}
{{ collection.all_tags }} {# All tags (max 1000) #}
{{ collection.all_types }} {# All product types #}
{{ collection.all_vendors }} {# All vendors #}
{{ collection.current_type }} {# Active type filter #}
{{ collection.current_vendor }} {# Active vendor filter #}
{{ collection.sort_by }} {# Current sort method #}
{{ collection.default_sort_by }} {# Default sort #}
{{ collection.sort_options }} {# Available sort methods #}
{# Filters (Storefront Filtering) #}
{{ collection.filters }} {# Array of filter objects #}
{% for filter in collection.filters %}
{{ filter.label }} {# Filter name #}
{{ filter.type }} {# "list", "price_range" #}
{{ filter.active_values }} {# Currently active #}
{{ filter.values }} {# Available values #}
{% endfor %}
{# Navigation (on product pages within collection) #}
{{ collection.next_product }} {# Next product in collection #}
{{ collection.previous_product }} {# Previous product #}
{# Metafields #}
{{ collection.metafields.namespace.key }}
{# Template #}
{{ collection.template_suffix }}
```
### cart
Cart object (global - always available):
```liquid
{# Cart state #}
{{ cart.item_count }} {# Total line items #}
{{ cart.total_price }} {# Total in cents #}
{{ cart.total_weight }} {# Weight sum #}
{{ cart.empty? }} {# Boolean: is cart empty #}
{# Items #}
{{ cart.items }} {# Array of line items #}
{{ cart.items.size }} {# Number of line items #}
{% for item in cart.items %}
{{ item.product_id }}
{{ item.variant_id }}
{{ item.title }}
{{ item.quantity }}
{{ item.price }}
{{ item.line_price }} {# price × quantity #}
{{ item.image }}
{% endfor %}
{# Notes and attributes #}
{{ cart.note }} {# Customer note #}
{{ cart.attributes }} {# Custom cart attributes #}
{# Access specific attribute #}
{% if cart.attributes.gift_wrap %}
Gift wrap requested
{% endif %}
{# Discounts #}
{{ cart.cart_level_discount_applications }}
{{ cart.total_discount }} {# Total discount amount #}
{# Checkout #}
{{ cart.requires_shipping }} {# Boolean #}
```
### line_item
Line item object (cart.items):
```liquid
{% for item in cart.items %}
{{ item.id }} {# Line item ID #}
{{ item.key }} {# Unique key #}
{{ item.product_id }} {# Product ID #}
{{ item.variant_id }} {# Variant ID #}
{# Product info #}
{{ item.product }} {# Product object #}
{{ item.variant }} {# Variant object #}
{{ item.title }} {# Product title #}
{{ item.product_title }} {# Same as title #}
{{ item.variant_title }} {# Variant options #}
{# Pricing #}
{{ item.quantity }} {# Quantity ordered #}
{{ item.price }} {# Price per unit (cents) #}
{{ item.line_price }} {# Total: price × quantity #}
{{ item.original_price }} {# Before discounts #}
{{ item.original_line_price }}
{{ item.final_price }} {# After discounts #}
{{ item.final_line_price }}
{# Images #}
{{ item.image }} {# Line item image #}
{{ item.featured_image.src }}
{# URL #}
{{ item.url }} {# Link to product #}
{# SKU #}
{{ item.sku }} {# Variant SKU #}
{# Properties (custom line item data) #}
{{ item.properties }} {# Hash of properties #}
{% for property in item.properties %}
{{ property.first }}: {{ property.last }}
{% endfor %}
{# Discounts #}
{{ item.discount_allocations }}
{% for discount in item.discount_allocations %}
{{ discount.amount }}
{{ discount.discount_application.title }}
{% endfor %}
{# Fulfillment #}
{{ item.requires_shipping }} {# Boolean #}
{{ item.taxable }} {# Boolean #}
{% endfor %}
```
### customer
Customer object (when logged in):
```liquid
{% if customer %}
{{ customer.id }} {# Numeric ID #}
{{ customer.email }} {# Email address #}
{{ customer.first_name }}
{{ customer.last_name }}
{{ customer.name }} {# Full name #}
{{ customer.phone }}
{# Account status #}
{{ customer.has_account }} {# Boolean: registered #}
{{ customer.accepts_marketing }} {# Email marketing opt-in #}
{{ customer.email_marketing_consent }}
{# Addresses #}
{{ customer.addresses }} {# Array of addresses #}
{{ customer.addresses_count }}
{{ customer.default_address }} {# Primary address #}
{% for address in customer.addresses %}
{{ address.first_name }}
{{ address.last_name }}
{{ address.address1 }}
{{ address.address2 }}
{{ address.city }}
{{ address.province }}
{{ address.province_code }} {# State/region code #}
{{ address.country }}
{{ address.country_code }} {# Country code: US, CA, etc. #}
{{ address.zip }}
{{ address.phone }}
{{ address.company }}
{% endfor %}
{# Orders #}
{{ customer.orders }} {# Array of orders #}
{{ customer.orders_count }} {# Total orders #}
{{ customer.total_spent }} {# Lifetime value (cents) #}
{# Tags #}
{{ customer.tags }} {# Array of customer tags #}
{# Metafields #}
{{ customer.metafields.namespace.key }}
{% endif %}
```
### order
Order object (order confirmation, customer account):
```liquid
{{ order.id }} {# Numeric ID #}
{{ order.name }} {# Order name: "#1001" #}
{{ order.order_number }} {# 1001 #}
{{ order.confirmation_number }} {# Unique confirmation #}
{{ order.email }} {# Customer email #}
{{ order.phone }} {# Customer phone #}
{{ order.customer_url }} {# Link to view order #}
{# Timestamps #}
{{ order.created_at }} {# Order date/time #}
{{ order.updated_at }}
{{ order.cancelled_at }} {# If cancelled #}
{{ order.processed_at }}
{# Customer #}
{{ order.customer }} {# Customer object #}
{{ order.customer.name }}
{# Items #}
{{ order.line_items }} {# Array of line items #}
{{ order.line_items_count }}
{% for item in order.line_items %}
{{ item.title }}
{{ item.quantity }}
{{ item.price }}
{{ item.line_price }}
{% endfor %}
{# Pricing #}
{{ order.subtotal_price }} {# Before tax/shipping #}
{{ order.total_price }} {# Grand total #}
{{ order.tax_price }} {# Total tax #}
{{ order.shipping_price }} {# Shipping cost #}
{{ order.total_discounts }} {# Discount amount #}
{# Status #}
{{ order.financial_status }} {# "paid", "pending", "refunded" #}
{{ order.fulfillment_status }} {# "fulfilled", "partial", null #}
{{ order.cancelled }} {# Boolean #}
{{ order.cancel_reason }}
{# Addresses #}
{{ order.shipping_address }}
{{ order.billing_address }}
{# Shipping #}
{{ order.shipping_method.title }} {# Shipping method name #}
{{ order.shipping_method.price }}
{# Discounts #}
{{ order.discount_applications }}
{% for discount in order.discount_applications %}
{{ discount.title }}
{{ discount.total_allocated_amount }}
{% endfor %}
{# Notes #}
{{ order.note }} {# Customer note #}
{{ order.attributes }} {# Custom attributes #}
{# Tags #}
{{ order.tags }}
```
### article
Article object (blog post pages):
```liquid
{{ article.id }} {# Numeric ID #}
{{ article.title }} {# Article headline #}
{{ article.handle }} {# URL slug #}
{{ article.content }} {# Full HTML content #}
{{ article.excerpt }} {# Summary/teaser #}
{{ article.excerpt_or_content }} {# Excerpt if set, else content #}
{# Author #}
{{ article.author }} {# Author name #}
{{ article.author_url }} {# Author profile URL #}
{# Dates #}
{{ article.published_at }} {# Publication date #}
{{ article.created_at }}
{{ article.updated_at }}
{# URL #}
{{ article.url }} {# Article URL #}
{# Image #}
{{ article.image }} {# Featured image #}
{{ article.image.src }}
{{ article.image | img_url: 'large' }}
{# Comments #}
{{ article.comments }} {# Array of comments #}
{{ article.comments_count }}
{{ article.comments_enabled }} {# Boolean #}
{{ article.moderated }} {# Comment moderation enabled #}
{# Tags #}
{{ article.tags }} {# Array of tags #}
{# Blog reference #}
{{ article.blog }} {# Parent blog object #}
{{ article.blog.title }}
{# Metafields #}
{{ article.metafields.namespace.key }}
```
### blog
Blog object (blog listing page):
```liquid
{{ blog.id }} {# Numeric ID #}
{{ blog.title }} {# Blog name #}
{{ blog.handle }} {# URL slug #}
{{ blog.url }} {# Blog URL #}
{# Articles #}
{{ blog.articles }} {# Array of articles #}
{{ blog.articles_count }} {# Total articles #}
{# Tags #}
{{ blog.all_tags }} {# All article tags #}
{# Metafields #}
{{ blog.metafields.namespace.key }}
```
### search
Search results object:
```liquid
{{ search.performed }} {# Boolean: search executed #}
{{ search.results }} {# Results array #}
{{ search.results_count }} {# Number of results #}
{{ search.terms }} {# Search query #}
{{ search.types }} {# Resource types found #}
{% for item in search.results %}
{% case item.object_type %}
{% when 'product' %}
{{ item.title }}
{{ item.price | money }}
{% when 'article' %}
{{ item.title }}
{{ item.excerpt }}
{% when 'page' %}
{{ item.title }}
{{ item.content | strip_html | truncatewords: 50 }}
{% endcase %}
{% endfor %}
```
## Metafields
Access custom data on any object:
```liquid
{# Product metafields #}
{{ product.metafields.namespace.key }}
{{ product.metafields.custom.warranty_info }}
{{ product.metafields.specifications.material }}
{# Collection metafields #}
{{ collection.metafields.seo.custom_title }}
{# Customer metafields #}
{{ customer.metafields.loyalty.points }}
{# Shop metafields #}
{{ shop.metafields.global.announcement }}
{# Check for existence #}
{% if product.metafields.custom.size_guide %}
{{ product.metafields.custom.size_guide }}
{% endif %}
{# Use default filter for safety #}
{{ product.metafields.custom.field | default: "Not specified" }}
```
## Metaobjects
Access metaobject definitions:
```liquid
{# Access metaobject by handle #}
{% assign testimonial = shop.metaobjects.testimonials['customer-review-1'] %}
{{ testimonial.name }}
{{ testimonial.rating }}
{{ testimonial.content }}
{# Loop through metaobjects #}
{% for testimonial in shop.metaobjects.testimonials.values %}
{{ testimonial.fields.author }}
{{ testimonial.fields.quote }}
{% endfor %}
```

View File

@@ -0,0 +1,551 @@
# Liquid Syntax - Complete Reference
## Tag Categories
### Control Flow Tags
#### if/elsif/else/endif
```liquid
{% if product.available %}
<button>Add to Cart</button>
{% elsif product.coming_soon %}
<p>Coming Soon</p>
{% else %}
<p>Sold Out</p>
{% endif %}
```
**Operators:**
- `==` - equals
- `!=` - not equals
- `>` - greater than
- `<` - less than
- `>=` - greater than or equal
- `<=` - less than or equal
- `contains` - substring or array contains
- `and` - logical AND
- `or` - logical OR
**Examples:**
```liquid
{% if product.price > 100 and product.available %}
Premium item in stock
{% endif %}
{% if product.tags contains 'sale' or product.type == 'clearance' %}
On sale!
{% endif %}
```
#### unless
Negated if statement:
```liquid
{% unless customer.name == blank %}
Hello, {{ customer.name }}
{% endunless %}
{# Equivalent to: #}
{% if customer.name != blank %}
Hello, {{ customer.name }}
{% endif %}
```
#### case/when
Switch-case statement:
```liquid
{% case product.type %}
{% when 'shoes' %}
<icon>👟</icon>
{% when 'boots' %}
<icon>👢</icon>
{% when 'sneakers' %}
<icon>👟</icon>
{% else %}
<icon>📦</icon>
{% endcase %}
```
### Iteration Tags
#### for loop
```liquid
{% for product in collection.products %}
{{ product.title }}
{% endfor %}
```
**Modifiers:**
```liquid
{# Limit to first 5 #}
{% for product in collection.products limit: 5 %}
{{ product.title }}
{% endfor %}
{# Skip first 10 #}
{% for product in collection.products offset: 10 %}
{{ product.title }}
{% endfor %}
{# Reverse order #}
{% for product in collection.products reversed %}
{{ product.title }}
{% endfor %}
{# Combine modifiers #}
{% for product in collection.products limit: 5 offset: 10 %}
{# Items 11-15 #}
{% endfor %}
```
**forloop object (available inside loops):**
```liquid
{% for item in array %}
{{ forloop.index }} {# 1-based: 1, 2, 3, ... #}
{{ forloop.index0 }} {# 0-based: 0, 1, 2, ... #}
{{ forloop.rindex }} {# Reverse 1-based: 3, 2, 1 #}
{{ forloop.rindex0 }} {# Reverse 0-based: 2, 1, 0 #}
{{ forloop.first }} {# true on first iteration #}
{{ forloop.last }} {# true on last iteration #}
{{ forloop.length }} {# Total number of items #}
{% endfor %}
```
**Example usage:**
```liquid
{% for product in collection.products %}
{% if forloop.first %}
<h2>Featured Product</h2>
{% endif %}
<div class="product-{{ forloop.index }}">
{{ product.title }}
</div>
{% if forloop.index == 3 %}
<hr> {# Divider after 3rd item #}
{% endif %}
{% if forloop.last %}
<p>Showing {{ forloop.length }} products</p>
{% endif %}
{% endfor %}
```
#### break and continue
```liquid
{% for product in collection.products %}
{% if product.handle == 'target' %}
{% break %} {# Exit loop entirely #}
{% endif %}
{% if product.available == false %}
{% continue %} {# Skip to next iteration #}
{% endif %}
{{ product.title }}
{% endfor %}
```
#### tablerow
Creates HTML table rows:
```liquid
{% tablerow product in collection.products cols: 3 %}
{{ product.title }}
{% endtablerow %}
{# Output: #}
<table>
<tr class="row1">
<td class="col1">Product 1</td>
<td class="col2">Product 2</td>
<td class="col3">Product 3</td>
</tr>
<tr class="row2">
<td class="col1">Product 4</td>
...
</tr>
</table>
```
**tablerow object:**
```liquid
{% tablerow product in products cols: 3 limit: 12 %}
{{ tablerow.col }} {# Current column (1-based) #}
{{ tablerow.col0 }} {# Current column (0-based) #}
{{ tablerow.row }} {# Current row (1-based) #}
{{ tablerow.index }} {# Item index (1-based) #}
{{ tablerow.first }} {# true on first item #}
{{ tablerow.last }} {# true on last item #}
{{ tablerow.col_first }} {# true on first column #}
{{ tablerow.col_last }} {# true on last column #}
{% endtablerow %}
```
#### paginate
For paginating large collections:
```liquid
{% paginate collection.products by 12 %}
{% for product in paginate.collection.products %}
{% render 'product-card', product: product %}
{% endfor %}
{# Pagination controls #}
{% if paginate.pages > 1 %}
{{ paginate | default_pagination }}
{% endif %}
{% endpaginate %}
```
**paginate object:**
```liquid
{{ paginate.current_page }} {# Current page number #}
{{ paginate.pages }} {# Total pages #}
{{ paginate.items }} {# Total items #}
{{ paginate.page_size }} {# Items per page #}
{{ paginate.previous.url }} {# Previous page URL (if exists) #}
{{ paginate.previous.title }} {# Previous page title #}
{{ paginate.previous.is_link }} {# Boolean #}
{{ paginate.next.url }} {# Next page URL (if exists) #}
{{ paginate.next.title }} {# Next page title #}
{{ paginate.next.is_link }} {# Boolean #}
{{ paginate.parts }} {# Array of page links #}
```
**Custom pagination:**
```liquid
{% paginate collection.products by 20 %}
<div class="pagination">
{% if paginate.previous %}
<a href="{{ paginate.previous.url }}">← Previous</a>
{% endif %}
{% for part in paginate.parts %}
{% if part.is_link %}
<a href="{{ part.url }}">{{ part.title }}</a>
{% else %}
<span class="current">{{ part.title }}</span>
{% endif %}
{% endfor %}
{% if paginate.next %}
<a href="{{ paginate.next.url }}">Next →</a>
{% endif %}
</div>
{% endpaginate %}
```
### Variable Assignment
#### assign
Single-line variable assignment:
```liquid
{% assign sale_price = product.price | times: 0.8 %}
{% assign is_available = product.available %}
{% assign product_count = collection.products.size %}
{% assign full_name = customer.first_name | append: ' ' | append: customer.last_name %}
```
#### capture
Multi-line content capture:
```liquid
{% capture product_title %}
{{ collection.title }} - {{ product.title }}
{% endcapture %}
{{ product_title }} {# "Summer Sale - Blue T-Shirt" #}
{% capture greeting %}
<h1>Welcome, {{ customer.name }}!</h1>
<p>You have {{ customer.orders_count }} orders.</p>
{% endcapture %}
{{ greeting }}
```
#### liquid (multi-statement)
Cleaner syntax for multiple statements:
```liquid
{% liquid
assign product_type = product.type
assign is_on_sale = product.on_sale
assign sale_percentage = product.discount_percent
if is_on_sale
assign status = 'SALE'
else
assign status = 'REGULAR'
endif
echo status
%}
```
### Template Inclusion
#### render
Isolated scope (preferred method):
```liquid
{# Basic usage #}
{% render 'product-card', product: product %}
{# Multiple parameters #}
{% render 'product-card',
product: product,
show_price: true,
show_vendor: false,
css_class: 'featured'
%}
{# Render for each item #}
{% render 'product-card' for collection.products as item %}
{# Pass arrays #}
{% render 'gallery', images: product.images %}
```
**Inside product-card.liquid:**
```liquid
{# Only has access to passed parameters #}
<div class="product {% if css_class %}{{ css_class }}{% endif %}">
<h3>{{ product.title }}</h3>
{% if show_price %}
<p>{{ product.price | money }}</p>
{% endif %}
{% if show_vendor %}
<p>{{ product.vendor }}</p>
{% endif %}
</div>
```
#### include
Shared scope (legacy, avoid in new code):
```liquid
{% include 'product-details' %}
{# Can access all parent template variables #}
{# Harder to debug and reason about #}
```
#### section
Load dynamic sections:
```liquid
{% section 'featured-product' %}
{% section 'newsletter-signup' %}
```
### Utility Tags
#### comment
Multi-line comments:
```liquid
{% comment %}
This entire block is ignored
by the Liquid renderer.
Use for documentation.
{% endcomment %}
{# Single-line comment #}
```
#### echo
Output shorthand (alternative to `{{ }}`):
```liquid
{% echo product.title %}
{# Equivalent to: {{ product.title }} #}
```
#### raw
Output Liquid code without processing:
```liquid
{% raw %}
{{ This will be output as-is }}
{% Liquid tags won't be processed %}
{% endraw %}
```
Useful for documentation or code examples.
## Whitespace Control
Strip whitespace using hyphens:
```liquid
{%- if condition -%}
Content (whitespace stripped on both sides)
{%- endif -%}
{{ "hello" -}}world
{# Output: helloworld (no space) #}
{{- product.title }}
{# Strips whitespace before output #}
{{ product.title -}}
{# Strips whitespace after output #}
```
**Example:**
```liquid
{# Without whitespace control: #}
{% for item in array %}
{{ item }}
{% endfor %}
{# Output has newlines and indentation #}
{# With whitespace control: #}
{%- for item in array -%}
{{ item }}
{%- endfor -%}
{# Output is compact #}
```
## Operator Precedence
**Order of evaluation (right-to-left):**
```liquid
{% if true or false and false %}
{# Evaluates as: true or (false and false) = true #}
{% endif %}
```
**IMPORTANT:** No parentheses support in Liquid. Break complex conditions into variables:
```liquid
{# ❌ DOESN'T WORK: #}
{% if (x > 5 and y < 10) or z == 0 %}
{# ✅ WORKS: #}
{% assign condition1 = false %}
{% if x > 5 and y < 10 %}
{% assign condition1 = true %}
{% endif %}
{% if condition1 or z == 0 %}
{# Logic here #}
{% endif %}
```
## Performance Tips
1. **Cache repeated calculations:**
```liquid
{# ❌ Inefficient: #}
{% for i in (1..10) %}
{{ collection.products.size }} {# Calculated 10 times #}
{% endfor %}
{# ✅ Efficient: #}
{% assign product_count = collection.products.size %}
{% for i in (1..10) %}
{{ product_count }}
{% endfor %}
```
2. **Use `limit` and `offset` instead of iterating full arrays:**
```liquid
{# ❌ Inefficient: #}
{% for product in collection.products %}
{% if forloop.index <= 5 %}
{{ product.title }}
{% endif %}
{% endfor %}
{# ✅ Efficient: #}
{% for product in collection.products limit: 5 %}
{{ product.title }}
{% endfor %}
```
3. **Prefer `render` over `include`** for better performance and variable scoping
4. **Use `liquid` tag** for cleaner multi-statement blocks
## Common Gotchas
1. **No parentheses in conditions** - Use variables instead
2. **Right-to-left evaluation** - Be careful with operator precedence
3. **String concatenation** - Use `append` filter or `capture` tag
4. **Array/object mutation** - Not possible; create new variables
5. **Integer division** - `{{ 5 | divided_by: 2 }}` returns `2`, not `2.5`
6. **Truthy/falsy values:**
- `false` and `nil` are falsy
- Everything else (including `0`, `""`, `[]`) is truthy
## Debugging Tips
1. **Output variable types:**
```liquid
{{ product | json }} {# Output entire object as JSON #}
{{ product.class }} {# Output object type #}
{{ variable.size }} {# Check array/string length #}
```
2. **Check for nil/existence:**
```liquid
{% if product.metafield %}
Metafield exists
{% else %}
Metafield is nil
{% endif %}
```
3. **Use default filter for safety:**
```liquid
{{ product.metafield.value | default: "Not set" }}
```
4. **Enable theme preview console** to see Liquid errors in real-time