<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nathan Allen</title>
    <description>The latest articles on DEV Community by Nathan Allen (@nathan_allen).</description>
    <link>https://dev.to/nathan_allen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4170899%2F0a49d9e8-9064-41e2-a232-95f0fc757d2e.jpg</url>
      <title>DEV Community: Nathan Allen</title>
      <link>https://dev.to/nathan_allen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nathan_allen"/>
    <language>en</language>
    <item>
      <title>Headless Ecommerce Is Easy to Explain. System Ownership Is the Hard Part.</title>
      <dc:creator>Nathan Allen</dc:creator>
      <pubDate>Mon, 12 Oct 2026 09:08:41 +0000</pubDate>
      <link>https://dev.to/nathan_allen/headless-ecommerce-is-easy-to-explain-system-ownership-is-the-hard-part-4g3c</link>
      <guid>https://dev.to/nathan_allen/headless-ecommerce-is-easy-to-explain-system-ownership-is-the-hard-part-4g3c</guid>
      <description>&lt;p&gt;A headless ecommerce diagram looks clean. A Next.js storefront on top. A commerce API underneath. Two boxes and one arrow.&lt;/p&gt;

&lt;p&gt;Production rarely stays that tidy. Search arrives. Then a CMS, an ERP, a PIM, inventory rules, promotions, tax, analytics, and personalization. Every new box brings its own failure modes.&lt;/p&gt;

&lt;p&gt;When I review these architectures, decoupling is rarely the hard part. Ownership is. The better question is not “should we go headless?” It is this: when we decouple the storefront, which responsibilities did we actually move, and who owns them now?&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless Does Not Remove the Backend
&lt;/h2&gt;

&lt;p&gt;Separating the storefront removes the theme layer. It does not remove the work the platform was doing. Checkout, pricing, inventory, customer accounts, orders, fulfillment, tax, promotions, and product data still exist. They need a clear home.&lt;/p&gt;

&lt;p&gt;In a traditional setup, the commerce platform owns most of that by default. The theme calls platform code directly. When something breaks, there is usually one place to look.&lt;/p&gt;

&lt;p&gt;After decoupling, the same responsibilities can spread across several systems and several teams. This is the diagram most proposals show:&lt;/p&gt;

&lt;p&gt;Customer&lt;br&gt;
   ↓&lt;br&gt;
Next.js / React Storefront&lt;br&gt;
   ↓&lt;br&gt;
API Layer&lt;br&gt;
   ├── Commerce&lt;br&gt;
   ├── CMS&lt;br&gt;
   ├── Search&lt;br&gt;
   ├── ERP&lt;br&gt;
   └── Inventory&lt;/p&gt;

&lt;p&gt;The diagram is easy. The questions it hides are not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which system is authoritative for price and stock?&lt;/li&gt;
&lt;li&gt;Who owns the failure when one API is down?&lt;/li&gt;
&lt;li&gt;What happens when inventory sync is delayed?&lt;/li&gt;
&lt;li&gt;What happens when CMS content references a removed product?&lt;/li&gt;
&lt;li&gt;What happens when pricing differs by region?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the team cannot answer these before the build, it will answer them during an incident.&lt;/p&gt;

&lt;p&gt;Platform choice does not settle this either. Shopify’s Hydrogen is built on React Router and works with the Storefront API and Customer Account API. BigCommerce’s Catalyst is built with Next.js on its GraphQL Storefront API. Both give you a solid frontend starting point. Neither decides ownership for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Problems That All Get Called “Headless”
&lt;/h2&gt;

&lt;p&gt;The request sounds identical every time: “we need headless.” The underlying problems are not identical. I try to separate them first. For the business side of that decision, see &lt;a href="https://www.gyan.solutions/ecommerce/blog/headless-ecommerce-vs-traditional-ecommerce/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=headless-system-ownership&amp;amp;utm_content=nathan-headless-cms-page" rel="noopener noreferrer"&gt;headless ecommerce vs traditional ecommerce&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A frontend problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The store has a slow theme, heavy scripts, and a dated design. But the catalog is standard. Pricing is standard. Checkout works. There is one storefront and few integrations.&lt;/p&gt;

&lt;p&gt;Here the constraint is frontend engineering. Clean up the theme, audit third-party code, fix images and caching. A new architecture would add a deployment pipeline and an API layer to solve a problem that better frontend work can solve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. An experience problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Marketing needs buying guides, product education, campaign pages, and flexible layouts. Every idea has to fit theme templates, and every test needs a developer.&lt;/p&gt;

