Skip to content

How to Build a Custom Shopify Theme: Step-by-Step Guide (2026)

A practical 2026 guide to building a custom Shopify theme: set up Shopify CLI, start from Skeleton, build JSON templates, sections and theme blocks, then test and publish. Every command is checked against Shopify's current docs.

How to Build a Custom Shopify Theme: Step-by-Step Guide (2026)

To build a custom Shopify theme in 2026, install Shopify CLI, run shopify theme init to start from Shopify's Skeleton theme, and preview your work on a development store with shopify theme dev. Then build JSON templates, sections and theme blocks in Liquid, lint the code with shopify theme check, push it as an unpublished theme and publish it once it passes testing.

This guide walks through each step with the current commands, checked against Shopify's developer documentation in October 2026. It is written for developers who want to build a theme themselves. If you would rather have it built for you, see our custom Shopify theme development service.

What do you need before you start?

  • Node.js 22.12 or higher and Git 2.28.0 or higher. Shopify CLI needs both, plus npm, Yarn 1.x or pnpm.
  • A development store. A dev store is a free Shopify store for building themes. Create one with shopify store create dev or from the Dev Dashboard. To use it with Shopify CLI, you must be the store owner or have a staff account on it.
  • A code editor. In VS Code, install the Shopify Liquid extension. It adds syntax highlighting, auto-completion, inline docs and Theme Check linting.
  • HTML, CSS, JavaScript and Liquid. Liquid is Shopify's open-source template language. A theme can be buildless: plain Liquid, CSS and JavaScript files are enough.
  • Optional: an AI coding assistant. The Shopify AI Toolkit connects assistants such as Claude Code, Codex or Cursor to Shopify's docs, APIs and CLI. Shopify's own theme tutorial lists it as an optional first step.

How is a Shopify theme structured?

A theme is a folder of Liquid, JSON, CSS and JavaScript files with a fixed structure. Only layout/theme.liquid is required to upload a theme, but a real theme uses all of these folders:

FolderWhat goes in it
assetsCSS, JavaScript, images and fonts, served from Shopify's CDN
blocksTheme blocks: reusable components that merchants can add and nest
configTheme settings (settings_schema.json) and their values (settings_data.json)
layouttheme.liquid, the wrapper around every page, plus optional layouts such as password.liquid
localesTranslation files for storefront text and theme editor labels
sectionsSections and section groups, such as the header and footer groups
snippetsReusable Liquid fragments rendered with {% render %}
templatesOne template per page type, mostly JSON
templates/customersLegacy customer account templates

Modern themes follow Online Store 2.0, the architecture Shopify announced at Unite 2021. Its core ideas are still the base of theme development in 2026:

  • JSON templates. A template is a data file that lists which sections render on a page and in what order. Merchants add, remove and reorder those sections in the theme editor.
  • Sections on most pages, not only on the homepage.
  • Section groups. The header and footer live in JSON groups, so merchants can add sections there too.
  • App blocks. Apps add their UI as blocks that merchants place in the theme editor, instead of editing theme code.
  • Dynamic sources. Settings can pull values from metafields, so one template can serve many products.

One thing to watch in 2026: in July 2026 Shopify released a developer preview of two new Liquid tags, {% block %} and {% partial %}. They let a Liquid template compose a page directly from blocks, without sections. Shopify says existing themes keep working with sections, theme settings and JSON templates. The preview needs a dev store with the Liquid July '26 developer preview enabled, so build production themes on JSON templates, sections and theme blocks for now.

How do you build a Shopify theme, step by step?

Here is the full flow. Each step is explained below.

  1. Install Shopify CLI.
  2. Create the theme with shopify theme init.
  3. Preview it locally with shopify theme dev.
  4. Build templates and sections in Liquid and JSON.
  5. Add theme blocks and app blocks.
  6. Lint the code with Theme Check.
  7. Put the theme in Git and connect GitHub.
  8. Test performance, accessibility and devices.
  9. Push it as an unpublished theme, then publish.

Step 1: Install Shopify CLI

Install Shopify CLI globally with npm. Yarn and pnpm work too.

npm install -g @shopify/cli@latest

On macOS you can use Homebrew instead:

brew tap shopify/shopify
brew install shopify-cli

Check the install with shopify version.

Step 2: Create the theme with shopify theme init

Run shopify theme init with a name for your theme:

shopify theme init my-theme

