Skip to content
All posts
3 min read

What Shopify's theme layer is actually for

Every Shopify build eventually faces the same fork: stay in the theme, or go headless. Getting it wrong is expensive in both directions, and the deciding question isn't technical.

  • shopify
  • commerce
  • cms

Shopify's theme layer gets dismissed by people who arrive from application work. Liquid looks dated, the editor constrains you, and the instinct is to reach straight for the Storefront API and build the frontend properly.

Sometimes that is right. More often it trades a solved problem for an unsolved one, and the bill arrives about four months later.

What the theme layer is actually doing

It is easy to see Liquid as a template language and miss that the theme is carrying a large amount of commerce behaviour you would otherwise own:

  • Cart state, including the awkward parts — discount codes, gift cards, line item properties, quantity rules.
  • Checkout handoff, which is not yours to rebuild and where PCI scope lives.
  • Market and currency switching, tax display rules, local pickup.
  • App integrations, which mostly inject themselves via theme extensions and simply stop existing if there is no theme.

That last one surprises teams most often. The reviews widget, the subscription app, the loyalty programme — a merchant buys these expecting them to work. Headless means each one is now an integration project, and some have no headless story at all.

Sections are the content model

The part worth understanding before deciding anything: sections with schema are Shopify's version of a content model, and they are better than their reputation.

{% schema %}
{
  "name": "Featured collection",
  "settings": [
    {
      "type": "collection",
      "id": "collection",
      "label": "Collection"
    },
    {
      "type": "range",
      "id": "product_count",
      "label": "Products to show",
      "min": 2, "max": 12, "step": 2, "default": 4
    }
  ],
  "presets": [{ "name": "Featured collection" }]
}
{% endschema %}

That range is the same discipline as a character limit on a CMS heading: the merchant cannot choose a value that breaks the grid, because the schema does not offer one. A closed set of well-constrained sections gives a merchant real compositional freedom without the ability to build a broken page — which is exactly what you want, and exactly what an open block library fails to provide.

The question that decides it

Not "is Liquid good enough". The question is: who changes this site, and how often?

If a merchandising team adjusts the homepage weekly, runs campaigns, and swaps collections seasonally, the theme editor is the product. Going headless takes that away and replaces it with a deploy. You will have built something faster that changes more slowly, and merchandising velocity is usually worth more than a Lighthouse score on a storefront.

If the storefront is largely static, the differentiator is a custom experience Liquid genuinely cannot express — a configurator, a complex search, deep integration with systems outside Shopify — and there is an engineering team committed to owning it, headless earns its cost.

The middle path is underrated

The framing is not binary. Shopify's own headless stack keeps the checkout and the commerce primitives while giving you a real frontend, and a well-built theme can host a mounted application on the one route that needs it.

Most of the projects I have seen regret going headless did not need a new frontend. They needed three sections rebuilt and someone to delete four apps that were each adding a render-blocking script to every page.

If you do stay in the theme

Two things carry most of the value.

Audit the apps. App scripts are the dominant performance problem on almost every Shopify storefront I have looked at — well ahead of anything in the theme. Each one a merchant installs adds script tags that load on every page, including ones where the app does nothing. Removing three unused apps routinely beats a month of theme optimisation.

Constrain the schema. Every setting you expose is a way for the site to end up looking wrong. Ranges over free numbers, a fixed set of colour options rather than a picker, character limits on anything that has to fit. The merchant is not the enemy here — they simply have no way to know that a 90-character heading wraps to four lines on a phone, and the schema is where you can tell them.