&lt;p&gt;This is where separating presentation from commerce starts to pay off. Commerce keeps products, carts, and checkout. A CMS and a custom frontend own the experience. Each side can then change without forcing the other to move.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. An architecture problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The business has an ERP, a PIM, regional pricing, B2B rules, and fulfillment systems. Orders and stock move between tools. Middleware keeps growing.&lt;/p&gt;

&lt;p&gt;This is bigger than a frontend decision. The storefront is one consumer of a wider system. The real work is deciding where pricing, inventory, and orders live and how those systems agree with each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless Is Not a Performance Strategy by Itself
&lt;/h2&gt;

&lt;p&gt;A Next.js storefront can still be slow. I would not assume otherwise because the repo is modern.&lt;/p&gt;

&lt;p&gt;Real storefronts collect analytics, tag managers, review widgets, personalization, and ad scripts. Slow APIs and uncached calls add latency. Oversized images and heavy client-side JavaScript add more. A decoupled frontend can carry all of that, and sometimes adds new network calls on top.&lt;/p&gt;

&lt;p&gt;Performance depends on engineering: rendering strategy, caching, image delivery, API response times, and script discipline. Headless gives you control over those. It does not do the work for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless and Composable Solve Different Levels of Separation
&lt;/h2&gt;

&lt;p&gt;Headless separates presentation from the commerce backend. That is one cut.&lt;/p&gt;

&lt;p&gt;Composable architecture makes several cuts. Commerce, CMS, search, PIM, ERP, personalization, and analytics can each be a separate service with its own owner. You choose the best tool per capability and connect them through APIs.&lt;/p&gt;

&lt;p&gt;That flexibility is real. So is the cost. Each additional cut adds integrations, monitoring, vendor relationships, and another place for data to drift. I treat headless as one decision and composable as a bigger one. They should not be bought together by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a CMS Should and Should Not Own
&lt;/h2&gt;

&lt;p&gt;Content is often the first thing teams separate, and for good reasons. Buying guides, landing pages, FAQs, campaign copy, and regional editorial content change often. Editors need previews and structure, not a deploy.&lt;/p&gt;

&lt;p&gt;A well-planned &lt;a href="https://www.gyan.solutions/technology/headless-cms-development/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=headless-system-ownership&amp;amp;utm_content=nathan-headless-cms-page" rel="noopener noreferrer"&gt;headless CMS architecture&lt;/a&gt; gives that content a proper home. But the CMS should not quietly grow into a second commerce system.&lt;/p&gt;

&lt;p&gt;Pricing, inventory, customers, checkout, and orders belong to commerce or to the operational systems behind it. When a CMS stores its own copy of a price or stock level, you now have two sources of truth. One of them will be wrong at the worst time.&lt;/p&gt;

&lt;p&gt;The safer pattern is to store references. CMS content points to a product ID. The frontend fetches live commercial data from the commerce API and combines it with editorial content at render time.&lt;/p&gt;

&lt;p&gt;Next.js supports this with on-demand revalidation by tag or path. A CMS webhook can trigger it when content changes. That keeps pages fresh without rebuilding everything. It also creates a dependency someone must monitor.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Rough Decision Table
&lt;/h2&gt;

&lt;p&gt;This is a starting point, not a rulebook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgp9pv2ie3yj6w39vfw6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgp9pv2ie3yj6w39vfw6c.png" alt=" " width="690" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Decoupled Technology, Undecoupled Responsibility
&lt;/h2&gt;

&lt;p&gt;This is where distributed architecture turns into distributed confusion. The technology is separated. The responsibility is not.&lt;/p&gt;

&lt;p&gt;Here is the pattern I look for in reviews. A price looks wrong on the storefront. Is it the commerce platform, the ERP sync, a regional price list, or a stale cache? If four teams each own a piece and nobody owns the path, the answer takes hours.&lt;/p&gt;

&lt;p&gt;Or take inventory. The ERP is authoritative, but the commerce platform shows stock. A sync runs late. The storefront sells something that is gone. Who decides what customers see when the data is uncertain?&lt;/p&gt;

&lt;p&gt;I want a written answer to a few things for every system in the stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is it the source of truth for?&lt;/li&gt;
&lt;li&gt;Who owns its uptime and its upgrades?&lt;/li&gt;
&lt;li&gt;What does the storefront show when it fails?&lt;/li&gt;
&lt;li&gt;How do we detect that it faile
d?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is exciting. All of it decides whether the architecture survives its second year.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I Would Not Go Headless
&lt;/h2&gt;