Without a --clone-url, the command copies Shopify's Skeleton theme, the minimal starting point Shopify uses in its own tutorial. Current CLI versions then ask two questions:

  • Which version of Skeleton? Pick Latest stable release. The Upstream option is Skeleton's main branch. In October 2026 that branch is the v2.0.0 release candidate for the Liquid July '26 preview. It has no sections and no JSON templates, and its new tags may not work on your store. The --latest flag skips the question and takes the stable release.
  • Which LLM instruction file? The CLI can add an AGENTS.md file with instructions for coding assistants such as Claude, Cursor or GitHub Copilot. Sidekick in Shopify Canvas reads a theme's AGENTS.md too, so keep it current as the theme grows.

To start from a complete theme instead, pass another repository. Dawn is Shopify's Online Store 2.0 reference theme and is still maintained. Version 16.0.0 shipped in August 2026.

shopify theme init my-theme --clone-url https://github.com/Shopify/dawn.git --latest

Horizon is the flagship of Shopify's newer free themes. It was released in May 2025 and is built on theme blocks. Its repository is public and worth reading for block patterns, but Shopify itself recommends Skeleton as the starting point for new theme projects.

Selling on the Theme Store? Start from Skeleton. It is the only approved codebase for Theme Store development, and new submissions built on or derived from Dawn or Horizon are not eligible.

Step 3: Preview it locally with shopify theme dev

cd my-theme
shopify theme dev --store your-store.myshopify.com

The first run asks you to log in. The CLI uploads your files as a development theme and serves a preview at http://127.0.0.1:9292, using the store's real products and settings. Shopify's docs say this local preview works only in Google Chrome. Changes to CSS and sections hot-reload without a full page refresh.

The command also prints a link to the theme editor and a preview link you can send to other developers. Two things to know:

  • Development themes are deleted when you run shopify auth logout. For a link that lasts, use shopify theme share or push to an unpublished theme.
  • If you also change settings in the theme editor, add --theme-editor-sync so those edits are written back to your local files.

Step 4: Build templates and sections in Liquid and JSON

Liquid has two kinds of markup. Output tags {{ }} print values, and logic tags {% %} control what renders. This snippet shows the price when a product is in stock and a sold-out label when it is not:

{% if product.available %}
  <div class="price">{{ product.price | money }}</div>
{% else %}
  <div class="sold-out">Sold out</div>
{% endif %}

Templates decide which sections appear on each page type. Here is a JSON product template, templates/product.json, with two sections:

{
  "sections": {
    "main": {
      "type": "product",
      "settings": { "show_vendor": true }
    },
    "recommendations": {
      "type": "product-recommendations"
    }
  },
  "order": ["main", "recommendations"]
}

Each key in sections is a section ID, type points to a file in the sections folder, and order sets the render order. A JSON template can render up to 25 sections, and each section can hold up to 50 blocks.

A few template types can't be JSON: gift_card and robots.txt, plus the agent-discovery files agents.md, llms.txt and llms-full.txt. Shopify serves default versions of those last three for every store, so most themes never need to add them.

Build sections around how the store uses its content, not around a single page. Start with these pages:

  • Homepage: a hero, featured collections and content sections that merchants can reorder.
  • Product page: make the price, variant picker, buy buttons and description separate blocks inside the main product section, so merchants and apps can rearrange them.
  • Collection and search pages: filters, sorting and product cards that stay fast with large catalogs.
  • Cart: the last step the theme controls. Checkout is not built in theme code. Shopify retired checkout.liquid, so checkout is styled in the checkout and accounts editor and extended with checkout extensions.

Step 5: Add theme blocks and app blocks

Blocks are the pieces inside a section. There are three kinds:

Block typeWhere it is definedWhat it is for
Theme blocksTheir own files in the blocks folderReusable across sections and can nest inside other blocks
Section blocksInside one section's {% schema %}Work only in that section, one level deep, and can't share a section with theme blocks
App blocksIn an app's theme app extensionLet merchants place app content, such as reviews or forms, without editing theme code

Theme blocks are the current standard. A section opts in by accepting @theme blocks, plus @app blocks for apps, and renders them with {% content_for 'blocks' %}. Here is sections/feature.liquid:

<div class="feature">
  {% content_for 'blocks' %}
</div>

{% schema %}
{
  "name": "Feature",
  "blocks": [{ "type": "@theme" }, { "type": "@app" }],
  "settings": [],
  "presets": [{ "name": "Feature" }]
}
{% endschema %}

