In modern theme development, the quality of your code is not just measured by its output, but by its clarity and maintainability. As themes become more complex and team collaboration more common, clear documentation is no longer a luxury—it’s a necessity.
Furthermore, with the rise of AI-assisted development, the context we provide in our code directly impacts the quality of the suggestions we receive.
This is where LiquidDoc, a native Shopify feature, becomes an essential tool in the professional developer’s toolkit. It’s a simple, structured way to document your reusable components, making your code easier for both humans and AI to understand.
What is LiquidDoc?
LiquidDoc is Shopify’s standardized format for documenting Liquid snippet and block files. It uses a JSDoc-inspired syntax inside a {% doc %} tag to define what a component does, what parameters it accepts, and how to use it. These details power theme checks, code completions, and hover information in your editor.
Crucially, LiquidDoc is for snippets and blocks only. It is not supported in sections, where documentation and settings are handled by the {% schema %} tag.
A well-documented snippet using LiquidDoc looks like this:
{% doc %}
Renders a single product card for use in grids or carousels.
@param {product} product - The product object to render
@param {string} [image_size] - Optional image size, defaults to 'medium'
@example
{% render 'product-card', product: my_product, image_size: 'large' %}
{% enddoc %}
<div class="product-card">
<img src="{{ product.featured_image | image_url: width: 400 }}" alt="{{ product.featured_image.alt }}">
<h3>{{ product.title }}</h3>
</div>
LiquidDoc @param Valid Types
The most common question about LiquidDoc: what are the valid types for @param? Shopify’s ValidDocParamTypes theme check accepts exactly these:
| Type | Description |
|---|---|
string | Text values |
number | Numeric values |
boolean | True/false values (everything in Liquid is truthy or falsy) |
object | Complex Liquid types, or anything that isn’t a primitive |
| Any Liquid object | e.g. product, collection, image, color, currency — as long as it isn’t exclusively a global object |
| Typed arrays | Append [] to any valid type: string[], product[] |
Rules worth knowing:
- Types are optional.
@param some_untypedis valid — the type in curly braces can be omitted. - Optional parameters are marked by wrapping the name in square brackets:
@param {string} [subtitle]. - Multidimensional arrays are invalid.
{string[][]}fails the theme check. - Made-up types fail.
{custom}or{fake}will be flagged byValidDocParamTypes.
{% doc %}
@param {string} some_str
@param {number} some_num
@param {boolean} some_bool
@param {object} some_obj
@param {product} special_product
@param {product[]} special_products
@param {string} [optional_str]
@param some_untyped
{% enddoc %}
All of the above pass validation. @param {custom} param1 and @param {string[][]} matrix do not.
Why LiquidDoc is a Game-Changer
Implementing LiquidDoc might seem like extra work, but the long-term benefits are massive.
1. Improved Maintainability and Collaboration
When you or another developer revisits a component months later, the LiquidDoc block provides immediate context. There’s no need to reverse-engineer the code to understand its purpose or what parameters it expects. This dramatically speeds up maintenance and reduces the risk of introducing bugs.
2. Supercharging AI and Agentic Development
This is perhaps the most modern and compelling reason to adopt LiquidDoc. AI coding assistants and tools that use Figma’s MCP rely on context to provide accurate suggestions.
As noted by Shopify expert Vitalii Ponomarov, “Most AI-assisted coding fails on Shopify projects because the model doesn’t have the right context about Liquid, the API schema, or object patterns.”
LiquidDoc provides that explicit context. When an AI agent sees a LiquidDoc block, it understands:
- The component’s purpose.
- The required and optional parameters.
- The data types of those parameters.
- A clear example of how to use the component correctly.
This allows the AI to generate more accurate code, validate your implementations, and catch errors before you do.
3. Enforcing Best Practices
The act of writing LiquidDoc forces you to think more clearly about the components you’re building. It encourages you to design a clean, explicit API for your snippets and blocks, leading to a more modular and well-architected theme.
How to Implement LiquidDoc: The Core Tags
Implementing LiquidDoc is simple. Place a {% doc %} block at the top of your snippet or block file. Three tags are supported:
@description: A brief explanation of what the component does. You can also just write the description as plain text before any@annotation and omit the tag.@param {type} name - description: Defines a parameter.{type}: Optional data type in curly braces — one of the valid types listed above (e.g.,{string},{number},{product}).name: The parameter name. Wrap it in square brackets for optional parameters (e.g.,[image_size]).- description: A clear explanation of the parameter.
@example: A code block showing how to render the component. Multiple@exampletags are allowed.
LiquidDoc also integrates with Theme Check: ValidDocParamTypes validates your types, UniqueDocParamNames catches duplicate names, UnusedDocParam flags documented-but-unused parameters, and render/content_for usage checks make sure callers pass what you declared.
Final Thoughts: A Mark of Professionalism
In the evolving landscape of Shopify development, writing self-documenting code is a mark of professionalism. LiquidDoc is a simple, powerful, and officially supported way to achieve this.
It elevates your code from a set of instructions into a well-documented, reusable asset that is easier for your team, your future self, and your AI coding partners to understand and build upon.
❓ Have you integrated LiquidDoc into your workflow? What has been the biggest benefit?