&lt;p&gt;I get cautious when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The store has standard requirements&lt;/li&gt;
&lt;li&gt;The existing platform handles checkout well&lt;/li&gt;
&lt;li&gt;One storefront is enough&lt;/li&gt;
&lt;li&gt;Integrations are limited&lt;/li&gt;
&lt;li&gt;The theme can support the experience the business needs&lt;/li&gt;
&lt;li&gt;No engineering team owns the extra infrastructure
Sometimes keeping the monolith is good engineering. A simpler system with clear ownership beats a flexible one nobody can explain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Question I Start With
&lt;/h2&gt;

&lt;p&gt;Headless gives teams real freedom over the frontend, the content, and the integrations. That freedom is valuable when a specific constraint justifies it.&lt;/p&gt;

&lt;p&gt;So I start with one question. What is the current platform preventing us from doing cleanly? If the answer is a theme, fix the theme. If it is content freedom, separate content. If it is operations, look behind the storefront.&lt;/p&gt;

&lt;p&gt;How have you decided where pricing and inventory live once the storefront was decoupled?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ecommerce</category>
      <category>architecture</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>I Like Strapi for Ecommerce. I Still Wouldn't Start With Strapi.</title>
      <dc:creator>Nathan Allen</dc:creator>
      <pubDate>Thu, 08 Oct 2026 10:17:55 +0000</pubDate>
      <link>https://dev.to/nathan_allen/i-like-strapi-for-ecommerce-i-still-wouldnt-start-with-strapi-n19</link>
      <guid>https://dev.to/nathan_allen/i-like-strapi-for-ecommerce-i-still-wouldnt-start-with-strapi-n19</guid>
      <description>&lt;p&gt;I wouldn't start with Strapi.&lt;/p&gt;

&lt;p&gt;I wouldn't start with Sanity, Payload, or any other CMS either. The first decision in an ecommerce stack isn't the CMS. It's simpler than that. Which system owns each piece of data?&lt;/p&gt;

&lt;p&gt;Teams skip that question because choosing a tool feels like progress. Content types get modeled. Pages get built. Then two systems quietly start storing the same price.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ownership Comes Before the Tool
&lt;/h2&gt;

&lt;p&gt;Before I look at any CMS, I list what the business actually stores. Products and variants. Prices and promotions. Inventory. Cart, checkout, and orders. Editorial content. Search indexes. Customer data. Anything the ERP or PIM already holds.&lt;/p&gt;

&lt;p&gt;Then I ask three questions about each item. Who writes it? Who reads it? What should the storefront do when the owner is down?&lt;/p&gt;

&lt;p&gt;The last question matters most. It's easy to say "the commerce backend owns prices." It's harder to decide what the page shows when that backend times out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Overlapping Ownership Looks Like
&lt;/h2&gt;

&lt;p&gt;*&lt;em&gt;Here's a stack I'd call reasonable:&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
Storefront (Next.js)&lt;br&gt;
 ├─ Strapi  → editorial content&lt;br&gt;
 ├─ Medusa  → products, prices, carts, orders&lt;br&gt;
 ├─ ERP     → warehouse stock&lt;br&gt;
 └─ Search  → indexed catalog&lt;/p&gt;

&lt;p&gt;Each box has one job. Strapi holds guides, campaigns, and FAQs. Medusa runs commerce. The ERP owns stock. Search owns discovery.&lt;/p&gt;

&lt;p&gt;Now add one shortcut. A marketer wants a sale price inside a campaign banner. Someone adds a price field to the Strapi content type. Both Strapi and Medusa can now hold an editable price.&lt;/p&gt;

&lt;p&gt;That's where the trouble starts. A sync job gets written. It runs late, or it fails quietly. Say the banner shows 49 and the cart shows 59. No CMS feature fixes that. It's an ownership bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture Mistake I See Most Often
&lt;/h2&gt;

&lt;p&gt;The mistake is modeling content before deciding ownership. It feels harmless. A "Product Highlight" type with name, price, stock status, and image looks useful on day one.&lt;/p&gt;

&lt;p&gt;Later, those fields drift. Names change in the commerce backend. Stock changes in the ERP. Editors fix what they can see, and nobody trusts the data anymore.&lt;/p&gt;

&lt;p&gt;Now I write a one-page ownership table first. Every field gets one owner. If the CMS doesn't own a field, it doesn't get a copy of it. It gets a reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store References, Not Copies
&lt;/h2&gt;

