As someone who's spent most of my time building headless storefronts with frameworks like Next.js, I didn't take Shopify theme development very seriously until recently.
The truth is that theme customization is much more common than headless builds. It is faster to ship, easier to hand off to clients, and more budget-friendly. I wanted to understand how Shopify's native themes work and what it takes to customize or build one from scratch using Liquid.
This post breaks down the mental model that helped me get up to speed. If you're a frontend or full-stack developer coming from the React or Next.js world and trying to understand Shopify’s Liquid-based theming system, this is for you.
The 80/20 of Shopify Themes: Start Here
Look at the high-level structure. Shopify themes are made of templates, sections, blocks, snippets, and assets.
Once you see how these parts fit together, you know about 80 percent of the system.
Templates
Templates are top-level pages.
Each template defines the layout for one page type. This includes product pages, collection pages, cart, homepage, and others.
You can pre-process CSS (for example, with Tailwind) or JavaScript (for example, with React) and upload the final files here.
How the {% schema %} Block Works (and Why It Matters)
In Shopify theme development, the {% schema %} block lets you turn static Liquid files into customizable components. Merchants can then edit these through the Theme Editor without touching code.
In simple terms: Schema lets you define settings and content blocks for the end user (the merchant) to control.
This lets merchants control the page structure by adding, removing, or reordering sections. The content for sections is still defined by the section's schema.
Two Ways to Add Content: Native Data and Theme Settings
Once you have the structure, your content comes from one of two places.
Native Shopify Data
Shopify provides data objects, depending on page context.
You often combine these with Shopify’s native data for dynamic, editable themes.
Quick Folder Structure Recap
Here's how it fits together in files:
code
/templates/product.liquid
└── references sections (e.g. main-product, related-products)
/sections/main-product.liquid
└── defines blocks (e.g. features, highlights)
/snippets/
└── reusable logic or markup
/assets/
└── theme.css, app.js, fonts, images
/templates/index.json
└── declares dynamic sections and their order
Bonus: What About Tailwind or React?
You can use Tailwind or React, but you must build them outside Shopify and upload as static assets.
Tailwind CSS
Set up Tailwind locally.
Let Tailwind scan .liquid files for class usage.
Build your theme.css using Tailwind and PurgeCSS.
Upload theme.css to /assets/ and link it in your theme layout.
React
Build with Vite or another bundler.
Output a bundled JS file (for example, app.js).
Upload it to /assets/.
Reference the script in your Liquid layout and mount to a DOM node.
I'll cover this workflow in a separate article soon.
Final Thoughts
If you are coming from React or Next.js, Shopify's Liquid system can feel strange at first. Once you understand:
Templates, sections, and blocks
Native data vs. Theme Editor settings
How schema ties everything together
it all becomes clearer.
This mental model helps you build dynamic, flexible, and merchant-friendly themes without overcomplication. As you get more advanced, it's easy to bring in Tailwind, React, or APIs.
Let me know if you want to see more articles about dynamic sections, metafields, performance, or deployment workflows.