Why Your Shopify Theme Needs Theme Check in CI
Shopify Theme Check prevents Liquid errors before they hit production, yet most agencies skip it in CI. I'll show how to integrate it into GitHub Actions to block faulty PRs, saving countless emergencies.
Ashraful
Shopify Select Partner

I've shipped over 700 Shopify projects, and I've seen the same pattern repeat dozens of times: a seemingly minor Liquid change goes live, breaks a critical store function, and then it's a scramble to fix. This isn't just about bad code; it's about a lack of process. Specifically, it's about ignoring a foundational tool that Shopify themselves provides: Theme Check.
Most development agencies, even the "good" ones, don't run Shopify Theme Check in their Continuous Integration (CI) pipelines. This is a massive oversight. Theme Check catches Liquid, JSON, and CSS/JS syntax errors, performance anti-patterns, and even security vulnerabilities before your code ever reaches production. My argument is simple: if you're building Shopify themes, Theme Check needs to be a mandatory gate in your CI. It takes 10 minutes to set up and can save you from 10 client emergencies.
Why Shopify Theme Check in CI is Non-Negotiable
Theme Check is Shopify's official linter for Liquid, JSON, and other theme files. It's designed to catch common errors, enforce best practices, and identify potential performance bottlenecks. Think of it as ESLint or Prettier, but for your Shopify theme code.
I've been a Shopify Select Partner since 2021, and I've audited countless theme codebases. What I consistently find is that while developers might know about Theme Check, almost no one integrates it into their automated workflows. They might run it manually occasionally, or worse, not at all. This leaves a gaping hole in their quality assurance process.
Here's why relying on manual checks is a terrible idea:
- Human Error: Developers forget. They're busy. They're under pressure. Manual steps are skipped, leading to inconsistencies and missed issues.
- Inconsistency: What one developer checks, another might not. Coding standards erode over time without automated enforcement.
- Late Detection: Errors are found during manual QA, or worse, by the client or their customers in a live environment. This is expensive to fix, damages trust, and can lead to lost sales.
By embedding Shopify Theme Check directly into your CI pipeline, you automate this crucial step. Every Pull Request (PR) is automatically scanned, and if it fails the checks, it simply cannot merge. This isn't about being draconian; it's about building robust, reliable stores from the ground up. It ensures a baseline level of quality and consistency across your entire team's contributions, making code reviews faster and more focused on logic rather than syntax.
The Mistake Most Agencies Make: Trusting "Good Enough"
The mistake I see most often is agencies relying on visual QA alone, or basic syntax highlighting in their IDE. They push code, someone looks at it on a staging environment, and if it "looks fine," it goes to production. This approach is fundamentally flawed for Shopify theme development.
Liquid isn't like React or Vue where a compiler will throw a fit if you misspell a component or forget a closing tag. Liquid is interpreted at runtime. A simple typo like assign product = prooducts.first instead of products might not crash the page, but it will silently fail to assign the product, leading to incorrect data display, broken buy buttons, or missing content. These are the kinds of subtle, hard-to-debug issues that Theme Check excels at finding. It can pinpoint performance issues like excessive database queries or asset sizes, and even security risks such as unescaped output.
A Client War Story: The Missing Product Loop
I once took over a project for a client, a high-growth fashion brand, whose previous agency had delivered a custom theme. They were complaining about inconsistent product displays on collection pages. Sometimes, product images wouldn't load, or the "add to cart" button would be missing. It was intermittent and maddening for them.
When I pulled down the theme and ran Theme Check, it immediately flagged a dozen warnings and errors. One critical error was a Liquid loop structured incorrectly, causing it to sometimes iterate over an empty array if a specific product tag wasn't present, even though the intent was to show all products. The previous agency's manual QA had missed this because it only manifested under specific data conditions not always present in their staging environment. Setting up Theme Check in CI for them would have caught this in minutes, not months after launch. This experience solidified my belief that automated checks are paramount for reliable theme development, like the specialized theme development services I offer at ezomfy.com/services/theme-dev.
Setting Up Shopify Theme Check in GitHub Actions
Okay, enough theory. Let's get practical. I'll show you how to set up Theme Check as a GitHub Action. This will run every time you push code to a PR, and it will fail the PR if any critical Theme Check errors are found.
First, you need to have Theme Check installed. It's a Ruby gem, but the easiest way to use it in a CI context is often via npx if you have Node.js installed, as many front-end projects do. Shopify provides a CLI tool that wraps Theme Check, making it simple to integrate into an existing npm or yarn workflow.
Step 1: Install Shopify CLI (if not already present)
While you can install the Theme Check gem directly, using the Shopify CLI is generally more robust for CI environments as it handles dependencies and keeps everything updated. If you don't already have @shopify/cli installed as a dev dependency, add it to your package.json.
Your package.json might look something like this, with a script for Theme Check:
{
"name": "my-shopify-theme",
"version": "1.0.0",
"scripts": {
"theme:check": "shopify theme check",
"theme:dev": "shopify theme dev",
"theme:push": "shopify theme push"
},
"devDependencies": {
"@shopify/cli": "^3.0.0"
}
}
After adding the dev dependency, run npm install. Then, you can run npm run theme:check locally to test it out.
Step 2: Configure Theme Check Rules (Optional but Recommended)
By default, Theme Check uses a sensible set of rules. However, you might want to customize them. You can create a .theme-check.yml file in the root of your theme directory. This allows you to disable certain checks that might not apply to your workflow, or elevate the severity of others.
Here’s an example .theme-check.yml that disables a few checks I often find too strict for client projects and makes a critical HTML parsing error fail a build:
# .theme-check.yml
# See https://shopify.dev/docs/themes/tools/theme-check/configuration
root: "./"
ignore:
- "node_modules/**"
- "assets/*.js"
- "assets/*.css"
- "sections/*.liquid" # Example: ignore a specific file if needed
# Adjust check severities or disable them
check_configs:
HtmlParsingError:
severity: error # Make sure HTML parsing errors are always errors
MissingTemplate:
severity: error
DeprecatedFilter:
severity: warning # Log deprecated filters as warnings, not errors
MatchingTranslations:
enabled: false # Disable this check if you're not using translation keys consistently
RequiredLayoutThemeFile:
enabled: false # If you have a custom layout strategy that doesn't use theme.liquid
TranslationKeyExists:
severity: warning # We want to know, but not fail PRs immediately
This file gives you fine-grained control. I prefer to make HtmlParsingError an error because broken HTML is almost always a bug. I might set MatchingTranslations to false on some projects where translation consistency isn't the highest priority during initial development. Tailor this to your project's needs and your team's coding standards.
Step 3: Create the GitHub Actions Workflow
Now, let's create the actual CI workflow. In your theme repository, create a file at .github/workflows/theme-check.yml. This file defines the steps GitHub Actions will take to run Theme Check.
name: Shopify Theme Check
on:
pull_request:
branches:
- main
- master
push:
branches:
- main
- master
jobs:
theme_check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18' # Or your preferred Node.js version
- name: Install dependencies
run: npm install
- name: Run Shopify Theme Check
run: npm run theme:check -- --fail-on=error # Fails the action if any errors are found
Let's break down this GitHub Actions file:
name: Shopify Theme Check: A human-readable name for your workflow, which will appear in GitHub's checks UI.on: pull_requestandon: push: This workflow will trigger on everypull_requestagainstmainormasterbranches, and also onpushto those branches. I recommendpull_requestas the primary trigger so errors are caught before merging.jobs: theme_check: Defines a single job within the workflow. You could have multiple jobs if you had other CI steps.runs-on: ubuntu-latest: The job will run on a fresh Ubuntu virtual machine provided by GitHub Actions.steps:actions/checkout@v4: This action checks out your repository code into the runner's environment.actions/setup-node@v4: This sets up Node.js, which is needed fornpm installand the Shopify CLI. Choose a Node.js version compatible with your project.npm install: Installs yourdevDependencies, including@shopify/cli, from yourpackage.json.npm run theme:check -- --fail-on=error: This is the crucial step. It executes thetheme:checkscript we defined inpackage.json. The-- --fail-on=errorargument tells Theme Check to exit with a non-zero status code (which fails the GitHub Action) if any errors are detected. You could change this to--fail-on=warningif you want to be even stricter, but I typically start witherrorto block critical issues without being overly prescriptive on minor warnings.
Making Theme Check a PR Blocker
Running the workflow is one thing; making it a required check is another. This is where you actually block merges, ensuring no code with detected errors makes it into your main branch.
In your GitHub repository settings:
- Go to
Settings->Branches. - Select the branch you want to protect (e.g.,
mainormaster). - Click
Add rule. - Under
Require status checks to pass before merging, search for "Shopify Theme Check" (or whatever you named your workflow). - Check the box next to it. This links your workflow's success to the PR's mergeability.
- Ensure
Require branches to be up to date before mergingis also checked (good practice for avoiding merge conflicts). - Save changes.
Now, any Pull Request targeting your protected branch will require the "Shopify Theme Check" workflow to pass before it can be merged. If Theme Check finds an error, the PR will show a red X, and the merge button will be disabled. Your developers will be forced to fix the Liquid before shipping it. This automated gate ensures that a baseline quality is met with every single code change.
This process takes maybe 10 minutes to set up, and it immediately elevates your team's code quality and reduces the risk of production outages due to theme errors. It's a small investment for a massive payoff in stability, developer sanity, and ultimately, client satisfaction.
Beyond Basic Checks: Custom Rules and Best Practices
While Theme Check's built-in rules are excellent, for larger agencies or very specific project requirements, you might want to extend its capabilities with custom checks. This is where you can define rules specific to your internal coding standards or unique Liquid patterns that are critical for your projects.
For instance, if your agency always uses a specific naming convention for sections or snippets, you can create a custom check to enforce it. Or, if you have a strict policy against using certain global objects directly in Liquid to maintain performance or prevent data exposure, you can write a check for that. This level of customization ensures that your themes not only meet Shopify's general standards but also your own bespoke requirements, making your codebase uniquely robust.
I've worked with numerous clients to develop custom Theme Check configurations that align with their long-term maintenance goals and internal development guidelines. It's a key part of building sustainable and high-performing Shopify stores, and something I often help clients with through my Shopify theme development services.
How Custom Checks Work
Custom checks are typically written in Ruby and live within your theme's directory, often in a lib/theme_check folder. You then reference them in your .theme-check.yml to ensure they are run alongside Shopify's default checks.
For example, a simple custom check might look for specific comments (e.g., a required copyright header) or ensure all {% schema %} tags have a name property, which is crucial for theme editor usability.
# lib/theme_check/checks/my_custom_check.rb
module ThemeCheck
class MyCustomCheck < Check
def initialize(config)
super
@offenses = []
end
def on_schema(node)
# Ensure all schema tags have a 'name' property
if node.schema["name"].nil? || node.schema["name"].empty?
add_offense("All schema tags must have a 'name' property for editor visibility.", node)
end
end
def offenses
@offenses
end
private
def add_offense(message, node)
@offenses << Offense.new(
check: self,
message: message,
template: node.template,
line_number: node.start_line_number,
markup: node.markup,
severity: :error
)
end
end
end
Then, in your .theme-check.yml, you'd include your custom check:
# .theme-check.yml
root: "./"
require:
- "./lib/theme_check" # Path to your custom checks folder
check_configs:
MyCustomCheck:
enabled: true
severity: error
This ensures that your team adheres to specialized requirements, making your codebase more consistent and easier to maintain in the long run. It's a powerful way to codify your team's institutional knowledge and prevent common project-specific errors.
This isn't about adding unnecessary overhead. It's about building a robust development process that catches problems early, saves time, and prevents client headaches. If you're serious about delivering high-quality Shopify themes, Theme Check in CI isn't optional; it's fundamental.
If you're struggling with consistent theme quality, or if you're an agency looking to implement more robust CI/CD practices for your Shopify projects, I offer free 30-minute consultation calls. We can discuss your specific challenges and explore how you can streamline your development workflow to avoid preventable errors. Book a call at ezomfy.com/consultation.
About the author
Ashraful
Shopify Select Partner, Top Rated Plus on Upwork. 700+ Shopify projects shipped over 7+ years — themes, apps, migrations, speed, Hydrogen. Solo shop, no agency middlemen.
Read the full storyWorking on a Shopify project?
That's what I do every day. Pick whichever feels lower-friction.
More from the blog
Keep reading

Metaobjects vs. Metafields in Shopify: The Decision Tree I Use to Avoid Costly Refactoring
Confused about Shopify Metafields vs. Metaobjects? I'll show you my practical decision tree, with real-world examples, to pick the right tool for structured data and save yourself costly refactoring later.
Read
Shopify Section vs. Block: Master When and How to Use Them (with Code)
Shopify developers and merchants often misuse sections for everything. I'll show you why blocks are crucial for repeating content and how getting this wrong leads to unmaintainable themes in months.
Read
Your Shopify Store Has a Third-Party Script Budget — And You're Over It
Your Shopify store has a finite budget for third-party scripts. Most stores blow past it, adding unnecessary bloat that slows down the site and costs you sales. It's time to audit and cut.
Read