&lt;p&gt;A reference is usually a product handle or ID. The CMS stores which product, not what the product is.&lt;/p&gt;

&lt;p&gt;`// Editorial content comes from Strapi&lt;br&gt;
const campaign = await strapi.getCampaign(slug);&lt;/p&gt;

&lt;p&gt;// Product facts come from the commerce backend&lt;br&gt;
const products = await commerce.getProducts(campaign.productHandles);`&lt;/p&gt;

&lt;p&gt;This keeps one source of truth. But it has a cost. Every campaign page now needs two requests. Previews need commerce data too. If the commerce API is slow, the campaign page is slow.&lt;/p&gt;

&lt;p&gt;So I decide the failure behavior up front. If products don't load, the page should still show the editorial content. The product block can hide or fall back. A buying guide shouldn't return a 500 because a price service had a bad minute.&lt;/p&gt;

&lt;p&gt;I'd rather accept two requests than maintain two prices. But it's a tradeoff, not a free win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Webhooks, Caching, and Stale Content
&lt;/h2&gt;

&lt;p&gt;Once content and commerce live apart, freshness becomes your job. Strapi can send webhooks on events like entry.create, entry.update, entry.publish, and entry.unpublish. For most events, the payload contains the full entry with its relations and components.&lt;/p&gt;

&lt;p&gt;A common pattern is to call your frontend when an editor publishes. The frontend then revalidates the affected page. In Next.js, that's on-demand revalidation.&lt;/p&gt;

&lt;p&gt;Two details matter to me. First, secure the endpoint. Strapi lets you configure webhook headers, so verify them. Second, don't treat a webhook as a guarantee. I'd add a scheduled reconcile job, so one missed event doesn't leave a page stale for days.&lt;/p&gt;

&lt;p&gt;Preview needs thought too. Editors want to see drafts. The preview route has to read draft content from Strapi and still fetch live commerce data. Test that path early. In my experience it breaks more easily than the published path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Strapi Earns Its Place
&lt;/h2&gt;

&lt;p&gt;I like Strapi when content needs real structure. Components and Dynamic Zones let editors assemble pages from approved blocks. REST and GraphQL let each channel request what it needs. Backend customization is real, and you can self-host it.&lt;/p&gt;

&lt;p&gt;Next to Medusa, the split is clean. Medusa handles products, variants, pricing, carts, and orders through its commerce modules. Strapi handles guides, campaigns, FAQs, and reusable blocks. Different problems, different systems.&lt;/p&gt;

&lt;p&gt;But using both increases what you own. That's two deployments, two upgrade paths, two permission models, and one more integration to monitor. Strapi 5 also changed core APIs, so I check version support before depending on any community plugin. If you want a closer look at the implementation side, this page on &lt;a href="https://www.gyan.solutions/technology/strapi-development-services/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=strapi-ownership-first&amp;amp;utm_content=article-middle" rel="noopener noreferrer"&gt;Strapi development services&lt;/a&gt; covers content models, integrations, and upgrades.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I Wouldn't Add Strapi
&lt;/h2&gt;

&lt;p&gt;The commerce platform already covers your content needs&lt;br&gt;
Nobody owns hosting, upgrades, and security&lt;br&gt;
The team wants fully managed infrastructure&lt;br&gt;
Another CMS fits your editor workflow better&lt;br&gt;
The design needs the CMS to duplicate operational data&lt;/p&gt;

&lt;p&gt;The last one is a design problem, not a tooling problem. If the plan requires copying prices or stock into the CMS, I'd fix the plan before choosing software.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Ask Before Installing Anything
&lt;/h2&gt;

&lt;p&gt;Who owns each field? What happens when that owner is unavailable? How does a content change reach the storefront? Who patches the CMS? Who owns the integration between systems?&lt;/p&gt;

&lt;p&gt;If I can't answer those in plain language, the CMS isn't the next step. A missing answer usually means two systems will fight over the same data later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Principle I Keep
&lt;/h2&gt;

&lt;p&gt;I still like Strapi. I just don't start there anymore.&lt;/p&gt;

&lt;p&gt;I start with one page that says who owns what. Once that page is honest, the CMS choice gets smaller and calmer. Sometimes the answer is Strapi. Sometimes it's something simpler. Either way, the stack has fewer arguments waiting to happen.&lt;/p&gt;

</description>
      <category>strapi</category>
      <category>architecture</category>
      <category>ecommerce</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
