Building Custom Shopify Experiences: When Headless Beats a Theme
What I've learned building custom Shopify storefronts and apps for merchants, and how I decide between headless and a customized theme.
Most Shopify work I get asked about starts the same way: a merchant has outgrown their theme. They want a product page that behaves differently per collection, a bundle builder, or a storefront that feels like a real product rather than a template with the colors swapped. Liquid can carry you a long way, but at some point you hit the wall where the theme fights you instead of helping. This is where Shopify development beyond themes actually starts, and over the last few years I've built in most corners of that space.
Headless storefronts with Next.js and the Storefront API
The biggest jump is going headless. Instead of rendering through Liquid, I build the storefront in Next.js and pull products, collections, and cart data from Shopify's Storefront API over GraphQL. Shopify stays the source of truth for catalog, inventory, and checkout, while the front end becomes a normal React app I have full control over. That control is the whole point: routing, data fetching, caching, and component structure are mine to shape.
On a recent project for a merchant with a large catalog, I used the Storefront API to drive product and collection pages and the Cart API to manage line items, then handed users off to Shopify's hosted checkout at the end. I lean on Next.js incremental static regeneration for product pages so they stay fast and cheap to serve, and fall back to on-demand fetching for anything that changes often, like inventory counts. Hydrogen, Shopify's own React framework, is a solid path too, but for clients already invested in the Next.js and Jamstack world I usually stay in Next.js so the storefront fits the rest of their stack.
Custom apps, metafields, and checkout extensions
Not every problem needs a full rebuild. A lot of what merchants want lives inside Shopify itself, and metafields are the unsung hero here. I use them to attach structured data to products and collections: ingredient lists, sizing tables, care instructions, or flags that drive conditional UI. Defining metafields with proper types and then reading them through the Storefront API keeps content out of hardcoded templates and in the hands of the merchant's team.
When the logic gets heavier, I build a custom app. That might be an admin tool that syncs orders to an external system, a private app exposing the Admin API for back-office workflows, or a service that listens to webhooks and reacts to events. For the checkout itself, checkout extensions let me add fields, banners, or upsells at specific points without touching the rest of the flow. On Shopify Plus that opens up customizing checkout in ways that used to be locked down, and it's a cleaner approach than the old script-based hacks.
When headless is worth it, and when it isn't
Headless is not a default, it's a tradeoff. You gain a custom front end, real performance control, and the freedom to integrate content from a CMS like Sanity alongside Shopify data. You also take on hosting, a build pipeline, and the reality that some app-store apps assume a Liquid theme and simply won't drop in. I'm honest with clients about that last part, because it surprises people late in a project when it shouldn't.
My rule of thumb: if the merchant mainly needs a polished, on-brand store and edits content often, a well-customized theme with metafields and a few sections is faster to ship and cheaper to maintain. If they need a unique storefront experience, content that lives outside Shopify, or front-end behavior the theme can't express, headless earns its keep. Either way, Shopify stays the commerce engine. The question is only how much of the experience I build on top of it, and I'd rather match that to the merchant's real needs than to whatever sounds impressive.