Generate Shopify Liquid theme code (sections, blocks, snippets) with correct schema JSON, LiquidDoc headers, translation keys, and CSS/JS patterns. Use when creating or editing .liquid files for Shopify themes, working with schema, doc, stylesheet, javascript tags, or Shopify Liquid objects/filters/tags.
npx skills add https://github.com/Shopify/liquid-skills --skill shopify-liquid-themes
.
├── sections/ # Full-width page modules with {% schema %} — hero, product grid, testimonials
├── blocks/ # Nestable components with {% schema %} — slides, feature items, text blocks
├── snippets/ # Reusable fragments via {% render %} — buttons, icons, image helpers
├── layout/ # Page wrappers (must include {{ content_for_header }} and {{ content_for_layout }})
├── templates/ # JSON files defining which sections appear on each page type
├── config/ # Global theme settings (settings_schema.json, settings_data.json)
├── locales/ # Translation files (en.default.json, fr.json, etc.)
└── assets/ # Static CSS, JS, images (prefer {% stylesheet %}/{% javascript %} instead)
| Need | Use | Why |
|------|-----|-----|
| Full-width customizable module | Section | Has {% schema %}, appears in editor, renders blocks |
| Small nestable component with editor settings | Block | Has {% schema %}, can nest inside sections/blocks |
| Reusable logic, not editable by merchant | Snippet | No schema, rendered via {% render %}, takes params |
| Logic shared across blocks/snippets | Snippet | Blocks can't {% render %} other blocks |
{{ ... }} — Output (prints a value){{- ... -}} — Output with whitespace trimming{% ... %} — Logic tag (if, for, assign) — prints nothing{%- ... -%} — Logic tag with whitespace trimmingComparison: ==, !=, >, <, >=, <=
Logical: and, or, contains
{% if %} instead{% if cond %}value{% else %}other{% endif %}for loops max 50 iterations — use {% paginate %} for larger arrayscontains only works with strings — can't check objects in arrays{% stylesheet %}/{% javascript %} don't render Liquid — no Liquid inside theminclude is deprecated — always use {% render 'snippet_name' %}{% liquid %} tag — multi-line logic without delimiters; use echo for output{% assign my_var = 'value' %}
{% capture my_var %}computed {{ value }}{% endcapture %}
{% increment counter %}
{% decrement counter %}
Filters are chained with |. Output type of one filter feeds input of next.
Array: compact, concat, find, find_index, first, has, join, last, map, reject, reverse, size, sort, sort_natural, sum, uniq, where
String: append, capitalize, downcase, escape, handleize, lstrip, newline_to_br, prepend, remove, replace, rstrip, slice, split, strip, strip_html, truncate, truncatewords, upcase, url_decode, url_encode
Math: abs, at_least, at_most, ceil, divided_by, floor, minus, modulo, plus, round, times
Money: money, money_with_currency, money_without_currency, money_without_trailing_zeros
Color: color_brightness, color_darken, color_lighten, color_mix, color_modify, color_saturate, color_desaturate, color_to_hex, color_to_hsl, color_to_rgb
Media: image_url, image_tag, video_tag, external_video_tag, media_tag, model_viewer_tag
URL: asset_url, asset_img_url, file_url, shopify_asset_url
HTML: link_to, script_tag, stylesheet_tag, time_tag, placeholder_svg_tag
Localization: t (translate), format_address, currency_selector
Other: date, default, json, structured_data, font_face, font_url, payment_button
> Full details: language filters, HTML/media filters, commerce filters
| Category | Tags |
|----------|------|
| Theme | content_for, layout, section, sections, schema, stylesheet, javascript, style |
| Control | if, elsif, else, unless, case, when |
| Iteration | for, break, continue, cycle, tablerow, paginate |
| Variable | assign, capture, increment, decrement, echo |
| HTML | form, render, raw, comment, liquid |
| Documentation | doc |
> Full details with syntax and parameters: references/tags.md
cart, collections, customer, localization, pages, request, routes, settings, shop, template, theme, linklists, images, blogs, articles, all_products, metaobjects, canonical_url, content_for_header, content_for_layout, page_title, page_description, handle, current_page
| Template | Objects |
|----------|---------|
| /product | product, remote_product |
| /collection | collection, current_tags |
| /cart | cart |
| /article | article, blog |
| /blog | blog, current_tags |
| /page | page |
| /search | search |
| /customers/* | customer, order |
> Full reference: commerce objects, content objects, tier 2, tier 3
Sections and blocks require {% schema %} with a valid JSON object. Sections use section.settings.*, blocks use block.settings.*.
{
"name": "t:sections.hero.name",
"tag": "section",
"class": "hero-section",
"limit": 1,
"settings": [],
"max_blocks": 16,
"blocks": [{ "type": "@theme" }],
"presets": [{ "name": "t:sections.hero.name" }],
"enabled_on": { "templates": ["index"] },
"disabled_on": { "templates": ["password"] }
}
{
"name": "t:blocks.slide.name",
"tag": "div",
"class": "slide",
"settings": [],
"blocks": [{ "type": "@theme" }],
"presets": [{ "name": "t:blocks.slide.name" }]
}
| Need | Setting Type | Key Fields |
|------|-------------|------------|
| On/off toggle | checkbox | default: true/false |
| Short text | text | placeholder |
| Long text | textarea | placeholder |
| Rich text (with <p>) | richtext | — |
| Inline rich text (no <p>) | inline_richtext | — |
| Number input | number | placeholder |
| Slider | range | min, max, default (all required), step, unit |
| Dropdown/segmented | select | options: [{value, label}] |
| Radio buttons | radio | options: [{value, label}] |
| Text alignment | text_alignment | default: "left"/"center"/"right" |
| Color picker | color | default: "#000000" |
| Image upload | image_picker | — |
| Video upload | video | — |
| External video URL | video_url | accept: ["youtube", "vimeo"] |
| Product picker | product | — |
| Collection picker | collection | — |
| Page picker | page | — |
| Blog picker | blog | — |
| Article picker | article | — |
| URL entry | url | — |
| Menu picker | link_list | — |
| Font picker | font_picker | default (required) |
| Editor header | header | content (no id needed) |
| Editor description | paragraph | content (no id needed) |
visible_if pattern{
"visible_if": "{{ block.settings.layout == 'vertical' }}",
"type": "select",
"id": "alignment",
"label": "t:labels.alignment",
"options": [...]
}
Conditionally shows/hides a setting in the editor based on other setting values.
{ "type": "@theme" } — Accept any theme block{ "type": "@app" } — Accept app blocks{ "type": "slide" } — Accept only the slide block type> Full schema details and all 33 setting types: references/schema-and-settings.md
Use {% stylesheet %} and {% javascript %} in sections, blocks, and snippets:
{% stylesheet %}
.my-component { display: flex; }
{% endstylesheet %}
{% javascript %}
console.log('loaded');
{% endjavascript %}
{% stylesheet %} tags will errorsections/, blocks/, and snippets/{% style %} tag (Liquid-aware CSS)For dynamic CSS that needs Liquid (e.g., color settings that live-update in editor):
{% style %}
.section-{{ section.id }} {
background: {{ section.settings.bg_color }};
}
{% endstyle %}
Single CSS property — use CSS variables:
<div style="--gap: {{ block.settings.gap }}px">
Multiple CSS properties — use CSS classes as select values:
<div class="{{ block.settings.layout }}">
{% doc %})Required for: snippets (always), blocks (when statically rendered via {% content_for 'block' %})
{% doc %}
Brief description of what this file renders.
@param {type} name - Description of required parameter
@param {type} [name] - Description of optional parameter (brackets = optional)
@example
{% render 'snippet-name', name: value %}
{% enddoc %}
Param types: string, number, boolean, image, object, array
t filter<!-- Correct -->
<h2>{{ 'sections.hero.heading' | t }}</h2>
<button>{{ 'products.add_to_cart' | t }}</button>
<!-- Wrong — never hardcode strings -->
<h2>Welcome to our store</h2>
{{ 'products.price_range' | t: min: product.price_min | money, max: product.price_max | money }}
Locale file:
{
"products": {
"price_range": "From {{ min }} to {{ max }}"
}
}
locales/
├── en.default.json # English translations (required)
├── en.default.schema.json # Editor setting translations (required)
├── fr.json # French translations
└── fr.schema.json # French editor translations
t: prefix: "label": "t:labels.heading"sections.hero.heading, blocks.slide.titleToolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
Set up Tailwind CSS v4 in Expo with react-native-css and NativeWind v5 for universal styling
Use Expo DOM components to run web code in a webview on native and as-is on web. Migrate web code to native incrementally.
Take shopify/shopify-liquid-themes from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.