Deployment & Production Workflow

Building a great theme means nothing if you can't deploy it safely. This chapter covers the complete deployment pipeline — from testing and debugging to Git workflows, safe deployment strategies, and preparing themes for production.

📌 Chapter Overview

Time estimate: 45 – 60 minutes
Tags: CLI Workflow

Pre-Deployment Testing Checklist

Before pushing any theme to production, run through this comprehensive checklist. Professional developers never deploy without testing:

Pre-Deployment Checklist
PRE-DEPLOYMENT TESTING CHECKLIST
═══════════════════════════════════════════

PAGES TO TEST
□ Homepage (with all sections populated)
□ Collection page (with products)
□ Collection page (empty collection)
□ Product page (with variants)
□ Product page (single variant)
□ Product page (sold out)
□ Product page (on sale)
□ Cart page (with items)
□ Cart page (empty)
□ Search page (with results)
□ Search page (no results)
□ Blog page
□ Article page
□ Custom page (e.g., About Us)
□ Contact page
□ 404 error page
□ Password page
□ Gift card page
□ Customer login page
□ Customer account page

FUNCTIONALITY
□ Add to cart works (all product types)
□ Cart updates quantity correctly
□ Cart removes items
□ Navigation links all work (no broken links)
□ Search returns relevant results
□ Predictive search works (if implemented)
□ Mobile menu opens and closes
□ All forms submit correctly
□ Variant selector updates price and image
□ Newsletter signup submits
□ Social media links open in new tabs

RESPONSIVE DESIGN
□ Test at 320px (smallest phone)
□ Test at 375px (standard phone)
□ Test at 768px (tablet portrait)
□ Test at 1024px (tablet landscape)
□ Test at 1440px (desktop)
□ No horizontal scrollbar at any width
□ All text is readable (no overflow)
□ Buttons/links are tappable (44px min)
□ Images don't overflow containers

BROWSER TESTING
□ Chrome (latest)
□ Firefox (latest)
□ Safari (latest — test on Mac/iPhone if possible)
□ Edge (latest)
□ Mobile Safari (iOS)
□ Mobile Chrome (Android)

PERFORMANCE
□ Lighthouse score above 50 (ideally 70+)
□ No render-blocking resources
□ Images optimized with srcset
□ Lazy loading implemented
□ No console errors

ACCESSIBILITY
□ Skip-to-content link works
□ All images have alt text
□ Color contrast meets WCAG AA
□ Keyboard navigation works (Tab through page)
□ Focus states are visible
□ Form labels are properly associated
□ ARIA labels on interactive elements

SEO
□ Page titles are unique and descriptive
□ Meta descriptions present
□ Canonical URLs are correct
□ Open Graph tags present
□ Structured data (if implemented)
□ No broken links

Debugging Shopify Themes

Debugging Liquid Errors

When Liquid has errors, the Shopify CLI terminal shows them. Common patterns:

Common Liquid Errors and Fixes
ERROR: "Liquid error: Unknown tag 'endfor'"
FIX:   Check for typos — ensure {% endfor %} matches {% for %}
       Check nesting — every if/for/case needs a closing tag

ERROR: "Liquid error: undefined variable"  
FIX:   Variable doesn't exist in current scope.
       If using {% render %}, pass the variable explicitly.
       Check for typos in variable names.

ERROR: "Liquid error: Array index out of bounds"
FIX:   Check array .size before accessing by index.
       Use {% if array.size > 0 %} before looping.

ERROR: "Liquid error: wrong number of arguments"
FIX:   Check filter syntax. Common mistake:
       ❌ {{ image | image_url: 400 }}
       ✅ {{ image | image_url: width: 400 }}

ERROR: Page renders but section is blank
FIX:   1. Check {% if %} conditions — something is probably blank/nil
       2. Output debug: {{ section.settings | json }}
       3. Check schema — setting IDs must match Liquid references
       4. Check template JSON — is the section referenced?

Browser DevTools Debugging

Issue DevTools Tool How to Use
CSS not applying Elements panel → Styles Inspect the element. Check if your CSS is loaded. Look for overriding rules (crossed out).
Layout broken Elements panel → Layout Enable Grid/Flexbox overlays to visualize layout structure.
JavaScript errors Console tab Look for red errors. Click the file:line link to see the source.
Network issues Network tab Check for 404s (missing files), slow resources, large downloads.
Performance issues Lighthouse tab Run Performance audit. Read opportunities and diagnostics.
Mobile rendering Device toolbar (Ctrl+Shift+M) Toggle device mode. Select specific devices or set custom dimensions.
Accessibility issues Lighthouse → Accessibility Run Accessibility audit. Also use Elements → Accessibility panel for individual elements.

