Streaming CMS Content in Hydrogen with Sanity and Contentful

Introduction

Hydrogen gives Shopify developers React-first power, but content marketers need more than APIs — they need a CMS. Sanity and Contentful are the leading choices, and when paired with React Router 7’s defer() streaming, they can deliver fast, SEO-friendly storefronts with dynamic content that doesn’t block page loads.

This post shows how to integrate CMS SDKs directly into Hydrogen loaders, stream content to the client, and balance performance with editorial flexibility.

Why Streaming Matters in Hydrogen

  • ⚡ First paint faster → stream product and cart essentials first.
  • 📝 Editorial flexibility → pull CMS content without slowing PDPs.
  • 🌍 Localization → serve localized content from Contentful or Sanity schemas.
  • 🔍 SEO-safe → crawlers see HTML-first output, not blank JS shells.

Without streaming, Hydrogen pages risk slow TTFB and blocked rendering.

Sanity Integration Example

Loader

import { createClient } from '@sanity/client'; import { defer } from '@shopify/remix-oxygen'; const sanity = createClient({ projectId: "abc123", dataset: "production", useCdn: true, }); export async function loader() { const productData = await fetchProduct(); // Shopify Storefront API const cmsPromise = sanity.fetch(`*[_type == "storyHub"][0]`); return defer({ product: productData, cms: cmsPromise, // stream later }); }

Component

export default function ProductPage() { const data = useLoaderData<typeof loader>(); return ( <div> <ProductDetails product={data.product} /> <Suspense fallback={<p>Loading content…</p>}> <Await resolve={data.cms}> {(cms) => <StoryHub content={cms} />} </Await> </Suspense> </div> ); }

👉 Shopify product data loads first, Sanity content streams after.

Contentful Integration Example

Multi-Locale Campaigns

  • Contentful’s GraphQL API supports locale param.
  • Hydrogen loader fetches correct locale async.
  • Use defer() to avoid blocking PDPs while campaign banners stream in.

query($locale: String!) { campaignCollection(locale: $locale, limit: 1) { items { title, body } } }

Case Study: International Campaigns

A DTC brand launched a holiday campaign across 5 markets.

  • Shopify products served instantly.
  • Contentful campaign banners streamed by locale.
  • TTFB improved by 40%, Lighthouse LCP went green.
  • Marketers updated banners in Contentful without dev intervention.

Best Practices

  • ✅ Stream CMS data with defer() to avoid blocking.
  • ✅ Use Sanity for flexible schemas, Contentful for localization/governance.
  • ✅ Always fallback → “Loading content” states.
  • ✅ Cache CMS queries when possible.
  • ✅ QA with Lighthouse to ensure SEO output is crawlable.

Conclusion

Sanity and Contentful make Hydrogen stores editorial-friendly. With React Router 7 streaming, you get the best of both worlds: fast storefronts for customers and flexible content tools for marketers.

CMS integration isn’t just about editing — it’s about streaming content without slowing the store.