This document outlines the coding standards and best practices to follow when developing for this Shopify theme.
Files should be organized in the following order for optimal performance and maintainability:
- Liquid variable assignments and logic (at the top)
- CSS/Styles (
<style>tags) - HTML markup (with Liquid templating)
- JavaScript (
<script>tags at the bottom)
{% comment %} Liquid variable assignments {% endcomment %}
{% assign product_title = product.title %}
{% assign show_feature = true %}
{% comment %} CSS/Styles at the top {% endcomment %}
<style>
.custom-class {
/* styles here */
}
</style>
{% comment %} HTML with Liquid {% endcomment %}
<div class="custom-class">
{{ product_title }}
</div>
{% comment %} JavaScript at the bottom {% endcomment %}
<script>
// JavaScript functionality here
</script>- Always use CSS for styling - Never use inline JavaScript for style changes (mouseover, mouseout, etc.)
- Use :hover pseudo-classes instead of JavaScript event listeners for hover effects
- Place all CSS at the top of the file after Liquid assignments
- Leverage existing theme classes before creating new ones
- Use CSS variables and theme colors consistently
- Place all JavaScript at the bottom of the file for better performance
- Use event delegation when possible to reduce event listeners
- Avoid inline onclick handlers when the functionality is complex
- Use semantic function names that describe what they do
- Account for header offsets when implementing scroll functionality
- Check for mobile app context when implementing app-specific features
- Assign variables at the top of the file for clarity
- Use descriptive variable names
- Comment complex logic to explain the purpose
- Minimize logic in templates - move complex logic to the top as variable assignments
- Use the {% liquid %} block tag for multi-line Liquid code for better readability and maintainability
- Use proper variable assignment syntax - ALWAYS initialize variables with default values first, then conditionally reassign them. Never use compound assignments or logical operators in variable declarations
IMPORTANT: Always initialize variables with default values first, then conditionally reassign:
Correct approach:
{% liquid
assign show_matching_lid = false
if container_tag and matching_lid_text != blank
assign show_matching_lid = true
endif
assign show_custom_branding = false
if custom_branding_text != blank and custom_branding_link != blank
assign show_custom_branding = true
endif
%}NEVER do this (will break the page):
{% liquid
# WRONG - This will cause Liquid syntax errors
assign show_matching_lid = container_tag and matching_lid_text != blank
assign show_custom_branding = custom_branding_text != blank and custom_branding_link != blank
%}For multiple Liquid statements, use the {% liquid %} block tag instead of multiple separate tags:
Preferred approach:
{% liquid
assign is_available = product.available
assign has_variants = product.variants.size > 1
assign show_button = false
if is_available and has_variants
assign show_button = true
endif
if show_button
assign button_text = 'Add to Cart'
else
assign button_text = 'Unavailable'
endif
%}Avoid this approach:
{% assign is_available = product.available %}
{% assign has_variants = product.variants.size > 1 %}
{% assign show_button = is_available and has_variants %}
{% if show_button %}
{% assign button_text = 'Add to Cart' %}
{% else %}
{% assign button_text = 'Unavailable' %}
{% endif %}The {% liquid %} tag provides cleaner code with less syntax overhead and improved performance. Reference: https://shopify.dev/docs/api/liquid/tags/liquid
- Minimize DOM queries - Cache selectors when used multiple times
- Use CSS transitions instead of JavaScript animations
- Lazy load images when appropriate
- Avoid unnecessary re-renders by batching DOM updates
- Always include proper ARIA labels for interactive elements
- Ensure keyboard navigation works for all interactive components
- Use semantic HTML elements (button, nav, main, etc.)
- Provide alternative text for images
- Use Liquid comments for Liquid-specific notes:
{% comment %} Note here {% endcomment %} - Use HTML comments sparingly in production code
- Document complex functionality with clear explanations
- Include TODO comments for future improvements
Before committing changes:
- Test on mobile and desktop viewports
- Verify JavaScript console has no errors
- Check that styles don't conflict with existing theme styles
- Ensure Liquid syntax is valid
- Test with different product types/variants
{% comment %} Shop metafields {% endcomment %}
{% assign plan_settings = shop.metafields.namespace.field_name %}
{% comment %} Product metafields {% endcomment %}
{% assign custom_data = product.metafields.custom.field_name %}
{% comment %} Safe access with default values {% endcomment %}
{% assign show_feature = false %}
{% if product.metafields.features.enabled %}
{% assign show_feature = true %}
{% endif %}IMPORTANT: When working with metaobject arrays/lists, use .count to get the size, NOT .size or .length.
{% comment %} Accessing metaobjects in templates {% endcomment %}
{% assign all_briefings = shop.metaobjects.sda_briefings.values %}
{% comment %} In metaobject templates, metaobject is automatically available {% endcomment %}
{{ metaobject.name.value }}
{{ metaobject.date.value }}
{% comment %} For metaobject reference lists, use .count for array size {% endcomment %}
{% if metaobject.presenters %}
{% assign presenters_count = metaobject.presenters.value.count %}
{% for presenter in metaobject.presenters.value %}
{{ presenter.name.value }}
{% endfor %}
{% endif %}
{% comment %} Accessing file fields {% endcomment %}
{% if metaobject.transcript %}
<a href="{{ metaobject.transcript.value }}" download>Download Transcript</a>
{% endif %}- Use kebab-case for file names:
product-form.liquid - Prefix component files with
component-:component-product-card.liquid - Use descriptive names that indicate the file's purpose
Last Updated: {{ "now" | date: "%Y-%m-%d" }}