Theme Editor Debugging

Theme Editor Debugging Tips
PROBLEM: Section doesn't appear in "Add section" menu
CHECK:  Does your schema have a "presets" array?
        Without presets, the section can't be added manually.

PROBLEM: Settings don't appear in theme editor sidebar
CHECK:  Is the setting inside the "settings" array in schema?
        Is the JSON valid? (missing comma, bracket, quote)
        Validate JSON at jsonlint.com

PROBLEM: Blocks can't be clicked in the editor preview
CHECK:  Is {{ block.shopify_attributes }} on the block wrapper?
        This is REQUIRED for editor interactivity.

PROBLEM: Section shows in editor but not on live site
CHECK:  Is the section in the JSON template's "order" array?
        Is there a conditional that hides it?

PROBLEM: Schema changes not reflecting
FIX:    Save the section file, refresh the theme editor.
        Sometimes you need to close and reopen the editor.
        Clear browser cache if needed.

Deployment Strategies

Strategy 1: Push to Unpublished Theme (Safest)

This is the recommended approach for client stores. Push your changes to a new unpublished theme, let the client preview and approve it, then publish.

Safe Deployment — Unpublished Theme
# Step 1: Push to a new unpublished theme
shopify theme push --unpublished \
  --store client-store.myshopify.com

# This creates a new theme named "[development] Your Theme"
# It does NOT affect the live store

# Step 2: Share preview link with client
# The CLI will output a preview URL like:
# https://client-store.myshopify.com/?preview_theme_id=XXXXXXX

# Step 3: After client approves, publish via Shopify Admin
# Online Store → Themes → Actions → Publish

# Or publish via CLI (use with caution):
shopify theme publish --theme THEME_ID \
  --store client-store.myshopify.com

Strategy 2: Push to Existing Theme

Use this when updating an existing unpublished theme during development:

Push to Specific Theme
# List existing themes to find the ID
shopify theme list --store client-store.myshopify.com

# Output:
# ID           NAME                  ROLE
# 123456789    Dawn (Live)           live
# 987654321    My Custom Theme       unpublished

# Push to the specific unpublished theme
shopify theme push --theme 987654321 \
  --store client-store.myshopify.com

Strategy 3: Push to Live Theme (Risky)

🚨 Pushing to Live — Use Extreme Caution

Pushing directly to the live theme affects the store immediately. Customers will see changes in real-time. Only do this for small, well-tested changes — never for major updates.

Push to Live (Only When Necessary)
# This pushes directly to the live published theme
# WARNING: Changes are immediately visible to customers
shopify theme push --allow-live \
  --store client-store.myshopify.com

# SAFER: Push specific files only
shopify theme push --allow-live \
  --only sections/header.liquid \
  --only assets/section-header.css \
  --store client-store.myshopify.com

Ignoring Files During Push

Protecting Merchant Settings
# Never overwrite the merchant's customized settings
shopify theme push \
  --ignore config/settings_data.json \
  --store client-store.myshopify.com

# You can also create a .shopifyignore file
# in your project root:

# .shopifyignore
config/settings_data.json
templates/*.json
✅ The .shopifyignore File

Create a .shopifyignore file in your project root. It works like .gitignore but for Shopify CLI. Any files listed here won't be pushed or pulled. This protects merchant settings and template configurations from being overwritten.

.shopifyignore
# Don't overwrite merchant's theme settings
config/settings_data.json

# Don't overwrite template configurations
# (merchant may have added/reordered sections)
templates/*.json

# Keep the default templates in your repo
# but don't push them over merchant customizations
!templates/product.json
!templates/collection.json

Git Workflow for Production

Professional Branching Model

Branching Strategy
RECOMMENDED BRANCHING MODEL
═══════════════════════════════════════════

main (or production)
  │
  ├── The stable, production-ready code
  ├── Only merged from staging or hotfix branches
  ├── Tagged with version numbers (v1.0.0, v1.1.0)
  │
  └── staging (or develop)
        │
        ├── Integration branch for testing
        ├── Features merge here first
        ├── Pushed to unpublished theme for review
        │
        ├── feature/hero-redesign
        │     └── New feature development
        │
        ├── feature/mega-menu
        │     └── Another feature in parallel
        │
        └── fix/mobile-nav-bug
              └── Bug fix branch


SIMPLIFIED MODEL (for solo developers):

main
  │
  ├── Stable theme code
  │
  ├── feature/new-section
  │     └── Develop → Test → Merge to main
  │
  └── fix/cart-bug
        └── Fix → Test → Merge to main

Complete Git Deployment Workflow

Full Deployment Workflow
# ── DEVELOPMENT PHASE ──────────────────────────

# 1. Create a feature branch
git checkout main
git pull origin main
git checkout -b feature/announcement-bar

# 2. Develop with live preview
shopify theme dev --store dev-store.myshopify.com

# 3. Make changes, test, commit regularly
git add sections/announcement-bar.liquid
git add assets/section-announcement-bar.css
git commit -m "feat: add announcement bar section with auto-rotate"

git add sections/announcement-bar.liquid
git commit -m "fix: announcement bar dismiss uses sessionStorage"

# 4. Push branch to GitHub
git push -u origin feature/announcement-bar


# ── REVIEW PHASE ──────────────────────────────

# 5. Merge to main when feature is complete
git checkout main
git merge feature/announcement-bar
git push origin main

# 6. Clean up feature branch
git branch -d feature/announcement-bar
git push origin --delete feature/announcement-bar


# ── DEPLOYMENT PHASE ──────────────────────────

# 7. Push to unpublished theme on client store
shopify theme push --unpublished \
  --ignore config/settings_data.json \
  --store client-store.myshopify.com

# 8. Share preview link with client for approval

# 9. After approval, publish the theme
# (via Shopify Admin or CLI)

# 10. Tag the release in Git
git tag -a v1.2.0 -m "Add announcement bar section"
git push origin v1.2.0

Version Tagging

Use semantic versioning to tag releases:

Version When to Bump Example
Major (X.0.0) Complete theme redesign, breaking changes v1.0.0 → v2.0.0
Minor (0.X.0) New sections, new features, non-breaking v1.0.0 → v1.1.0
Patch (0.0.X) Bug fixes, small adjustments v1.1.0 → v1.1.1
Git Tagging Commands
# Create an annotated tag
git tag -a v1.0.0 -m "Initial theme release"

# Push tags to GitHub
git push origin v1.0.0

# Push all tags
git push origin --tags

# List all tags
git tag -l

# View tag details
git show v1.0.0

Syncing Theme Editor Changes

One of the trickiest aspects of Shopify development: merchants make changes through the theme editor, which modifies config/settings_data.json and template JSON files. You need to sync these changes with your local codebase.

1

Commit Your Local Changes First

WSL Terminal
git add .
git commit -m "feat: my latest local changes"
2

Pull Theme Editor Changes

WSL Terminal
# Pull only settings and templates (what the editor changes)
shopify theme pull \
  --only config/settings_data.json \
  --only "templates/*.json" \
  --store client-store.myshopify.com
3

Review and Commit

WSL Terminal
# Review what changed
git diff

# Commit the editor changes
git add config/settings_data.json templates/
git commit -m "sync: pull theme editor changes from client"
⚠️ Coordinate With Clients

Establish a rule with clients: "Don't make theme editor changes while I'm actively developing." Simultaneous local development and theme editor changes create conflicts. Set specific times for development work and merchant customization to avoid this.

Backup Strategies

Theme Backup Workflow
# Before ANY major deployment, create a backup:

# Option 1: Download the live theme as a backup
shopify theme pull \
  --theme LIVE_THEME_ID \
  --path ./backups/backup-$(date +%Y%m%d) \
  --store client-store.myshopify.com

# Option 2: Duplicate the live theme in Shopify Admin
# Online Store → Themes → Actions → Duplicate
# This creates a copy the merchant can revert to

# Option 3: Git tags serve as backups
git tag -a backup/pre-v2-launch -m "Backup before v2 launch"
git push origin backup/pre-v2-launch
🚨 Always Backup Before Major Deploys

Before publishing a new theme version on a live store, always duplicate the current live theme in Shopify Admin. If anything goes wrong, the merchant can instantly revert by publishing the duplicate. This takes 10 seconds and can save hours of crisis management.

Rollback Procedures

When something goes wrong in production, you need to act fast:

Instant Rollback via Shopify Admin

1

Go to Online Store → Themes

Find the backup/duplicate theme you created before deployment.

2

Click Actions → Publish

This instantly makes the old theme live again. The new theme becomes unpublished.

3

Debug the New Theme

Fix the issues on the now-unpublished new theme. Test thoroughly. Then publish again.

Rollback via Git

Git Rollback Options
# Option 1: Revert a specific commit
git revert HEAD    # Reverts the last commit
git push

# Option 2: Reset to a specific tag
git checkout v1.1.0    # Go to a tagged version
shopify theme push --unpublished \
  --store client-store.myshopify.com

# Option 3: Reset branch to a previous state (destructive!)
git reset --hard v1.1.0
git push --force     # CAUTION: rewrites remote history

Production Readiness Checklist

Production Readiness Checklist
PRODUCTION READINESS
═══════════════════════════════════════════

CODE QUALITY
□ All debug output removed ({{ product | json }}, HTML comments)
□ No console.log() statements in JavaScript
□ No TODO or FIXME comments left unresolved
□ Code is consistently formatted
□ Snippets are documented with accepted parameters
□ Schema settings have helpful labels, info text, and defaults
□ Translation keys used for all user-facing strings

THEME SETTINGS
□ settings_schema.json has theme_info block (name, version, author)
□ All global settings have sensible defaults
□ Color settings provide good default palette
□ Typography defaults are readable and professional

CONTENT
□ All sections render placeholder content when no data is set
□ Empty states are handled gracefully (empty cart, no results, etc.)
□ All images have meaningful alt text
□ Locales file has all required translation keys

LEGAL
□ No copyrighted code from premium themes
□ No copyrighted images or fonts
□ License information is clear (if distributing)
□ Privacy-related features comply with GDPR (cookie consent, etc.)

DEPLOYMENT
□ .shopifyignore is configured
□ .gitignore is configured
□ Git repository is clean (no uncommitted changes)
□ Live theme is backed up (duplicated in Shopify Admin)
□ Client has been notified of deployment timing
□ Post-deployment verification plan is ready

Post-Deployment Verification

After deploying, perform a quick verification:

Post-Deployment Checks (5 minutes)
IMMEDIATELY AFTER PUBLISHING
═══════════════════════════════════════════

□ Visit the homepage — does it load correctly?
□ Visit a product page — can you add to cart?
□ Visit a collection page — do products display?
□ Test on mobile (real phone, not just DevTools)
□ Complete a test checkout (on dev store) or verify
  checkout loads correctly (on live store)
□ Check browser console for JavaScript errors
□ Run a quick Lighthouse audit
□ Verify header and footer render correctly
□ Check that merchant's custom content is intact
□ Notify the client that deployment is complete

Automated Deployment Concepts

As you grow, consider automating deployments with GitHub Actions. Here's a basic concept:

.github/workflows/deploy-theme.yml (concept)
# This is a conceptual example — adapt to your needs
name: Deploy Shopify Theme

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Shopify CLI
        run: npm install -g @shopify/cli @shopify/theme

      - name: Deploy to Shopify
        env:
          SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }}
          SHOPIFY_FLAG_STORE: ${{ secrets.SHOPIFY_STORE }}
        run: |
          shopify theme push \
            --theme ${{ secrets.THEME_ID }} \
            --ignore config/settings_data.json
💡 Start Manual, Automate Later

CI/CD is powerful but adds complexity. As a beginner, focus on mastering the manual deployment workflow first. Once you're confident and handling multiple client stores, then set up automation. Premature automation creates more problems than it solves.

Key Takeaways

  • Always run the pre-deployment testing checklist before pushing to production
  • Use --unpublished flag for safe deployments to client stores
  • Protect merchant settings with .shopifyignore and --ignore flags
  • Never push directly to live themes without a backup
  • Duplicate the live theme in Shopify Admin before every major deployment
  • Use Git tags for version tracking and easy rollbacks
  • Coordinate with clients to avoid simultaneous theme editor and code changes
  • Sync theme editor changes with shopify theme pull --only
  • Perform post-deployment verification immediately after publishing
  • Master manual deployment before setting up CI/CD automation