A theme block is a Liquid file in the blocks folder with its own schema. Keep {{ block.shopify_attributes }} on the root element so the theme editor can select the block. Here is blocks/text.liquid:

<div class="text" {{ block.shopify_attributes }}>
  {{ block.settings.text }}
</div>

{% schema %}
{
  "name": "Text",
  "settings": [
    { "type": "text", "id": "text", "label": "Text", "default": "Text" }
  ],
  "presets": [{ "name": "Text" }]
}
{% endschema %}

Two reasons to accept theme blocks and app blocks widely:

  • Merchants can generate new blocks with Sidekick in the theme editor, but only in sections that accept theme blocks.
  • Apps can add reviews, size guides or subscription widgets as blocks, so merchants do not need a developer to paste app code into the theme.

When a block must stay in place, such as slideshow controls, render it as a static block with {% content_for 'block', type: 'slide-controls', id: 'controls' %}. Merchants can still hide it and change its settings, but they can't move or delete it.

Step 6: Lint the code with Theme Check

Theme Check is Shopify's linter for Liquid and JSON. It catches syntax errors, missing templates, unused variables and snippets, unknown or deprecated tags, and performance problems. Run it from the theme folder:

shopify theme check
  • shopify theme check --init creates a .theme-check.yml file, so everyone on the project runs the same checks.
  • --auto-correct fixes the problems it can fix automatically.
  • --fail-level sets the severity that makes the command exit with an error. Use it in CI so failing checks stop the build.

The Shopify Liquid extension for VS Code runs the same checks as you type.

Step 7: Put the theme in Git and connect GitHub

Commit the theme to a Git repository from day one. Then connect it to the store: in the Shopify admin, go to Online Store > Themes, click Add theme > Connect from GitHub, and choose the account, repository and branch.

The sync runs both ways. Pushes to the branch update the theme, and edits saved in the theme editor or the code editor are committed back to the branch. That keeps the branch and the theme in the admin identical. Plan around these rules:

  • The branch must match the default Shopify theme folder structure. If you use a build step, connect a branch that holds the built output.
  • You can connect more than one branch from the same repository, for example main for the live theme and staging for an unpublished theme you review first.
  • A disconnected branch can't be reconnected. Connecting it again adds it as a new theme.

Step 8: Test performance, accessibility and devices

Performance comes from decisions made in the theme. Shopify's theme performance guidance comes down to a few rules:

  • Keep theme assets in the assets folder so Shopify serves them from its CDN. Shopify sets browser caching for cacheable files to one year.
  • Load JavaScript only when it is needed. Add defer to non-critical scripts, and use async only for independent third-party scripts.
  • Render images with the image_url and image_tag filters, so you get a srcset, width and height attributes, and CDN delivery.
  • Lazy-load images below the fold, but never the LCP image, which is usually the hero or the main product photo.
  • Use preload for one or two late-discovered resources at most.
  • Self-host fonts on Shopify's CDN rather than calling an external font service.
  • Avoid deeply nested Liquid loops. They are a common cause of slow server response time.

For a product image below the fold, this gives the browser a set of sizes and lets it pick the right one:

{{ product.featured_image | image_url: width: 1000 | image_tag: loading: 'lazy', widths: '400, 600, 800, 1000', sizes: 'auto' }}

Then measure and test:

  • Run Lighthouse on the home, product and collection pages, on mobile and desktop. You can also use our Shopify speed test, which runs on Google PageSpeed Insights.
  • Use shopify theme profile or the Shopify Theme Inspector for Chrome to find the slowest Liquid.
  • After launch, watch Shopify's Web Performance reports. They use Core Web Vitals (LCP, CLS and INP) from real visitors.
  • Check keyboard navigation, visible focus states, alt text and color contrast.
  • Test in Chrome, Safari and Firefox and on real phones, including menus, filters, forms, the cart and the path to checkout.

Step 9: Push it as an unpublished theme, then publish

shopify theme push --unpublished

This creates a new unpublished theme in the store's theme library and asks you for a name. The live store does not change. Share its preview link, review it in the theme editor and add the real content. Later updates go out with shopify theme push.

Before you publish, check:

  • Navigation, search, filters, product variants, the cart and the path to checkout.
  • Every app block, and that each one shows in the right place.
  • SEO basics: page titles, meta descriptions, one H1 per page, image alt text and product structured data.
  • Every market and language, if the store sells in more than one.

When it is ready, run:

shopify theme publish

Pick the theme from the list and confirm. You can also publish it from Online Store > Themes in the admin. Keep the previous theme in the library so you can switch back quickly if something breaks.

What does the Shopify Theme Store require?

If you plan to sell your theme, Shopify's Theme Store requirements apply on top of everything above. The main ones:

  • Build on Skeleton or on fully original code. Themes built on or derived from Dawn or Horizon are not eligible.
  • Reach an average Lighthouse performance score of at least 60 and an average accessibility score of at least 90, across the home, product and collection pages, on desktop and mobile. Shopify tests with a benchmark dataset, and sections must contain real images and content.
  • Use JSON templates for every template except customer account pages, gift card pages and checkout.
  • Support blocks for all or most elements in the main product section, and support app blocks in the main product and featured product sections.
  • Include a Custom Liquid section, and render the header and footer in section groups.

A theme built for a single store doesn't have to meet these rules, but they make a sensible quality bar.

Should you hire a developer or use a theme?

Most stores do not need a theme built from scratch. A well-chosen Theme Store theme, set up properly, covers a lot. A custom theme pays off when the store's design or logic would force a ready-made theme into constant workarounds.

Your situationWhat we recommend
New store, standard catalog, tight budgetA Theme Store theme set up in the theme editor. Shopify's Horizon themes are free.
A theme mostly fits, but you need a few custom sections or app integrationsKeep the theme and have a developer extend it.
Distinctive design, custom product logic such as configurators or bundles, or several markets with different contentA custom theme built on sections, theme blocks and metafields.
A live store that needs a new look without losing what already worksA redesign of the current theme or a staged rebuild.
You have a developer who knows LiquidBuild it in-house with this guide.

Shopify Canvas and Sidekick now let merchants generate theme changes from a prompt. That makes trying ideas faster, but each change still needs a review of what it touches: shared sections, app blocks, SEO and conversion elements. We cover this in what Shopify Canvas means for custom themes.

If you want the theme built for you, we have been a Shopify Plus Partner since 2017, with more than 500 projects delivered. Custom theme builds on your own design start from €8,000. See our Shopify theme development service, or our store redesign service if you want to evolve a live store without starting over.

Where can you learn more?

FAQ

Do you need to know how to code to build a Shopify theme?

To build a theme from scratch, yes. You need HTML, CSS, JavaScript and Liquid, plus some comfort with the command line and Git. To change an existing theme's layout, colors and content, you don't: the theme editor handles that without code. AI coding assistants can speed up the work, but someone still has to review what they write.

Should I start from Skeleton, Dawn or Horizon?

Start from Skeleton for a new custom theme. It is minimal, Shopify CLI copies it by default, and it is the only approved base for Theme Store themes. Dawn, which is still maintained, and Horizon, which is built on theme blocks, are complete themes and good references. Use them as a base only for a theme that stays on your own store, because Theme Store submissions built on either are not eligible.

What is the difference between theme blocks and app blocks?

Theme blocks are components you write as files in the theme's blocks folder. They work in any section that accepts them and can nest inside each other. App blocks come from installed apps through theme app extensions. Merchants place them in the theme editor, and the theme only needs to accept the @app block type.

Do I still need JSON templates now that the block tag exists?

Yes, for any theme you launch now. The {% block %} and {% partial %} tags are a developer preview from July 2026 and need a dev store with that preview enabled. Shopify says existing themes keep working with sections, theme settings and JSON templates, and the Theme Store still requires JSON templates.

How do I preview a Shopify theme without publishing it?

Run shopify theme dev for a local preview with hot reload, or shopify theme push --unpublished to upload the theme as an unpublished theme in the theme library. shopify theme share also uploads it as a new unpublished theme you can share. The live store doesn't change until you run shopify theme publish or publish the theme from the admin.

Is a Shopify development store free?

Yes. A dev store is a free Shopify store for building and testing themes and apps. Create one with shopify store create dev or from the Dev Dashboard. It can process unlimited test orders but no real transactions, and it always stays password protected.

Want a custom theme built for you?

We design and build custom Shopify themes, with sections your team can edit in the theme editor.

Shopify insights, straight to your inbox

Practical notes on growing a Shopify store: conversion, speed, migrations, and what we learn from client builds.

No spam. Unsubscribe anytime. Privacy Policy

Want more of our posts in your Google results? Add Codersy as a preferred source.

Add Codersy on Google(opens in a new tab)