<?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>Forem: FocusReactive | Headless CMS Agency</title>
    <description>The latest articles on Forem by FocusReactive | Headless CMS Agency (@focusreactive).</description>
    <link>https://forem.com/focusreactive</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.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7833%2Fc570dc76-be10-4541-a24b-c091d92fc6fe.png</url>
      <title>Forem: FocusReactive | Headless CMS Agency</title>
      <link>https://forem.com/focusreactive</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/focusreactive"/>
    <language>en</language>
    <item>
      <title>7 Headless CMSs in 2026 — and the Mistakes Teams Make Picking Them</title>
      <dc:creator>Katarina Drozd</dc:creator>
      <pubDate>Thu, 02 Apr 2026 11:55:26 +0000</pubDate>
      <link>https://forem.com/focusreactive/7-headless-cmss-in-2026-stop-picking-the-wrong-headless-cms-a-no-bs-guide-5dfp</link>
      <guid>https://forem.com/focusreactive/7-headless-cmss-in-2026-stop-picking-the-wrong-headless-cms-a-no-bs-guide-5dfp</guid>
      <description>&lt;p&gt;In this guide, we’ll walk through how to pick a headless CMS that fits real‑world enterprise, marketing, and content‑ops needs — not just your current stack.&lt;/p&gt;

&lt;p&gt;When you choose a CMS for your next project, that decision shapes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How your content operations run.&lt;/li&gt;
&lt;li&gt;How editors create and update content.&lt;/li&gt;
&lt;li&gt;How your stack scales over time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;47% of organizations cite a skills gap and 44% report integration complexity as their top headless CMS challenges &lt;a href="https://www.globalgrowthinsights.com/market-reports/headless-cms-platform-software-market-100423" rel="noopener noreferrer"&gt;Global Growth Insights&lt;/a&gt; — both symptoms of picking the wrong platform for your team.&lt;/p&gt;

&lt;p&gt;We’ve shipped headless projects in production using Contentful, Sanity, Storyblok, Payload CMS, Hygraph, Directus, and Strapi — no vendor partnerships, no hidden agenda, just real‑world experience picking the right tool for the job.&lt;/p&gt;

&lt;p&gt;Let's get into it — platform by platform, no vendor bias.&lt;/p&gt;

&lt;h2&gt;
  
  
  The headless CMS landscape (the short list)
&lt;/h2&gt;

&lt;p&gt;Here are the most relevant options we see clients seriously considering:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Contentful&lt;/li&gt;
&lt;li&gt;Storyblok &lt;/li&gt;
&lt;li&gt;Sanity&lt;/li&gt;
&lt;li&gt;Payload&lt;/li&gt;
&lt;li&gt;Hygraph &lt;/li&gt;
&lt;li&gt;Directus&lt;/li&gt;
&lt;li&gt;Strapi&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  TL;DR – CMS “defaults” in 60 seconds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Contentful CMS&lt;/strong&gt; – Enterprise default. Mature, compliant, expensive.&lt;/p&gt;

&lt;p&gt;Pay 40–60% more than the headline price once you hit hidden limits.&lt;/p&gt;

&lt;p&gt;Worth it if you’re doing sophisticated personalization at scale; otherwise, you’re just carrying costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storyblok CMS&lt;/strong&gt; – Marketing‑site‑first CMS with great self‑serve UX.&lt;/p&gt;

&lt;p&gt;Visual editor is excellent, but the architecture can push back once your content model outgrows typical marketing patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanity CMS&lt;/strong&gt; – Content operations platform for dev‑led teams.&lt;/p&gt;

&lt;p&gt;Schema‑as‑code, GROQ, real‑time collaboration.&lt;/p&gt;

&lt;p&gt;Overkill for a simple marketing site; rewards teams who invest in building a proper Studio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload CMS&lt;/strong&gt; – MIT‑licensed, Next.js‑native, self‑hostable CMS.&lt;/p&gt;

&lt;p&gt;No licensing ceiling, full ownership.&lt;/p&gt;

&lt;p&gt;You’re betting on your dev team: upfront investment is real, but the ceiling is yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hygraph&lt;/strong&gt; – GraphQL federation for complex backends.&lt;/p&gt;

&lt;p&gt;Only worth it if you genuinely need GraphQL federation across multiple systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directus&lt;/strong&gt; – Open‑source path. Use Directus when you need to wrap an existing SQL database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strapi&lt;/strong&gt; - Open-source default for greenfield JavaScript projects.&lt;/p&gt;

&lt;p&gt;Largest community in the open-source CMS space, visual content-type builder, SQL-only. Free core is genuinely free — but advanced roles, environments, and key plugins will cost you once you scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Match Your Project to the Right CMS
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Best default CMS&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Situational need&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Contentful&lt;/td&gt;
&lt;td&gt;Enterprise-scale, large budget, advanced personalization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storyblok&lt;/td&gt;
&lt;td&gt;Small–mid marketing site, strong editor independence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sanity&lt;/td&gt;
&lt;td&gt;Experienced dev team, complex content ops, or Shopify-like complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payload CMS&lt;/td&gt;
&lt;td&gt;Flexible, scalable platform beyond standard CMS limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hygraph&lt;/td&gt;
&lt;td&gt;Genuine need for GraphQL federation across backends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strapi&lt;/td&gt;
&lt;td&gt;New project, open-source, JavaScript/TypeScript stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Directus&lt;/td&gt;
&lt;td&gt;Existing database, internal tools, legacy data modernization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Headless CMS Overview: Directorial listing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Contentful – The enterprise standard&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/contentful" rel="noopener noreferrer"&gt;Contentful on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of Contentful CMS as the “IBM of headless CMS.” It’s the safe, nobody‑gets‑fired‑for‑this choice. It’s mature, stable, and has solid compliance and uptime — which is why ~30% of the Fortune 500 use it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structured content, strong localization, and growing AI‑assisted features.&lt;/li&gt;
&lt;li&gt;Enterprise‑grade availability and governance.&lt;/li&gt;
&lt;li&gt;Huge ecosystem and referenceable case studies for procurement teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pricing is designed to extract maximum value. You start on an “affordable” plan, then hit content‑type limits, usage overages, and “enterprise‑only” features.&lt;/li&gt;
&lt;li&gt;The content model is rigid compared to more flexible options like Sanity or Payload.&lt;/li&gt;
&lt;li&gt;Marketers get a functional, but uninspiring UI and pay enterprise rates for it.&lt;/li&gt;
&lt;li&gt;Many teams end up paying for 80% of features they never use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👍🏻 When to use Contentful&lt;/p&gt;

&lt;p&gt;You need enterprise‑grade personalization (Contentful Studio, A/B testing, AI content gen).&lt;/p&gt;

&lt;p&gt;You’re running sophisticated campaigns and want compliance, SLAs, and integrations in one package.&lt;/p&gt;

&lt;p&gt;👎🏻 When to avoid it&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost‑conscious projects.&lt;/li&gt;
&lt;li&gt;Small teams.&lt;/li&gt;
&lt;li&gt;Any situation where you pay the enterprise tax without using the enterprise‑level features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Storyblok – The marketer’s platform&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/storyblok" rel="noopener noreferrer"&gt;Storyblok on Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Headless CMS has a classic problem: it liberates developers but often imprisons marketers. A lot of projects focus on dev flexibility while leaving editors with ticket‑based workflows.&lt;/p&gt;

&lt;p&gt;Storyblok is built on the opposite idea: editors come first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storyblok Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag‑and‑drop visual editor, live previews, and self‑serve publishing.&lt;/li&gt;
&lt;li&gt;Component‑based architecture that makes sense for marketing sites: heroes, features, testimonials, CTAs.&lt;/li&gt;
&lt;li&gt;Huge win for marketing sites, landing pages, and campaign content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Storyblok Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The component‑based model gives you Storyblok’s constraints, not yours.&lt;/li&gt;
&lt;li&gt;As your content model grows, page/component counts rise, and multi‑domain or multi‑channel content becomes harder.&lt;/li&gt;
&lt;li&gt;If your “marketing site” evolves into an application‑like product (commerce, workflows, custom logic), you hit architectural walls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👍🏻 When to use Storyblok&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small–mid marketing sites.&lt;/li&gt;
&lt;li&gt;Agencies whose clients need to self‑serve.&lt;/li&gt;
&lt;li&gt;Organizations where marketing autonomy is a real business requirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎🏻 When to avoid Storyblok&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex content models.&lt;/li&gt;
&lt;li&gt;Unusual data relationships.&lt;/li&gt;
&lt;li&gt;Projects likely to grow beyond typical marketing‑site patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Sanity – The content operations platform&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/sanity-io" rel="noopener noreferrer"&gt;Sanity on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sanity is the headless CMS for devs who typically hate CMSs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanity Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema‑as‑code in version control.&lt;/li&gt;
&lt;li&gt;Real‑time collaboration that actually works (Google Docs‑style).&lt;/li&gt;
&lt;li&gt;GROQ: fetch exactly the data you need and transform it in a single query.&lt;/li&gt;
&lt;li&gt;Dev‑led teams with strong front‑end capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sanity Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual editing is weak. Present (preview) is helpful, but marketers will still need dev help.&lt;/li&gt;
&lt;li&gt;Free tier is generous for small projects, but enterprise pricing scales aggressively.&lt;/li&gt;
&lt;li&gt;Overkill for standard corporate marketing sites — you pay for capabilities you don’t use and get a worse editor experience than simpler options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👍🏻 When to use Sanity&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large content operations.&lt;/li&gt;
&lt;li&gt;Teams willing to invest in building a custom Studio.&lt;/li&gt;
&lt;li&gt;Organizations where content modeling is strategic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎🏻 When to avoid Sanity&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tight budgets.&lt;/li&gt;
&lt;li&gt;Standard marketing sites.&lt;/li&gt;
&lt;li&gt;Teams that need marketing independence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Payload CMS – Build your ideal CMS&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/payloadcms/payload" rel="noopener noreferrer"&gt;Payload on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Payload is the newer, MIT‑licensed, Next.js‑native CMS that’s gaining traction in the TypeScript ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload's Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep integration with Next.js (front‑end + admin).&lt;/li&gt;
&lt;li&gt;Self‑hostable, scalable, and fully owned.&lt;/li&gt;
&lt;li&gt;MIT‑style licensing: no awkward commercial‑use restrictions.&lt;/li&gt;
&lt;li&gt;A flexible foundation, not a finished product.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Payload's Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You build the CMS experience, so upfront dev time is real.&lt;/li&gt;
&lt;li&gt;Ecosystem is growing but younger than Strapi or Sanity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👍🏻 When to use Payload&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teams that live in Next.js and TypeScript.&lt;/li&gt;
&lt;li&gt;Organizations that want to own their stack completely.&lt;/li&gt;
&lt;li&gt;Projects that won’t fit neatly into standard CMS patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎🏻 When to avoid Payload&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non‑Next.js teams.&lt;/li&gt;
&lt;li&gt;“Turnkey” expectations.&lt;/li&gt;
&lt;li&gt;Cases where time‑to‑market matters more than long‑term flexibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Hygraph CMS – The GraphQL specialist&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/hygraph" rel="noopener noreferrer"&gt;Hygraph on Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of Hygraph as the purpose-built CMS choice when your architecture genuinely requires unifying content across multiple backends, systems, and data sources into a single GraphQL API layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hygraph's Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native GraphQL federation: combine editorial content, product data, and third-party APIs into one unified graph.&lt;/li&gt;
&lt;li&gt;Content federation without replication — query remote data directly rather than duplicating it.&lt;/li&gt;
&lt;li&gt;Clean developer experience for teams already living in GraphQL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hygraph's Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to overbuy: most projects don't actually need federation, and Hygraph's core strength goes unused.&lt;/li&gt;
&lt;li&gt;Smaller community and ecosystem compared to Contentful, Sanity, or Strapi.&lt;/li&gt;
&lt;li&gt;Visual editing is basic — not a platform marketers will enjoy independently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👍🏻 When to use GraphQL CMS &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong fit for complex, multi-source architectures where content isn't siloed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎🏻 When to avoid GraphQL &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Project budget is a concern&lt;br&gt;
Hygraph sits in the $10K–60K/year range and delivers value only in specific architectural scenarios. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You're building a standard marketing site or blog&lt;br&gt;
This is overkill by definition.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Strapi – The open‑source path (new DB)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/strapi/strapi" rel="noopener noreferrer"&gt;Strapi on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strapi's Pros&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Strapi dominates the open‑source, JavaScript headless CMS space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual content‑type builder.&lt;/li&gt;
&lt;li&gt;Plugin marketplace and self‑hosting + Strapi Cloud options.
ecosystem that covers common needs (auth, media, SEO, etc.).&lt;/li&gt;
&lt;li&gt;Flexible deployment: self‑hostable or via Strapi Cloud for managed hosting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Strapi's Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core is free, but “must‑have” plugins often require per‑seat licensing.&lt;/li&gt;
&lt;li&gt;Clunky, slow, and non‑intuitive admin UI&lt;/li&gt;
&lt;li&gt;Poor documentation, unstable updates, and migration pain
A recurring theme is that the docs are often outdated, incomplete, or hard to follow, and major version updates (especially v4 → v5) can break builds, plugins, and schemas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👍🏻 When to use Strapi&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You’re building a new project with a separate database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You want a large community and pre‑built plugins (auth, media, SEO fields).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎🏻 When to avoid Strapi&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need NoSQL — MongoDB users are explicitly excluded
You expect zero ops overhead — self-hosting means your team owns uptime, backups, and upgrades&lt;/li&gt;
&lt;li&gt;You're mid-project and need to upgrade major versions — the "quick and dirty" reputation makes it harder to position as an enterprise solution to stakeholders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Directus – Wrap an existing database&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/directus/directus" rel="noopener noreferrer"&gt;Directus on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Directus wraps your existing SQL database (PostgreSQL, MySQL, SQLite) and auto‑generates REST and GraphQL APIs plus a built‑in admin UI on top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directus' Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Works with existing databases you don’t want to migrate, so you can keep your current schema and tooling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideal for internal tools and legacy‑system modernization, exposing old data with clean APIs and a modern UI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gives you REST and GraphQL APIs plus an admin panel out of the box, reducing the need to build custom back‑office tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open‑source core (BSL 1.1) that’s free for smaller organizations, with a clear path to commercial licensing when needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Directus' Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not ideal for green‑field projects — if you’re starting fresh with no existing database, Strapi usually offers a smoother setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-Editor UX is more technical — the interface is clean but feels SQL‑oriented and can confuse non‑technical marketers and content editors.&lt;/p&gt;

&lt;p&gt;-Limited deep UI customization — heavy customizations require Vue.js knowledge and are constrained by the SDK’s sandbox.&lt;/p&gt;

&lt;p&gt;-License complexity at scale — once your org exceeds the BSL revenue threshold, commercial licensing costs must be budgeted.&lt;/p&gt;

&lt;p&gt;-Operational overhead — self‑hosting means you own backups, scaling, and security, so it’s a poor fit if your team lacks DevOps capacity.&lt;/p&gt;

&lt;p&gt;👍🏻 When to use Directus&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Existing databases you don’t want to migrate.&lt;/li&gt;
&lt;li&gt;Internal tools and legacy‑system modernization.&lt;/li&gt;
&lt;li&gt;Exposing legacy data with an API and admin UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎🏻 When to avoid Directus&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're starting fresh with no existing database — 
Strapi is a better fit.&lt;/li&gt;
&lt;li&gt;Your editors need a polished, marketer-friendly UI — 
the interface is clean but SQL-oriented and can 
confuse non-technical users.&lt;/li&gt;
&lt;li&gt;You need deep UI customization — extensions require 
Vue.js knowledge and are sandboxed to the SDK.&lt;/li&gt;
&lt;li&gt;Your org is over the BSL revenue threshold — 
commercial licensing costs need to be factored in 
before you commit.&lt;/li&gt;
&lt;li&gt;You have no DevOps capacity — self-hosting means 
you own backups, scaling, and security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Make Your Choice Based on CMS Costs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Contentful&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The enterprise default: stable, compliant, and expensive once you start scaling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost&lt;/strong&gt;: $20K–150K+ / year&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Storyblok&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The marketer-friendly choice: excellent for visual editing, as long as your content model stays fairly standard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $5K–50K / year&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Sanity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The content operations platform: powerful for structured content, but it expects real investment in the editor experience.&lt;br&gt;
Cost: $5K–100K / year&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Payload&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The builder’s CMS: flexible, modern, and self-hostable, with no licensing ceiling — but it asks more from your developers upfront.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $0 + dev time&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Hygraph&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The GraphQL specialist: great when you truly need federation across systems, but easy to overbuy for simpler setups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $10K–60K / year&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Strapi&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The open-source path for new builds: familiar and flexible, with a strong community, but operational overhead still applies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; license + dev time&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Directus&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The database-first CMS: ideal when you already have an existing SQL database and want to expose it cleanly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; license + dev time&lt;/p&gt;

&lt;p&gt;Complexity grows.&lt;/p&gt;

&lt;p&gt;Editors hit the limits of their UI.&lt;/p&gt;

&lt;p&gt;Renewals hit your budget at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes While Choosing CMS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Overpaying for Contentful without using personalization, A/B testing, or Studio properly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Treating Sanity like a magic editor UX — it’s excellent only when you invest in the Studio; otherwise, marketers suffer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Picking Storyblok for a project that will grow into something app‑like, then facing big rework or migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reaching for Hygraph’s federation when they don’t actually have a multi‑backend data problem.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap-Up
&lt;/h2&gt;

&lt;p&gt;The best headless CMS is the one your team can implement well. Budget for the real costs — licenses, dev time, and ops — and focus on what you build on top of it, because that’s where the real competitive edge lives. &lt;/p&gt;

&lt;p&gt;If you need help choosing or setting up a CMS, feel free to &lt;a href="https://focusreactive.com/services/headless-cms-expert-agency/" rel="noopener noreferrer"&gt;reach out to headless CMS Agency&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>cms</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Google Tag Manager Loading Strategies in Next.js</title>
      <dc:creator>Sergey Labut</dc:creator>
      <pubDate>Fri, 13 Feb 2026 09:51:06 +0000</pubDate>
      <link>https://forem.com/focusreactive/google-tag-manager-loading-strategies-in-nextjs-3d0b</link>
      <guid>https://forem.com/focusreactive/google-tag-manager-loading-strategies-in-nextjs-3d0b</guid>
      <description>&lt;p&gt;&lt;strong&gt;Performance, Analytics Accuracy, and Risk-Aware Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google Tag Manager (GTM) can significantly affect Next.js apps. Choosing the right loading strategy requires balancing &lt;strong&gt;performance&lt;/strong&gt;, &lt;strong&gt;tracking reliability&lt;/strong&gt;, and &lt;strong&gt;implementation risk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This guide covers &lt;strong&gt;seven strategies&lt;/strong&gt;, with &lt;strong&gt;performance / analytics / complexity &amp;amp; risk&lt;/strong&gt; explained for each, including common mistakes and implementation examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why GTM Loading Matters in Next.js
&lt;/h2&gt;

&lt;p&gt;Next.js applications differ from traditional websites in important ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pages are server-rendered and then hydrated on the client&lt;/li&gt;
&lt;li&gt;JavaScript execution during hydration affects interaction metrics (&lt;strong&gt;INP&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Client-side navigation does not reload the page&lt;/li&gt;
&lt;li&gt;Page views must be tracked manually on route changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of this, GTM loading strategy directly affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core Web Vitals&lt;/strong&gt; (especially INP and LCP)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hydration speed and responsiveness&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analytics accuracy and attribution&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Balanced Approach – After-Interactive Loading (Recommended Default)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; Good&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Analytics:&lt;/strong&gt; High&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Complexity / Risk:&lt;/strong&gt; Low&lt;/p&gt;
&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GTM loads after the page becomes interactive using &lt;code&gt;strategy="afterInteractive"&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Hydration is not blocked, but GTM may execute while hydration is still finishing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Forgetting SPA page view tracking&lt;/li&gt;
&lt;li&gt;Assuming &lt;code&gt;afterInteractive&lt;/code&gt; alone guarantees good INP&lt;/li&gt;
&lt;li&gt;Leaving GTM’s default page view trigger enabled and causing duplicates
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GTM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_GTM_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GTM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Script&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gtm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;afterInteractive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
          // Ensure dataLayer exists before GTM loads
          window.dataLayer = window.dataLayer || [];

          (function(w,d,s,l,i){
            w[l]=w[l]||[];
            w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
            var f=d.getElementsByTagName(s)[0],
                j=d.createElement(s),
                dl=l!='dataLayer'?'&amp;amp;l='+l:'';
            j.async=true;
            j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
            f.parentNode.insertBefore(j,f);
          })(window,document,'script','dataLayer','&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;GTM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;');
        `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;SPA page view tracking — required&lt;br&gt;
Because Next.js uses client-side routing, page views must be sent manually on route changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you do this, disable GTM’s default Page View trigger to avoid duplicates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPA page view tracking — Pages Router&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;usePageViews&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleRouteChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page_view&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;page_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;page_location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;routeChangeComplete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleRouteChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;off&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;routeChangeComplete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleRouteChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPA page view tracking — App Router&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSearchParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PageViewTracker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePathname&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSearchParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`?&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page_view&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;page_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pagePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;page_location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Max Tracking – Early Loading (Before-Interactive)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Moderate / Risky&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: Maximum&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity / Risk&lt;/strong&gt;: Low&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GTM loads before React hydration starts using beforeInteractive.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beforeInteractive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://www.googletagmanager.com/gtm.js?id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;GTM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;INP regressions caused by long GTM tasks&lt;/li&gt;
&lt;li&gt;Duplicate page views when default GTM page view triggers are combined with SPA tracking&lt;/li&gt;
&lt;li&gt;Assuming “early load” only affects LCP (INP is usually the real casualty)&lt;/li&gt;
&lt;li&gt;Letting marketing add heavy tags without performance review&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Marketing-heavy pages&lt;/li&gt;
&lt;li&gt;Conversion funnels where attribution accuracy is critical&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Performance-First – Lazy Loading (After Page Fully Loads)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Very Good&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity / Risk&lt;/strong&gt;: Low&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GTM loads only after the browser load event.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gtm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lazyOnload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://www.googletagmanager.com/gtm.js?id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;GTM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Assuming Lighthouse ignores GTM entirely&lt;/li&gt;
&lt;li&gt;Missing page views from short sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Content-heavy sites&lt;/li&gt;
&lt;li&gt;SEO-driven pages where analytics is helpful but not critical&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Extreme Performance – Interaction-Based Loading with Event Buffering
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Excellent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: Medium–High&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity / Risk&lt;/strong&gt;: Medium&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GTM loads only after user interaction. Important events are buffered until GTM is ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Users who never interact are not tracked&lt;/li&gt;
&lt;li&gt;Event buffer flushed too late or never&lt;/li&gt;
&lt;li&gt;Overengineering simple setups
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example buffering logic&lt;/span&gt;
&lt;span class="c1"&gt;// Initialize dataLayer early&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bufferedEvents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="c1"&gt;// Track events before GTM is ready&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;trackEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gtmReady&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bufferedEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Call this when GTM finishes loading&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onGtmReady&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bufferedEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gtmReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Conditional Loading – Consent, Region, or Route-Based
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Good&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity / Risk&lt;/strong&gt;: Medium–High&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;p&gt;GTM is loaded only if certain conditions are met (for example, user consent).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasConsent&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GTM&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Inconsistent analytics across regions&lt;/li&gt;
&lt;li&gt;Consent state not persisted correctly&lt;/li&gt;
&lt;li&gt;Forgetting to update rules for new routes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GDPR-heavy environments&lt;/li&gt;
&lt;li&gt;Multi-region or multi-brand sites&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Server-Side GTM – High Reliability, High Complexity
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Good&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: Very High&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity / Risk&lt;/strong&gt;: High&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The browser sends events to your server, which forwards them to GTM and analytics tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Poor client/server event parity&lt;/li&gt;
&lt;li&gt;Added latency without batching&lt;/li&gt;
&lt;li&gt;Underestimating maintenance cost&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;High-traffic applications&lt;/li&gt;
&lt;li&gt;Long-term analytics infrastructure&lt;/li&gt;
&lt;li&gt;The user's browser extensions are blocking analytics&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Web Worker GTM (Partytown) – Maximum Frontend Performance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Excellent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: High&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity / Risk&lt;/strong&gt;: High&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this means
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GTM runs in a Web Worker using Partytown, keeping heavy scripts off the main thread.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;DOM-dependent tags silently failing&lt;/li&gt;
&lt;li&gt;Missing forwarded APIs&lt;/li&gt;
&lt;li&gt;Difficult debugging
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Partytown&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@builder.io/partytown/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Partytown&lt;/span&gt; &lt;span class="nx"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataLayer.push&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Script&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/partytown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://www.googletagmanager.com/gtm.js?id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;GTM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or just&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://www.googletagmanager.com/gtm.js?id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;GTM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;worker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Recommendations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default choice&lt;/strong&gt;: After-Interactive loading + manual SPA page views&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximum analytics reliability&lt;/strong&gt;: Early loading or Server-Side GTM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extreme performance&lt;/strong&gt;: Interaction-based loading with buffering or Partytown&lt;/li&gt;
&lt;li&gt;Regularly audit GTM tags — loading strategy alone won’t fix heavy scripts&lt;/li&gt;
&lt;li&gt;Always validate SPA tracking when using the App Router&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Performance Impact&lt;/th&gt;
&lt;th&gt;Tracking Reliability&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Recommended For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;After Interactive (Recommended Default)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;High (manual SPA page views required)&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Most Next.js apps; balanced performance &amp;amp; analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Before Interactive (Early Load)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Marketing-heavy pages; critical attribution tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lazy Onload (After Page Fully Loads)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very Good&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Content-focused or SEO-driven pages; analytics not critical&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interaction-Based Load&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Blogs or informational pages; extreme performance priority&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interaction with Event Buffering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;td&gt;Performance-first sites needing reliable early tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Conditional Load&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;td&gt;GDPR-heavy, multi-region, or multi-brand setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Server-Side GTM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;High-traffic apps; long-term analytics &amp;amp; reliability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web Worker (Partytown)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Performance-critical sites; heavy third-party scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>analytics</category>
      <category>nextjs</category>
      <category>performance</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Automating your content with Sanity's Agent Actions, Functions &amp; Blueprints</title>
      <dc:creator>Eugene Boruhov</dc:creator>
      <pubDate>Mon, 18 Aug 2025 17:38:07 +0000</pubDate>
      <link>https://forem.com/focusreactive/automating-your-content-with-sanitys-agent-actions-functions-blueprints-59fg</link>
      <guid>https://forem.com/focusreactive/automating-your-content-with-sanitys-agent-actions-functions-blueprints-59fg</guid>
      <description>&lt;p&gt;For a long time, we collectively treated the CMS as a "content store" - a convenient database with a  UI where non-developers could edit text and images without, as we’d say, a pain in the ass. Its job was to hold things.&lt;/p&gt;

&lt;p&gt;But over the past few years, Sanity has been aggressively pushing the boundaries of that definition. They transitioned from a simple content store into a true &lt;strong&gt;Content Operating System&lt;/strong&gt;. It became a hub for structured data you can model, query, and connect in powerful new ways.&lt;/p&gt;

&lt;p&gt;Yet, for all this progress, we as developers still hit a ceiling. When it came to a crucial part of the modern stack, automation, we had to look elsewhere. We found ourselves reaching for Vercel or Netlify functions to handle tasks that felt like they should belong inside Sanity. We needed to enrich content on publish, trigger a validation workflow or sync data with another service.&lt;/p&gt;

&lt;p&gt;This approach worked, but it always felt like a workaround. It created a divide, forcing us to manage fragmented architectures and spread authentication tokens across platforms. Our logic lived in one place, and our content in another.&lt;/p&gt;

&lt;p&gt;With the &lt;a href="https://www.sanity.io/blog/what-s-new-june-2025" rel="noopener noreferrer"&gt;Spring Release&lt;/a&gt;, that is no longer the case. Sanity has finally delivered the missing piece. The introduction of native AI and serverless capabilities means the platform is no longer just a sophisticated content store - it has become a truly mature &lt;strong&gt;Content Engine&lt;/strong&gt;. The logic and the content can now live together, closing the gap and fundamentally changing what's possible within a single, unified system.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI &amp;amp; Automation Inside Sanity
&lt;/h2&gt;

&lt;p&gt;So, what powers this new Content Engine? Sanity has delivered a trio of interconnected features that together create a complete and native ecosystem for automation. While still in their early stages, they already form a powerful foundation.&lt;/p&gt;

&lt;p&gt;Think of it as a complete toolkit with three core components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agent Actions (AI brains).&lt;/strong&gt; This is the intelligence layer. Agent Actions are schema-aware AI instructions that can programmatically generate, transform, and translate your content. They aren't just simple text prompts - they understand your content models, which allows for incredibly precise and structured results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functions (automation engine).&lt;/strong&gt; This is the serverless power we've been waiting for. Functions are event-driven pieces of code that live right inside your Sanity project and react to content changes. Triggered by content operations like ⁠publish, ⁠create, or ⁠delete, these functions spring into action, running your code and eliminating the need for external webhooks or authentication boilerplate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blueprints (infrastructure scaffolding).&lt;/strong&gt; This is how you manage your new serverless capabilities using an infrastructure-as-code approach. Blueprints allow you to declaratively define, configure, and deploy your Functions, ensuring your automation setup is version-controlled, repeatable, and easy to manage from the command line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The true power of this toolkit lies in how these components work together. You can use an &lt;strong&gt;Agent Action&lt;/strong&gt; to define an AI task, then invoke it from a &lt;strong&gt;Function&lt;/strong&gt; that triggers when a document is published, all managed and deployed via a &lt;strong&gt;Blueprint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the integrated system that ends the workarounds. Let's break it down, starting with the AI brains of the operation: Agent Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Actions
&lt;/h2&gt;

&lt;p&gt;The core of Sanity's new AI capabilities is powered by &lt;strong&gt;Agent Actions&lt;/strong&gt;. Think of them as an intelligent, schema-aware layer that sits on top of your content. They know what a "blog post" is in your project, what fields it has, and how a "product" might reference a "category." This awareness allows them to perform tasks with a level of precision that was previously impossible without complex, hand-written code.&lt;/p&gt;

&lt;p&gt;The Agent Actions are broken down into four distinct capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generate:&lt;/strong&gt; This is your creative engine. It goes beyond just text, allowing you to create entire documents from scratch, complete with structured data and even &lt;strong&gt;generated images&lt;/strong&gt;. It's perfect for drafting a blog post from a title, populating a product description, or creating visual assets that match your content's context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transform:&lt;/strong&gt; This is your intelligent editor. Instead of crude find-and-replace operations, Transform can modify existing documents with nuance. Use it to change an article's tone from formal to casual, summarize a long passage into a concise description, or update fields while preserving the integrity of the rest of the document.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translate:&lt;/strong&gt; Purpose-built for localization, this action handles both document-level and field-level translation. It's smart enough to protect brand names, technical terms, or other phrases you define, ensuring your core messaging remains consistent across languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt:&lt;/strong&gt; This is your direct line to an LLM, but with your Sanity content as the built-in context. It allows you to ask questions, analyze data, or run custom instructions against your documents without having to pipe the content to an external service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These powerful actions are already being integrated across the Sanity ecosystem. The recently introduced &lt;a href="https://www.sanity.io/blog/introducing-sanity-model-context-protocol-server" rel="noopener noreferrer"&gt;&lt;strong&gt;Sanity MCP&lt;/strong&gt;&lt;/a&gt;, which allows AI coding assistants to interact with Sanity projects, uses this new Agent Actions API under the hood.&lt;/p&gt;

&lt;p&gt;For developers, getting started is straightforward. The actions are exposed as a new dedicated scope within the familiar &lt;code&gt;@sanity/client&lt;/code&gt;, making them easy to call from anywhere you can run JavaScript. But how do we put them on autopilot? For that, we need an engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions &amp;amp; Blueprints
&lt;/h2&gt;

&lt;p&gt;An AI brain is powerful, but its true potential is unlocked when it can act on its own. This is where &lt;strong&gt;Sanity Functions&lt;/strong&gt; come in - the serverless engine we've been waiting for. This is the feature that finally allows us to stop outsourcing our automation logic to external platforms.&lt;/p&gt;

&lt;p&gt;Functions are event-driven, single-purpose pieces of code that live directly within your Sanity project. They respond to content changes, such as publish, update, or delete - and execute your logic right on Sanity's infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions CLI
&lt;/h3&gt;

&lt;p&gt;Sanity has built a complete local-first workflow around Functions. The CLI provides a robust development environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;sanity functions dev&lt;/code&gt; to run a local emulator for real-time development&lt;/li&gt;
&lt;li&gt;Simulate trigger events with &lt;code&gt;⁠sanity functions test&lt;/code&gt;. It lets you invoke your function locally with a mock payload by passing either a local JSON file or the ID of a document in your dataset&lt;/li&gt;
&lt;li&gt;When you need to debug a deployed function, you can stream its logs directly to your terminal with &lt;code&gt;sanity functions logs&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Automation with GROQ Delta Functions
&lt;/h3&gt;

&lt;p&gt;What makes Sanity Functions particularly powerful is their deep integration with the content layer. Using special &lt;a href="https://www.sanity.io/docs/specifications/groq-functions#a64594a50318" rel="noopener noreferrer"&gt;&lt;strong&gt;GROQ Delta Functions&lt;/strong&gt;&lt;/a&gt;, your code can understand not just the current state of a document, but precisely &lt;strong&gt;what changed&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;before()&lt;/code&gt; and &lt;code&gt;after()&lt;/code&gt; give you snapshots of the document before and after the triggering event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delta::changedAny()&lt;/code&gt; and &lt;code&gt;delta::changedOnly()&lt;/code&gt; let you check if specific fields were modified. Did the title change? Or &lt;em&gt;only&lt;/em&gt; the title?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delta::operation()&lt;/code&gt; tells you if the document was created, updated, or deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can build workflows that only run when a specific field is changed or when a document is first created, preventing unnecessary executions and complex boilerplate code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure as Code with Blueprints
&lt;/h3&gt;

&lt;p&gt;A powerful engine needs a robust control system. &lt;strong&gt;Blueprints&lt;/strong&gt; provide exactly that. They bring the discipline of infrastructure-as-code to your Sanity project, allowing you to define and manage your Functions (and other future Sanity resources) in a version-controlled file: &lt;code&gt;sanity.blueprint.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The workflow is clean and mirrors best practices from modern DevOps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define&lt;/strong&gt;: you declare your functions and their triggers in the blueprint file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt;: run ⁠&lt;code&gt;sanity blueprints plan&lt;/code&gt; to see what changes will be made to your cloud environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt;: execute ⁠&lt;code&gt;sanity blueprints deploy&lt;/code&gt; to push your functions to Sanity's infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage&lt;/strong&gt;: you can view info with &lt;code&gt;sanity blueprints info&lt;/code&gt; or tear down resources with &lt;code&gt;⁠sanity blueprints destroy&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach makes your automation setup repeatable, reviewable, and easy to manage as a team. And for a quick start, Sanity has provided a library of &lt;a href="https://www.sanity.io/exchange/type=recipes/by=sanity" rel="noopener noreferrer"&gt;Recipes&lt;/a&gt; with pre-built patterns for common use cases.&lt;/p&gt;

&lt;p&gt;Now we have the full picture: the AI brains with Agent Actions and the automation engine with Functions, all managed via Blueprints. Now, let’s put it all together and build something real.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Theory to Practice
&lt;/h2&gt;

&lt;p&gt;This is where the new toolkit moves from a list of features to a powerful, integrated system. At FocusReactive, we immediately used these tools to tackle a common content challenge: generating relevant, high-quality FAQ sections for our technical blog posts.&lt;/p&gt;

&lt;p&gt;Here’s how we built it, showcasing how you can use Agent Actions both manually with a UI trigger and automatically in a hands-off workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  FAQ Schema
&lt;/h3&gt;

&lt;p&gt;First things first, we need a home for our FAQ content. We'll set up a pretty standard schema with types for the FAQ section and its individual items:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// schemas/blog/postFaq.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postFaq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Post FAQ&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FAQ Items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postFaqItem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// schemas/blog/postFaqItem.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;defaul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postFaqItem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Post FAQ Item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;richText&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Custom Studio Action
&lt;/h3&gt;

&lt;p&gt;First, we wanted to give editors manual control. What if they want to regenerate an FAQ for an already-published post? This is a perfect use case for calling an Agent Action directly from a custom &lt;strong&gt;Document Action&lt;/strong&gt; in the Studio.&lt;/p&gt;

&lt;p&gt;This demonstrates the power of the Agent Action API on its own - no serverless function needed.&lt;/p&gt;

&lt;p&gt;We created a custom action that appears in the document's dropdown menu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// actions/GenerateFaqAction.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;DocumentActionComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;DocumentActionDescription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;DocumentActionProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;useClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sanity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RobotIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sanity/icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GenerateFaqAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DocumentActionComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DocumentActionProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;DocumentActionDescription&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isGenerating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsGenerating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agentClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleGenerateFaq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setIsGenerating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;draft&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;published&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ No document data available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🔄 Regenerating FAQ for: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agentClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🗑️ Existing FAQ cleared for: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agentClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;schemaId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_.schemas.default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;targetDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="c1"&gt;// The instruction below is a simplified example. In a real-world application,&lt;/span&gt;
                &lt;span class="c1"&gt;// you could provide much more detailed requirements, including rules for&lt;/span&gt;
                &lt;span class="c1"&gt;// tone of voice, brand guidelines, or specific formatting for the output&lt;/span&gt;
                &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Generate 5-7 relevant FAQ items for this blog post about $blogTitle.
Create questions that readers would commonly ask about this technical topic.
Provide comprehensive, helpful answers based on the blog content ($blogContent) and description ($blogDescription).
Make the questions specific and actionable.
Focus on practical implementation details, common issues, and best practices.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;instructionParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;blogTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="na"&gt;blogContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="na"&gt;blogDescription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✅ FAQ regenerated successfully for: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✅ FAQ generated successfully for "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"!&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;nThe document has been updated.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ Error generating FAQ:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`❌ Error generating FAQ: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setIsGenerating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isGenerating&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Generating FAQ...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Generate FAQ&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RobotIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isGenerating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;onHandle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handleGenerateFaq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Generate FAQ section using AI based on the blog content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in place, an editor can now click a button in the Studio, and the AI will generate and populate the FAQ field on demand.&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.amazonaws.com%2Fuploads%2Farticles%2F3zf0kyzkfxqilwpi6llp.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.amazonaws.com%2Fuploads%2Farticles%2F3zf0kyzkfxqilwpi6llp.png" alt="Custom " width="800" height="865"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Triggering on Publish
&lt;/h3&gt;

&lt;p&gt;Now for the magic. We want to generate the FAQ automatically when a new post is published. This is where Functions and Blueprints come into play.&lt;/p&gt;

&lt;p&gt;We first define our workflow in &lt;code&gt;sanity.blueprint.ts&lt;/code&gt;. We're telling Sanity to run a function named &lt;code&gt;generate-faq&lt;/code&gt; only on the publish event, and only for documents that are posts and don't already have an FAQ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// sanity.blueprint.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineBlueprint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineDocumentFunction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sanity/blueprints&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineBlueprint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;defineDocumentFunction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generate-faq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;publish&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_type == "post" &amp;amp;&amp;amp; !defined(faq)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;projection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{_id, title}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we create the function itself. This code will look very similar to our custom action, but instead of being triggered by a user click, it's triggered by the publish event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// functions/generate-faq/index.ts &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;documentEventHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sanity/functions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sanity/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;documentEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Required for Agent Actions&lt;/span&gt;
        &lt;span class="na"&gt;useCdn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🚀 FAQ generation triggered for: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ Missing _id in event data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🤖 Generating FAQ using AI for: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;schemaId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_.schemas.fr-website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;targetDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`drafts.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Create/update draft version instead of published&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Generate 5-7 relevant FAQ items for this blog post about $blogTitle.
Create questions that readers would commonly ask about this technical topic.
Provide comprehensive, helpful answers based on the blog content ($blogContent) and description ($blogDescription).
Make the questions specific and actionable.
Focus on practical implementation details, common issues, and best practices.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;instructionParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;blogTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;blogContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;blogDescription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;noWrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Don't write when testing locally&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✅ Successfully generated FAQ for: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`❌ Error generating FAQ for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy and Go
&lt;/h3&gt;

&lt;p&gt;Finally, we deploy our automation with a single command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sanity blueprints deploy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And now our workflow is complete. We have an on-demand, manual trigger inside the Studio and a fully automated, hands-off process for new content. This dual approach perfectly illustrates the flexibility of Sanity's new toolkit - you can meet editors where they are, while also building powerful, invisible automations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The June 2025 update is more than just another set of features, it represents a fundamental shift in what we can expect from a content platform. At FocusReactive, we couldn't be more excited about this evolution.&lt;/p&gt;

&lt;p&gt;We are already putting this knowledge into practice and are committed to using these capabilities to empower our clients. Our goal is to equip their content managers with the best possible tools, creating intuitive, AI-assisted workflows that automate repetitive tasks and unlock new creative potential.&lt;/p&gt;

&lt;p&gt;A huge thank you to the entire Sanity team for their incredible vision and execution. It feels like every month they deliver something new and exciting that moves the entire industry forward. We can't wait to build with this and see what comes next.&lt;/p&gt;

&lt;p&gt;To give you a concrete example of the output, you can see the AI-generated FAQ section for this article right below.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>news</category>
    </item>
    <item>
      <title>How to Optimize Vercel Costs</title>
      <dc:creator>Alex Hramovich</dc:creator>
      <pubDate>Tue, 26 Nov 2024 09:11:16 +0000</pubDate>
      <link>https://forem.com/focusreactive/how-to-optimize-vercel-costs-bd</link>
      <guid>https://forem.com/focusreactive/how-to-optimize-vercel-costs-bd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;👉 Read the full article &lt;a href="https://focusreactive.com/vercel-cost-optimization/?source=devto" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vercel is a go to hosting platform for Next.js projects. But let’s face it — &lt;strong&gt;hosting costs can add up quickly&lt;/strong&gt;. Whether you're on the PRO plan or considering the Enterprise tier, it's essential to ensure you're not overpaying for features you don’t need.&lt;/p&gt;

&lt;h2&gt;
  
  
  PRO vs Enterprise: The Smarter Choice
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PRO&lt;/strong&gt; Plan ($20/user/month): Offers generous resources like 1TB of bandwidth and full access to Edge Middleware. For most teams, this plan is enough, and additional bandwidth or serverless execution time can be purchased without committing to the Enterprise tier. Scaling this way often costs significantly less than jumping to Enterprise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise&lt;/strong&gt; Plan ($3,500+/month): Tailored for large-scale organizations requiring features like SSO, static IPs, and SLAs. However, many teams can replicate similar benefits by optimizing their PRO plan setup and buying extra resources when needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Why PRO with Add-Ons Makes Sense ?
&lt;/h5&gt;

&lt;p&gt;Instead of an enterprise monthly commitment, purchasing additional resources under the PRO plan keeps costs predictable and aligned with your actual usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Consider Self-Hosting
&lt;/h2&gt;

&lt;p&gt;If you’ve outgrown the PRO plan but the Enterprise plan feels like overkill, self-hosting can be a strong alternative:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost Efficiency: Host for $500–$1,000/month with platforms like Cloudflare or Render, gaining flexibility and control over your infrastructure.&lt;/li&gt;
&lt;li&gt;Improved Performance: Eliminate serverless bottlenecks with dedicated servers tailored for dynamic applications.&lt;/li&gt;
&lt;li&gt;Custom Caching Strategies: Optimize your setup beyond what’s possible with Vercel alone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;For most teams, the PRO plan with add-ons is the most cost-effective solution. It provides scalability and control without the significant expense of Enterprise. For advanced needs, self-hosting can offer a tailored and budget-friendly alternative.&lt;/p&gt;

</description>
      <category>vercel</category>
      <category>nextjs</category>
      <category>hosting</category>
    </item>
    <item>
      <title>Next.JS CMS — Top choices in 2024</title>
      <dc:creator>Aleksei Zhilyuk</dc:creator>
      <pubDate>Thu, 31 Oct 2024 09:38:54 +0000</pubDate>
      <link>https://forem.com/focusreactive/nextjs-cms-top-choices-in-2024-o38</link>
      <guid>https://forem.com/focusreactive/nextjs-cms-top-choices-in-2024-o38</guid>
      <description>&lt;h2&gt;
  
  
  WHY A HEADLESS CMS FOR YOUR NEXT.JS PROJECT?
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://focusreactive.com/headless-cms-expert-agency/" rel="noopener noreferrer"&gt;headless CMS&lt;/a&gt; serves as a backend-only content repository that provides content via an API, making it displayable on any device. This approach separates content management from its presentation, which is particularly advantageous for &lt;a href="https://focusreactive.com/next-js-expert-agency/" rel="noopener noreferrer"&gt;NextJS projects&lt;/a&gt;. By using a headless CMS, developers can fully leverage Next.js features like &lt;a href="https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering" rel="noopener noreferrer"&gt;server-side rendering&lt;/a&gt; and &lt;a href="https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation" rel="noopener noreferrer"&gt;static site generation&lt;/a&gt;, optimizing both SEO and performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  ADVANTAGES OF INTEGRATING A HEADLESS CMS WITH NEXTJS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/next-js-expert-agency/" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt; is a powerful framework for building efficient and scalable web applications. &lt;/p&gt;

&lt;h3&gt;
  
  
  Here are specific advantages of integrating a headless CMS with Next.js:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Performance&lt;/strong&gt;: Next.js excels in fast page loads through features like incremental static regeneration and server-side rendering. A headless CMS complements this by efficiently delivering content through APIs, reducing load times and server strain. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved SEO:&lt;/strong&gt; Next.js facilitates SEO-friendly site structures, which can be enhanced with a headless CMS that supports SEO optimization through metadata management and structured content delivery.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; As your project grows, the need to handle more traffic and content efficiently becomes crucial. A headless CMS can scale independently from the front-end, making it easier to manage large volumes of data without impacting the front-end performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility in Development:&lt;/strong&gt; Developers can use their preferred front-end technologies and frameworks without constraints imposed by traditional CMS platforms. This means you can use the latest Next.js features and updates as soon as they are released.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Better Security and Stability:&lt;/strong&gt; By decoupling the CMS from the presentation layer, security is enhanced as potential vulnerabilities in the CMS do not directly expose the front-end to security risks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Streamlined Workflows:&lt;/strong&gt; A headless CMS can support multiple front-ends simultaneously, which is advantageous for projects aiming to deliver content across different platforms and devices.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These benefits make a headless CMS an excellent match for Next.js, ensuring developers can build modern, secure, and high-performing applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/contentful-expert-agency/" rel="noopener noreferrer"&gt;Contentful&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2F0e2t6h5pm7ofa3opdpgc.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.amazonaws.com%2Fuploads%2Farticles%2F0e2t6h5pm7ofa3opdpgc.png" alt="Contentful logo" width="800" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/contentful-cms-overview/" rel="noopener noreferrer"&gt;Contentful&lt;/a&gt; is a leader in the headless CMS market, offering a comprehensive suite of features that cater to developers and content creators alike.&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.amazonaws.com%2Fuploads%2Farticles%2Fb0og6btorbin2on62acz.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.amazonaws.com%2Fuploads%2Farticles%2Fb0og6btorbin2on62acz.png" alt="Contentful interface" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration:&lt;/strong&gt; 
With its React SDK, integrating Contentful with Next.js projects is a breeze, providing a seamless workflow for developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; 
Contentful's content modeling capabilities are unmatched, allowing for the creation of complex content structures tailored to any project's needs. Its environment feature supports staging and production setups, enabling a robust development workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; 
Its Delivery API is built for speed, ensuring that content loads quickly, which is crucial for maintaining high performance in Next.js applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Support:&lt;/strong&gt; 
A vast community and extensive documentation mean that developers can easily find solutions or get help when needed. Contentful also offers professional support services for enterprise users, ensuring that any issues can be swiftly addressed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.contentful.com/pricing/?tab=platform" rel="noopener noreferrer"&gt;Contentful pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic:&lt;/strong&gt; $300/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Premium:&lt;/strong&gt; Custom pricing&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fb4xtxcr7h85o3mik616w.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.amazonaws.com%2Fuploads%2Farticles%2Fb4xtxcr7h85o3mik616w.png" alt="Conentful pricing" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/storyblok-expert-agency/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fqt7its9kecfgrxrug21e.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.amazonaws.com%2Fuploads%2Farticles%2Fqt7its9kecfgrxrug21e.png" alt="Storyblok logo" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/storyblok-cms-overview/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt; stands out for its visual editor and block-based approach to content management, making it particularly friendly for both developers and content creators.&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.amazonaws.com%2Fuploads%2Farticles%2Fakrq23bs9ycqp4h6kjio.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.amazonaws.com%2Fuploads%2Farticles%2Fakrq23bs9ycqp4h6kjio.png" alt="Storyblok interface" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration:&lt;/strong&gt; 
Storyblok's component-based approach integrates seamlessly with Next.js, allowing developers to map components in Storyblok to React components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; 
The platform offers incredible flexibility through its block-based content system, enabling creators to build dynamic, rich content experiences without needing developer intervention for layout changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; 
Storyblok's content delivery is optimized for speed, utilizing a CDN to ensure content is served quickly to Next.js applications globally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Support:&lt;/strong&gt; 
Storyblok has a rapidly growing community and provides extensive documentation, tutorials, and customer support, making it easy for developers to get started and find help when needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.storyblok.com/pricing" rel="noopener noreferrer"&gt;Storyblok pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community Plan:&lt;/strong&gt; Free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entry Plan:&lt;/strong&gt; €99/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; €3299/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Plus:&lt;/strong&gt; Custom pricing&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fvcq52nn164eqqk710l4t.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.amazonaws.com%2Fuploads%2Farticles%2Fvcq52nn164eqqk710l4t.png" alt="Storyblok pricing" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/sanity-expert-agency/" rel="noopener noreferrer"&gt;Sanity.io&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2F4jlmudmgnyvi1avyy8p1.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.amazonaws.com%2Fuploads%2Farticles%2F4jlmudmgnyvi1avyy8p1.png" alt="Sanity logo" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/sanity-cms-overview/" rel="noopener noreferrer"&gt;Sanity.io&lt;/a&gt; differentiates itself with its real-time content editing experience and a highly customizable content studio.&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.amazonaws.com%2Fuploads%2Farticles%2Fv87yn6x7xr7ucc6egnt5.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.amazonaws.com%2Fuploads%2Farticles%2Fv87yn6x7xr7ucc6egnt5.png" alt="Sanity interface" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration:&lt;/strong&gt; The platform offers excellent support for React and Next.js, including real-time preview capabilities that are invaluable during development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; The customizable content studio and the innovative portable text feature provide developers and content editors with the power to embed rich content structures directly within textual content, making it highly versatile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Sanity.io leverages GROQ and GraphQL for data querying, offering efficient and flexible options for fetching data, which enhances app performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Support:&lt;/strong&gt; With a vibrant community and plenty of guides, finding help or inspiration is easy. Sanity.io also hosts regular developer streams and community events, fostering a strong sense of community.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.sanity.io/pricing" rel="noopener noreferrer"&gt;Sanity pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Growth:&lt;/strong&gt; $15/month per user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; Custom pricing&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Flbtesxrevj4m3t6gr1u5.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.amazonaws.com%2Fuploads%2Farticles%2Flbtesxrevj4m3t6gr1u5.png" alt="Sanity Pricing" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/directus-expert-agency/" rel="noopener noreferrer"&gt;Directus&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2F26tyt9ag8qa5lx8899b3.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.amazonaws.com%2Fuploads%2Farticles%2F26tyt9ag8qa5lx8899b3.png" alt="Directus logo" width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/directus-cms-overview/" rel="noopener noreferrer"&gt;Directus&lt;/a&gt; is an open-source option that stands out for its API-driven approach and extensive customization capabilities.&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.amazonaws.com%2Fuploads%2Farticles%2Fyragsn9n1hfozdbhcnku.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.amazonaws.com%2Fuploads%2Farticles%2Fyragsn9n1hfozdbhcnku.png" alt="Directus interface" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration:&lt;/strong&gt; 
Offering both RESTful API and GraphQL endpoint, Directus provides versatile integration options with Next.js, catering to different developer preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; 
Being open-source, Directus allows for deep customization, from the admin UI to the underlying database schema. This flexibility ensures that developers can tailor the CMS to fit the project's exact requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; 
While performance is generally excellent, it can vary depending on how the Directus backend is configured. However, the ability to directly query the database ensures minimal overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Support:&lt;/strong&gt; 
The growing open-source community around Directus is a rich resource for troubleshooting and inspiration. Directus also offers dedicated support plans for businesses requiring more personalized assistance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://directus.io/pricing" rel="noopener noreferrer"&gt;Directus pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted:&lt;/strong&gt; License required &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Professional Cloud:&lt;/strong&gt; $99/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Cloud:&lt;/strong&gt; Custom&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fmibfxhzueir57xpcs7e3.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.amazonaws.com%2Fuploads%2Farticles%2Fmibfxhzueir57xpcs7e3.png" alt="Directus pricing" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://payloadcms.com/" rel="noopener noreferrer"&gt;Payload CMS&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fn3izx4y4k446k1u20cet.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.amazonaws.com%2Fuploads%2Farticles%2Fn3izx4y4k446k1u20cet.png" alt="Payload CMS logo" width="500" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/payload-cms-overview" rel="noopener noreferrer"&gt;Payload CMS&lt;/a&gt; is a newer entrant in the headless CMS space but has quickly gained attention for its developer-focused features and flexibility.&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.amazonaws.com%2Fuploads%2Farticles%2Faye9h7feroq1v61yi1ir.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.amazonaws.com%2Fuploads%2Farticles%2Faye9h7feroq1v61yi1ir.png" alt="Payload CMS interface" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration:&lt;/strong&gt; 
Designed with developers in mind, Payload CMS offers full TypeScript support and a highly customizable admin UI, making it a perfect match for Next.js applications that utilize TypeScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; 
It stands out for its deep customization capabilities, allowing full control over the admin UI and the APIs. This level of customization makes it possible to tailor every aspect of the CMS to the project's needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; 
Payload CMS is optimized for performance, featuring efficient data handling and delivery mechanisms. This focus on performance is evident in the speed and responsiveness of Next.js applications powered by Payload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Support:&lt;/strong&gt; 
Although the community is currently smaller, it's rapidly growing. The developers are actively involved in expanding the documentation and offering support, ensuring users have the resources they need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://payloadcms.com/cloud-pricing" rel="noopener noreferrer"&gt;Payload CMS pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard:&lt;/strong&gt; $35/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro:&lt;/strong&gt; $199/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; Custom&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fix54y39mw4ejl0jeydzj.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.amazonaws.com%2Fuploads%2Farticles%2Fix54y39mw4ejl0jeydzj.png" alt="Payload CMS pricing" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://prismic.io/" rel="noopener noreferrer"&gt;Prismic&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fh0lw8gmrsxjusiju724e.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.amazonaws.com%2Fuploads%2Farticles%2Fh0lw8gmrsxjusiju724e.png" alt="Prismic logo" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/prismic-cms-overview" rel="noopener noreferrer"&gt;Prismic&lt;/a&gt; offers a straightforward and developer-friendly approach to content management, making it a popular choice for many Next.js projects.&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.amazonaws.com%2Fuploads%2Farticles%2Fqagiyxav4eec9usquox5.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.amazonaws.com%2Fuploads%2Farticles%2Fqagiyxav4eec9usquox5.png" alt="Prismic interface" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Integration:&lt;/strong&gt; Its REST API and support for webhooks make integrating Prismic with Next.js straightforward, facilitating both static site generation and server-side rendering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; The slices feature allows for building dynamic page layouts with ease, offering developers and content creators a flexible and powerful tool for designing content-rich pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Prismic's use of a CDN for content delivery ensures fast load times, a critical factor for maintaining high performance in web applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Support:&lt;/strong&gt; While Prismic has good documentation and support, its community may not be as large as some others, but the quality of support and resources is high.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://prismic.io/pricing" rel="noopener noreferrer"&gt;Prismic pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free:&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Starter:&lt;/strong&gt; $10/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small:&lt;/strong&gt; $25/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medium:&lt;/strong&gt; $150/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platinum:&lt;/strong&gt; $675/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; Custom&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fyqi4f321qildokatqnnz.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.amazonaws.com%2Fuploads%2Farticles%2Fyqi4f321qildokatqnnz.png" alt="Prismic pricing" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/ghost-cms-overview/" rel="noopener noreferrer"&gt;Ghost CMS&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fy1r9bbz238uurpa86x3y.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.amazonaws.com%2Fuploads%2Farticles%2Fy1r9bbz238uurpa86x3y.png" alt="Ghost logo" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/ghost-cms-overview/" rel="noopener noreferrer"&gt;Ghost CMS&lt;/a&gt; is an open-source platform focused on blogging and online publishing. Built on Node.js, it is renowned for its simplicity and speed, providing a seamless content creation process. Ghost is ideal for bloggers and organizations seeking a lightweight CMS that enhances SEO and content delivery.&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.amazonaws.com%2Fuploads%2Farticles%2F4j2jgq7w9uqe1a8uh2vd.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.amazonaws.com%2Fuploads%2Farticles%2F4j2jgq7w9uqe1a8uh2vd.png" alt="Ghost CMS interface" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SEO Optimization&lt;/strong&gt;: Provides SEO-friendly features like automatic sitemap generation and rich meta tagging, complementing Next.js's SEO capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Technology Stack&lt;/strong&gt;: Built on a Node.js stack, Ghost aligns well with the server-side rendering features of Next.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight and Fast&lt;/strong&gt;: Its lightweight nature enhances the performance benefits of Next.js, making it ideal for projects requiring high-speed content delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Membership and Subscriptions&lt;/strong&gt;: Native support for memberships and subscriptions, enabling monetization in Next.js applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://ghost.org/pricing/" rel="noopener noreferrer"&gt;Ghost CMS pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Starter:&lt;/strong&gt; from $10/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; $25/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team:&lt;/strong&gt; $50/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business:&lt;/strong&gt; $199/month&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fsemed38echxk01d7jh8v.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.amazonaws.com%2Fuploads%2Farticles%2Fsemed38echxk01d7jh8v.png" alt="Ghost CMS pricing" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/kentiko-kontent-overview/" rel="noopener noreferrer"&gt;Kentico Kontent&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2F1mnkaai888zszun8v931.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.amazonaws.com%2Fuploads%2Farticles%2F1mnkaai888zszun8v931.png" alt="Kentico Kontent logo" width="600" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/kentiko-kontent-overview/" rel="noopener noreferrer"&gt;Kontent.ai&lt;/a&gt;, formerly known as Kentico Kontent, is a cloud-based CMS designed for content collaboration and delivery across multiple channels. It supports robust content modeling and real-time collaboration, making it suitable for large enterprises and digital agencies managing diverse content ecosystems.&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.amazonaws.com%2Fuploads%2Farticles%2F8909jzefa2075g9yhjb2.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.amazonaws.com%2Fuploads%2Farticles%2F8909jzefa2075g9yhjb2.png" alt="Kentiko Kontent interface" width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflow Management&lt;/strong&gt;: Offers robust tools for collaborative content creation and workflow management, supporting the development cycles typical in Next.js projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Modeling&lt;/strong&gt;: Features powerful content modeling tools to structure content efficiently, which is key when building scalable Next.js applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Capabilities&lt;/strong&gt;: Comprehensive APIs facilitate efficient data exchanges, crucial for integrating with Next.js's data fetching methods like &lt;code&gt;getStaticProps&lt;/code&gt; and &lt;code&gt;getServerSideProps&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-channel Delivery&lt;/strong&gt;: Ensures consistent content delivery across all platforms, which pairs well with Next.js's universal rendering capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/hygraph-cms-overview/" rel="noopener noreferrer"&gt;Hygraph&lt;/a&gt; (formerly GraphCMS)
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fl8dsn965cx1h8z69bj7m.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.amazonaws.com%2Fuploads%2Farticles%2Fl8dsn965cx1h8z69bj7m.png" alt="Hygraph logo" width="716" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/hygraph-cms-overview/" rel="noopener noreferrer"&gt;Hygraph&lt;/a&gt; is a headless CMS that uses GraphQL to enhance content management and delivery. It allows for the quick development of content APIs with minimal coding, ideal for projects requiring complex content structures and relationships.&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.amazonaws.com%2Fuploads%2Farticles%2Fdlmtj79hvfqod63ma9m2.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.amazonaws.com%2Fuploads%2Farticles%2Fdlmtj79hvfqod63ma9m2.png" alt="Hygraph interface" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL Native&lt;/strong&gt;: Being a GraphQL-native CMS, Hygraph provides powerful developer tools that perfectly match Next.js's data fetching strategies, enhancing the development of complex applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Management&lt;/strong&gt;: Easy management of content schemas with an intuitive interface complements Next.js's dynamic routing and static generation features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Collaboration&lt;/strong&gt;: Supports real-time collaboration and version control, which are beneficial for teams working on Next.js applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich Media Management&lt;/strong&gt;: Advanced media handling capabilities ensure that multimedia content is optimized for performance in Next.js applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://hygraph.com/pricing" rel="noopener noreferrer"&gt;Hygraph pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free forever:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Professional:&lt;/strong&gt; $199/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale:&lt;/strong&gt; $799/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom:&lt;/strong&gt; Contact to get a quote&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F8mr37fhxupvwujj4dm1o.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.amazonaws.com%2Fuploads%2Farticles%2F8mr37fhxupvwujj4dm1o.png" alt="Hygraph pricing" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/butter-cms-overview/" rel="noopener noreferrer"&gt;ButterCMS&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fnffs085ifrcduiiv5xpj.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.amazonaws.com%2Fuploads%2Farticles%2Fnffs085ifrcduiiv5xpj.png" alt="Butter CMS logo" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/butter-cms-overview/" rel="noopener noreferrer"&gt;ButterCMS&lt;/a&gt; is a straightforward headless CMS that integrates easily with existing projects thanks to its comprehensive API and SDKs. Known for its ease of use, Butter CMS is favored by marketers and developers needing to deploy content-rich sites quickly.&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.amazonaws.com%2Fuploads%2Farticles%2Fu82c8t69k7mpe0uoa9yg.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.amazonaws.com%2Fuploads%2Farticles%2Fu82c8t69k7mpe0uoa9yg.png" alt="Butter CMS interface" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Marketing Integration&lt;/strong&gt;: Offers robust tools for SEO and content marketing, enhancing the marketing aspects of Next.js websites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simple API&lt;/strong&gt;: Its simple RESTful API is easy to integrate with Next.js, supporting quick implementation in existing projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDKs and Libraries&lt;/strong&gt;: Provides SDKs for various programming languages, making it easy to integrate with Next.js and other parts of your technology stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personalization Features&lt;/strong&gt;: Content personalization capabilities align well with the dynamic and static rendering options of Next.js.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://buttercms.com/pricing/" rel="noopener noreferrer"&gt;Butter CMS pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Micror:&lt;/strong&gt; $99/month &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Startup:&lt;/strong&gt; $199/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small Business:&lt;/strong&gt; $375/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise + Agency:&lt;/strong&gt; Custom&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F8m2igfw1otyl12j1hto5.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.amazonaws.com%2Fuploads%2Farticles%2F8m2igfw1otyl12j1hto5.png" alt="Butter CMS pricing" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://focusreactive.com/strapi-cms-overview/" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt;
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2F8pbjnckp502rubm49m28.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.amazonaws.com%2Fuploads%2Farticles%2F8pbjnckp502rubm49m28.png" alt="Strapi logo" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://focusreactive.com/strapi-cms-overview/" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt; is an open-source, customizable headless CMS that supports various databases and frontend frameworks. Its API-centric approach and community-driven development make it a flexible choice for building scalable web applications. Strapi appeals to developers looking for control over their CMS environment.&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.amazonaws.com%2Fuploads%2Farticles%2Fdudqtgkiihtcaj2mvo53.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.amazonaws.com%2Fuploads%2Farticles%2Fdudqtgkiihtcaj2mvo53.png" alt="Strapi interface" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open Source&lt;/strong&gt;: One of the few fully open-source options available, giving developers complete control over their CMS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosting Capability&lt;/strong&gt;: Can be self-hosted, providing full control over the hosting environment and security aspects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable UI&lt;/strong&gt;: Offers a customizable admin panel built with React, making it a natural choice for React developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Plugins&lt;/strong&gt;: A vibrant community and a wide range of plugins available for extended functionalities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://strapi.io/pricing" rel="noopener noreferrer"&gt;Strapi pricing&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community:&lt;/strong&gt; Free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer:&lt;/strong&gt; $29/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro:&lt;/strong&gt; $99/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team:&lt;/strong&gt; $499/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; Custom&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fh2qbjyo0e640zic0z0sd.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.amazonaws.com%2Fuploads%2Farticles%2Fh2qbjyo0e640zic0z0sd.png" alt="Strapi pricing" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Recommendations
&lt;/h2&gt;

&lt;p&gt;After a detailed analysis of each platform, our top recommendations for Next.js developers based on specific project needs and priorities are:&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.amazonaws.com%2Fuploads%2Farticles%2F4jlmudmgnyvi1avyy8p1.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.amazonaws.com%2Fuploads%2Farticles%2F4jlmudmgnyvi1avyy8p1.png" alt="Sanity logo" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="https://focusreactive.com/sanity-cms-overview/" rel="noopener noreferrer"&gt;Sanity.io&lt;/a&gt;&lt;/strong&gt;:
&lt;/h3&gt;

&lt;p&gt;Perfect for projects that require real-time content updates and a high degree of customization in the content editing experience.&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.amazonaws.com%2Fuploads%2Farticles%2Fqt7its9kecfgrxrug21e.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.amazonaws.com%2Fuploads%2Farticles%2Fqt7its9kecfgrxrug21e.png" alt="Storyblok logo" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="https://focusreactive.com/storyblok-cms-overview/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt;&lt;/strong&gt;:
&lt;/h3&gt;

&lt;p&gt;Ideal for those who value intuitive content management with a visual editor and a block-based approach, offering ease of use for developers and content creators alike.&lt;/p&gt;

&lt;p&gt;If you are considering a &lt;a href="https://focusreactive.com/migration-from-wordpress-to-headless-cms/" rel="noopener noreferrer"&gt;migration to Headless CMS&lt;/a&gt; or you are building it from scratch - &lt;a href="https://focusreactive.com/#mail-us" rel="noopener noreferrer"&gt;contact us&lt;/a&gt;, we are &lt;a href="https://focusreactive.com/headless-cms-expert-agency/" rel="noopener noreferrer"&gt;headless cms agency&lt;/a&gt; and we can set up a free consultation around the project you have in mind &lt;/p&gt;

</description>
      <category>headlesscms</category>
      <category>nextjs</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Next.js Conf 2024 Highlights and React Framework Future</title>
      <dc:creator>Aleksei Zhilyuk</dc:creator>
      <pubDate>Thu, 31 Oct 2024 09:26:32 +0000</pubDate>
      <link>https://forem.com/focusreactive/nextjs-conf-2024-highlights-and-react-framework-future-1bdb</link>
      <guid>https://forem.com/focusreactive/nextjs-conf-2024-highlights-and-react-framework-future-1bdb</guid>
      <description>&lt;p&gt;While the overall ambitious tone of the previous conference editions have cooled off, we enthusiastically welcomed the direction the presenting team have taken, focusing on making Next.js API more streamlined, and self-hosting friendly. We saw updates and celebrated stable release of Turbopack for Dev, and insightful deep-dives from people behind the framework. &lt;/p&gt;

&lt;p&gt;Followed up by case studies of major Next.js adopters, and strategic partners, including, our most technological Headless CMS of choice - &lt;a href="https://focusreactive.com/sanity-expert-agency/" rel="noopener noreferrer"&gt;Sanity&lt;/a&gt;, which went all in with their Next.js 15 support and innovative “live” CMS content approach. We got so excited about the last one that we even wrote a separate blog post breaking down the vision behind the new architecture of choice when it comes to Next.js+Sanity combo.&lt;/p&gt;

&lt;p&gt;Let’s break down some of the talks we followed the most:&lt;/p&gt;

&lt;h2&gt;
  
  
  Opening Keynote
&lt;/h2&gt;

&lt;p&gt;Guillermo Rauch (CEO, Vercel &amp;amp; Creator of Next.js) welcomes everyone to the fifth anniversary of Next.js and begins his speech by expressing gratitude to the main contributors to Next.js.&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.amazonaws.com%2Fuploads%2Farticles%2Fybmi4tv8sibchvkwjddg.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fybmi4tv8sibchvkwjddg.webp" alt="Guillermo Rauch on stage" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lot happened during the year:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4000 PRs&lt;/li&gt;
&lt;li&gt;5 Next.js releases were made&lt;/li&gt;
&lt;li&gt;570 new contributors joined the project&lt;/li&gt;
&lt;li&gt;Next.js reaches 7 million downloads on NPM&lt;/li&gt;
&lt;li&gt;Many large companies have already migrated to APP Router, such as PayPal, wayfair, xAI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Guillermo Rauch believes that Next.js and its ecosystem is something we can rely on in the future. Next.js is used all over the world to create everything from the simplest websites to complex, sophisticated applications.&lt;/p&gt;

&lt;p&gt;Guillermo Rauch was guided by these principles when creating Next.js&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make it work &lt;/li&gt;
&lt;li&gt;Make it right&lt;/li&gt;
&lt;li&gt;Make it fast&lt;/li&gt;
&lt;li&gt;Make it blazing fast&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Ftwt52lr8bhi95m30d3hg.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Ftwt52lr8bhi95m30d3hg.webp" alt="make, right, fast" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;APP Router was created to make data fetching and rendering more predictable, since according to Guillermo Rauch, developers should not worry about caching and focus on creating the application.&lt;/p&gt;

&lt;p&gt;In order for the idea to turn into a product as quickly as possible and the time for each iteration to be as short as possible Guillermo Rauch is pleased to announce that Turbopack is finally stable. &lt;/p&gt;

&lt;p&gt;The new compiler is 50% faster than the previous one for initial compilation and 90% faster for Fast Refresh.&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.amazonaws.com%2Fuploads%2Farticles%2F0l29h0c3qlehwhmaj8zf.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F0l29h0c3qlehwhmaj8zf.webp" alt="nextjs.org compile time" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Coming soon for Turbopack: Turbopack uses persistent cache for its fast performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplifying Next.js Cache API
&lt;/h3&gt;

&lt;p&gt;Next, Delba de Oliveira (DX Engineer at Vercel) shows how to make the demo application faster using caching and introduces a new experimental NextJS “use cache” directive that allows you to explicitly specify that a component or the result of a function execution should be cached. &lt;/p&gt;

&lt;p&gt;This directive works both in components, similar to “use client”, and in functions, similar to “use server”, as well as a new API “cacheTag” for cache keys and “cacheLife” for specifying how long a given cache should live.&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.amazonaws.com%2Fuploads%2Farticles%2Fsa9t3hqx65oonxoe6yxw.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fsa9t3hqx65oonxoe6yxw.webp" alt="use cache" width="800" height="417"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fzewvqc9zhfmwysyhjcqu.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fzewvqc9zhfmwysyhjcqu.webp" alt="pertial prerendering" width="800" height="251"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwh92dcyfclzumiv1cd9a.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fwh92dcyfclzumiv1cd9a.webp" alt="dynamic/streaming/prerender/revalidate" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers can try these experimental changes in the canary version of Next.js. We will also soon write up our own deep-dive into the new “use cache” API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better self-hosting of Next.js
&lt;/h3&gt;

&lt;p&gt;Next, Lee Robinson (VP of Product at Vercel) appears on stage to uncover improvements for &lt;a href="https://focusreactive.com/self-hosted-next-js-when-vercel-is-not-an-option/" rel="noopener noreferrer"&gt;self-hosted Next.js&lt;/a&gt; they have shipped, re-iterating Vercel’s focus on keeping Next.js open-source first.&lt;/p&gt;

&lt;p&gt;In v15, the Vercel team has made it easier to configure how caching works by default, also simplifying the required minimal DevOps setup for self hosting Next.js. Documentation covering various deployment scenarios and templates have also been greatly improved, including the &lt;a href="https://github.com/nextjs" rel="noopener noreferrer"&gt;launch of Next.js community GitHub org&lt;/a&gt; with up-to-date redeployment recipes for community’s most popular hosting targets.&lt;/p&gt;

&lt;p&gt;Previously, Next.js used a web assembly-based image optimization library, but they were dissatisfied with the fact that this library consumed a lot of memory, so now it uses “Sharp”, which is installed automatically.&lt;/p&gt;

&lt;p&gt;Default cache control headers have been updated&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.amazonaws.com%2Fuploads%2Farticles%2F9zy5l6weifdwf75crw7m.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F9zy5l6weifdwf75crw7m.webp" alt="next14 vs next15 cache control headers" width="800" height="191"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Ffb92za938d6o45nbr4o5.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Ffb92za938d6o45nbr4o5.webp" alt="cache controll config" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AMA: Next.js Team
&lt;/h3&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.amazonaws.com%2Fuploads%2Farticles%2Fcwe0x3zazzikzlpascnv.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fcwe0x3zazzikzlpascnv.webp" alt="AMA: Next.js Team" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Variety of topics have been covered during the Ask Me Anything session with the Next.js team, we suggest you dive into it yourself on the &lt;a href="https://www.youtube.com/live/WLHHzsqGSVQ?si=rV4XvraDRztZINiB&amp;amp;t=4915" rel="noopener noreferrer"&gt;stream recording&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Server Components: Elevating speed, interactivity, and user experience
&lt;/h2&gt;

&lt;p&gt;Aurora starts her talk by saying that the RSC have changed the way we build apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some of the new possibilities, that come with the RSC:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch data async inside the component itself&lt;/li&gt;
&lt;li&gt;Access backend resources directly from component&lt;/li&gt;
&lt;li&gt;No JS is ship to the client&lt;/li&gt;
&lt;li&gt;Streaming&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;RSC and latest next.js features help increase speed of not only websites, but also development velocity. New versions of next.js and react help you split compute load between client and a server, which will help you build an application based on your needs. Another important aspects that have beed improved, are interactivity and ability to easily build responsive apps.&lt;/p&gt;

&lt;p&gt;With the new features comes new limitations, for example you can’t access client hooks such as useState, useEffect, or browser information in such components.&lt;/p&gt;

&lt;p&gt;New development patterns to leverage the latest features and create a stunning UI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Move data fetching closer to UI&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Instead of fetching data on top level, and make requests blocking render, move data fetching inside the component, and wrap component in Suspence boundary.&lt;/p&gt;

&lt;p&gt;Before and after&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.amazonaws.com%2Fuploads%2Farticles%2F4pm0ombdq6tyqz36aoa3.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F4pm0ombdq6tyqz36aoa3.webp" alt="render-blocking requests" width="476" height="487"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F9kxigi68eqh34yp16dup.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F9kxigi68eqh34yp16dup.webp" alt="suspense requests" width="529" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add client component and preserve request non-blocking fashion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you need to make a component inside Suspence boundary client-side, you will be forced to remove server function call from it. In this case, create a promise on the top level, pass it to client component as a prop, and resolve using react new use() function. It will help you avoid render blocking and keep client component in suspense boundary, to show a static shell on initial render.&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.amazonaws.com%2Fuploads%2Farticles%2Fii5do8q8ti77fs46i7v0.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fii5do8q8ti77fs46i7v0.webp" alt="react use hook" width="459" height="55"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fz0o8rs6aij5m6tebi7jo.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fz0o8rs6aij5m6tebi7jo.webp" alt="passing promise from RSC to RCC" width="535" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;useTransition, useOptimistic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These new react hooks allows you to create a smooth transitions on any user’s action. Moreover, using these hooks you are able to show instant feedback to the user and mnot depend on network connection.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;React cache&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use new cache function to prevent firing the same request multiple times. This means we can reuse existing pattern of calling data directly inside component and maintain composition.&lt;/p&gt;

&lt;p&gt;All these new features and patters allow us build fully interactive apps without use of useState and useEffect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best development practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resolve promises deep in the tree&lt;/li&gt;
&lt;li&gt;Display pending indicators&lt;/li&gt;
&lt;li&gt;Put state in the URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New tools:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Leverage react 19 features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cache() - perform per-render caching for expensive func calls&lt;/li&gt;
&lt;li&gt;useOptimistic() - respond to user interactions instantly even when the request is slow&lt;/li&gt;
&lt;li&gt;use() - suspend client components as they resolve a promise passed down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next.js features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;staleTimes - set state times for dynamic page segments to reuse them across subsequent requests&lt;/li&gt;
&lt;li&gt;PPR - statically renders parts of the page or layout to improve performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The long and winding road: CSR to static export to SSG
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Building user interfaces in the age of AI
&lt;/h3&gt;

&lt;p&gt;Oleg starts of by defining what is great interface? Great interface is measured by the ability to help users accomplish their task as quickly and as effortlessly as possible.&lt;/p&gt;

&lt;p&gt;The most important things here are speed and reliability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Generative UI?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is an umbrella for any project leveraging LLMs, in order to enhance user interface. It is a spectrum. Each side of the spectrum has it’s own tradeoffs and requirements. But they are united by the crucial role of LLM.&lt;/p&gt;

&lt;p&gt;Both edges of the spectrum has it’s own requirements,  tradeoffs and performance characteristics.&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.amazonaws.com%2Fuploads%2Farticles%2Fy49tmqy0h4tjiky7yyrg.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fy49tmqy0h4tjiky7yyrg.webp" alt="generative UI spectrum" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The slide represents the current state of LLM’s capabilities for generating UI.&lt;/p&gt;

&lt;p&gt;Generating HTML from text is a hard problem with following challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Slow. takes up to 5-7s to generate a HTML page on perplexity &lt;/li&gt;
&lt;li&gt;No reliable way to deploy it&lt;/li&gt;
&lt;li&gt;Hard to sync with design system&lt;/li&gt;
&lt;li&gt;Token inefficiency&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Perplexity team is focused on text to object generations instead.&lt;/p&gt;

&lt;p&gt;One of the patterns guys in Perplexity use is define schemas for each presentational component and define props based on schema.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fm1wdhpskj0bmoxezt3vu.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fm1wdhpskj0bmoxezt3vu.webp" alt="schema for component props" width="723" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then use component’s schema as input for the model. This way you can create simple components with streaming functionality using LLMs.&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.amazonaws.com%2Fuploads%2Farticles%2Frbsby0alqo844cfsvwvt.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Frbsby0alqo844cfsvwvt.webp" alt="component handling streaming schema" width="734" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use LLMs as APIs&lt;/li&gt;
&lt;li&gt;Faster and cheaper &lt;/li&gt;
&lt;li&gt;Fits well into existing flow&lt;/li&gt;
&lt;li&gt;Easy to integrate&lt;/li&gt;
&lt;li&gt;Structured output&lt;/li&gt;
&lt;li&gt;React friendly JSON data&lt;/li&gt;
&lt;li&gt;Guaranteed to be valid&lt;/li&gt;
&lt;li&gt;Schemas are useful without LLMs&lt;/li&gt;
&lt;li&gt;Streaming UX&lt;/li&gt;
&lt;li&gt;Address re-rendering issues&lt;/li&gt;
&lt;li&gt;Use OSS libs&lt;/li&gt;
&lt;li&gt;Implementation depends on your code&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Optimizing LCP: Partial Prerendering deep dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Wyatt Johnson
&lt;/h3&gt;

&lt;p&gt;Wyatt Johnson, a software engineer at Vercel, provides a comprehensive overview of “Partial Prerendering”, an experimental feature aimed at optimizing the Largest Contentful Paint (LCP) by combining the best of static and dynamic rendering techniques. This method has been developed to tackle the limitations of traditional rendering methods, improving site performance and user experience.&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.amazonaws.com%2Fuploads%2Farticles%2Fbe1d97oqnrtq4b6o3b5i.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fbe1d97oqnrtq4b6o3b5i.webp" alt="what are Core Web Vitals?" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wyatt begins by explaining the significance of Core Web Vitals, particularly focusing on LCP, which measures the render time of the largest image or text block visible within the viewport. He highlights the challenges faced with traditional rendering approaches where developers must choose between the speed of static rendering and the flexibility of dynamic rendering. Static rendering, while fast, cannot incorporate request data, leading to delays in rendering dynamic content. Conversely, dynamic rendering incorporates request data but often at the expense of speed due to server response times.&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.amazonaws.com%2Fuploads%2Farticles%2F9ywcuigbrrbvv86y07ie.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F9ywcuigbrrbvv86y07ie.webp" alt="speed functionality tradeoff" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The session delves into the mechanics of Partial Prerendering (PPR), which allows for a static shell of a page to be generated at build time and served from the edge. Simultaneously, it sends a request back to the origin to complete the dynamic rendering. This approach minimizes the time to first byte and ensures that the page loads quickly while still supporting dynamic capabilities.&lt;/p&gt;

&lt;p&gt;Wyatt demonstrates practical applications of PPR in an e-commerce setting, showing how PPR can streamline the rendering process, reduce latency, and improve the user experience by delivering a fast initial load with dynamic capabilities intact. He further explains the technical implementation of PPR, discussing how it leverages React’s capabilities to suspend and resume rendering as needed, based on the dynamic content requirements.&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.amazonaws.com%2Fuploads%2Farticles%2Folguu0y420br1v0wslro.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Folguu0y420br1v0wslro.webp" alt="enabling partial prerenderring" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To conclude, Wyatt emphasizes the future potential of PPR in Next.js and the ongoing efforts to integrate this feature across different hosting environments. He expresses enthusiasm for the capabilities of Next.js in bridging the gap between static speed and dynamic flexibility, ultimately providing developers with the tools to build faster and more responsive web applications.&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.amazonaws.com%2Fuploads%2Farticles%2Fvwmyjmf6hvlz4bu80vj8.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fvwmyjmf6hvlz4bu80vj8.webp" alt="streaming on 5$ VPS" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That's a Wrap
&lt;/h2&gt;

&lt;p&gt;Thank you for following our highlights from the Next.js Conference 2024, we enjoy sharing these with the community, as we eagerly follow all the developments in the Next.js space.&lt;/p&gt;

&lt;p&gt;Follow our blog for more Next.js content and practical use cases that we have solved building a variety of Next.js apps; as well as the practices we developed through our &lt;a href="https://focusreactive.com/nextjs-performance-audit/" rel="noopener noreferrer"&gt;Performance and SEO audits&lt;/a&gt; for our clients.&lt;/p&gt;

&lt;p&gt;We are excited about the direction Next.js team took, prioritizing API simplicity,increased transparency and support towards non-Vercel clients, which is dearly important for us. We support the renewed open source spirit and simplicity it brings for deployment of Next.js to own cloud environments.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Top React Conferences to Attend in 2024</title>
      <dc:creator>Aleksei Zhilyuk</dc:creator>
      <pubDate>Tue, 27 Aug 2024 10:31:42 +0000</pubDate>
      <link>https://forem.com/focusreactive/top-react-conferences-to-attend-in-2024-54n0</link>
      <guid>https://forem.com/focusreactive/top-react-conferences-to-attend-in-2024-54n0</guid>
      <description>&lt;p&gt;The React community continues to grow and evolve, making 2024 an exciting year for developers who want to connect, learn, and share their knowledge. Whether you're an experienced pro or just getting started, attending a React conference is an excellent way to stay up-to-date with the latest trends, tools, and best practices. Below, we've outlined some of the top React conferences coming up in 2024 that you won't want to miss.&lt;/p&gt;

&lt;p&gt;For a full list of events, check out the &lt;a href="https://gitnation.com/events/react-conferences" rel="noopener noreferrer"&gt;React events&lt;/a&gt; on GitNation.&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.amazonaws.com%2Fuploads%2Farticles%2Fow6v1naki4jsrvwt33mm.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.amazonaws.com%2Fuploads%2Farticles%2Fow6v1naki4jsrvwt33mm.png" alt="React Summit US logo" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. React Summit US
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt; November 19 - 22, 2024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; New York, USA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://reactsummit.us/" rel="noopener noreferrer"&gt;React Summit US&lt;/a&gt; is one of the largest React gatherings worldwide, bringing together industry leaders to discuss the latest in React technology, state management, performance optimization, and more. Whether you're interested in deep technical dives or broader industry trends, you'll find sessions and workshops that fit your needs.&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.amazonaws.com%2Fuploads%2Farticles%2Fk0dh0gwid220j44qa8on.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.amazonaws.com%2Fuploads%2Farticles%2Fk0dh0gwid220j44qa8on.png" alt="React Day Berlin logo" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. React Day Berlin
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt; December 13 - 16, 2024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Berlin, Germany&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Berlin, a vibrant tech hub, hosts &lt;a href="https://reactday.berlin/" rel="noopener noreferrer"&gt;React Day Berlin&lt;/a&gt;, a must-attend event for React developers in Europe. This conference offers a perfect blend of technical sessions, hands-on workshops, and networking opportunities. Expect to hear from top-notch speakers, including React core team members and contributors from the open-source community.&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.amazonaws.com%2Fuploads%2Farticles%2Fgins8gmr0urqrn92eup2.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.amazonaws.com%2Fuploads%2Farticles%2Fgins8gmr0urqrn92eup2.png" alt="React Advanced London logo" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. React Advanced London
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt; October 25 - 28, 2024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; London, UK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://reactadvanced.com/" rel="noopener noreferrer"&gt;React Advanced London&lt;/a&gt; is one of the most anticipated React events. Known for its diverse lineup of speakers and in-depth sessions, this conference covers everything from fundamental React concepts to advanced design patterns. It's a great opportunity to meet fellow developers and immerse yourself in the tech scene.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet the FocusReactive Team
&lt;/h2&gt;

&lt;p&gt;FocusReactive is a co-organizer of these conferences, and our team will be actively participating in all of them. We’d love to connect with you—whether to chat about the latest trends in React, explore potential collaborations, or just say hello. If you're attending any of these events, don't hesitate to reach out to us!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With so many incredible events on the horizon, 2024 is set to be a fantastic year for the React community. Each of these conferences offers unique opportunities to learn, network, and grow as a developer. Be sure to grab your tickets and join the community at these exciting gatherings.&lt;/p&gt;

&lt;p&gt;For more details on these and other React conferences, check out the full &lt;a href="https://gitnation.com/events/react-conferences" rel="noopener noreferrer"&gt;React conferences list&lt;/a&gt; by GitNation.&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>How to Manage Multiple Domains with a Headless CMS</title>
      <dc:creator>Anton Meleshkin</dc:creator>
      <pubDate>Mon, 26 Aug 2024 10:24:14 +0000</pubDate>
      <link>https://forem.com/focusreactive/how-to-manage-multiple-domains-with-a-headless-cms-4b28</link>
      <guid>https://forem.com/focusreactive/how-to-manage-multiple-domains-with-a-headless-cms-4b28</guid>
      <description>&lt;p&gt;Hello, fellow developers! Today, we’re diving into a common challenge: "&lt;strong&gt;How can I manage 2+ domains under one CMS space?&lt;/strong&gt;" Luckily, with modern technologies, this is easier than you might think.&lt;/p&gt;

&lt;p&gt;For this guide, we'll use &lt;a href="https://www.storyblok.com/" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt; as our headless CMS (hCMS) of choice due to its intuitive design and flexible features. However, if you’re using a different hCMS, you can still apply the core principles discussed here, as long as your CMS supports folder-based organization.&lt;/p&gt;

&lt;p&gt;What will you learn in this guide? Here's a sneak peek:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;How to bake a multi-domain Storyblok space&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tasty spices, aka small but very useful features&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handling international filling&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Scenario: Managing Multiple Domains
&lt;/h2&gt;

&lt;p&gt;Let’s imagine you have three domains that need to be managed under one hCMS workspace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;domain-1.com&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;domain-2.com&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;domain-3.com&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Organizing Content by Domain
&lt;/h3&gt;

&lt;p&gt;Start by creating folders within your CMS for each domain and fill them with the respective content. In Storyblok, this might look something like this:&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.amazonaws.com%2Fuploads%2Farticles%2F9tl09x67brxbp5233ipo.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.amazonaws.com%2Fuploads%2Farticles%2F9tl09x67brxbp5233ipo.png" alt="Three domain Storyblok example" width="800" height="177"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F3ulv0dwkedvxojk2ps01.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.amazonaws.com%2Fuploads%2Farticles%2F3ulv0dwkedvxojk2ps01.png" alt="Domain pages example" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With your content neatly organized, the necessary preparations on the CMS side is complete. Now, let’s dive into the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configuring Data Fetching in Next.js
&lt;/h3&gt;

&lt;p&gt;In this guide, we'll use &lt;strong&gt;Next.js&lt;/strong&gt; along with &lt;strong&gt;Vercel&lt;/strong&gt; for deployment. The key here is to configure data fetching based on the domain, which will allow your application to serve the correct content dynamically.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Fetching Data for a Specific Domain
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storyblokApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getStoryblokApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;storyblokApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`cdn/stories/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;draft&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Fetches the draft version of the content&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Revalidate every 24 hours&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/404&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Redirect to 404 page if content is not found&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Environment Variable Setup
&lt;/h4&gt;

&lt;p&gt;To ensure your application knows which domain it’s serving, set up an environment variable in your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Deploying on Vercel
&lt;/h3&gt;

&lt;p&gt;When deploying to Vercel, you’ll need to create a separate project for each domain. In each project, configure the environment variables accordingly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Project 1:&lt;/strong&gt; &lt;code&gt;NEXT_PUBLIC_BASE_PATH=domain-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project 2:&lt;/strong&gt; &lt;code&gt;NEXT_PUBLIC_BASE_PATH=domain-2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project 3:&lt;/strong&gt; &lt;code&gt;NEXT_PUBLIC_BASE_PATH=domain-3&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fkd6leizgy5tddgch3lye.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.amazonaws.com%2Fuploads%2Farticles%2Fkd6leizgy5tddgch3lye.png" alt="Vercel environment fields image" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ensures that each domain pulls the correct content from your CMS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Handling Links in Your Application
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Example: Link Processing Function
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkProcessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IStoryLink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;correctUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;full_slug&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cached_url&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Remove base path if link is to the homepage&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;correctUrl&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;correctUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;correctUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;correctUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;correctUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;correctUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;full_slug&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cached_url&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function ensures that when users navigate your site, they won’t see URLs like &lt;code&gt;prod-domain.com/domain-1/&lt;/code&gt; but rather the cleaner &lt;code&gt;prod-domain.com/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's all. It's THAT simple. What did you expect, a 10-page guide? Stop reading and go have fun with JavaScript! &lt;strong&gt;Happy hacking&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Considerations
&lt;/h2&gt;

&lt;p&gt;For more sophisticated readers, here are a few other places where you can use this in your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sitemap Generation
&lt;/h3&gt;

&lt;p&gt;First of all, don't forget your roots. In our case, it's a sitemap. The main thing you should do is add this &lt;code&gt;NEXT_PUBLIC_BASE_PATH&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_PRODUCTION_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//prod-domain.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your sitemap generation script (&lt;code&gt;generateSitemap.ts&lt;/code&gt;), modify the slug to remove the base path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;full_slug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slugWithoutTrailingSlash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`\n&amp;lt;url&amp;gt;\n&amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_PRODUCTION_DOMAIN&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slugWithoutTrailingSlash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/loc&amp;gt;
&amp;lt;lastmod&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/lastmod&amp;gt;&amp;lt;/url&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Configuring Redirects and Rewrites
&lt;/h3&gt;

&lt;p&gt;You can also control redirects, rewrites, or other configurations based on the domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;domain-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;redirects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT_REDIRECTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;DOMAIN_1_REDIRECTS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;rewrites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_REWRITES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;redirects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_REDIRECTS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;rewrites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_REWRITES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Managing Tracking Scripts
&lt;/h3&gt;

&lt;p&gt;Lastly, use the environment variable to manage domain-specific tracking scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Script&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tracking-script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lazyOnload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.tracking_script.com/script/ididid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_PATH&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;domain-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;first-domain-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;domain-2.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that your tracking data is accurately associated with the correct domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multilanguage
&lt;/h2&gt;

&lt;p&gt;You may ask yourself, "What about multilanguage support?" Fear not! Storyblok has you covered. By following the same principles discussed here, you can easily manage multilanguage content across multiple domains. Simply create folders for each language and domain, and you're good to go.&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.amazonaws.com%2Fuploads%2Farticles%2Ffk5y1xvzuc94p63iho1l.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.amazonaws.com%2Fuploads%2Farticles%2Ffk5y1xvzuc94p63iho1l.png" alt="Multilanguage folders example" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you wish for more control over multilanguage settings, you can create a &lt;code&gt;configuration&lt;/code&gt; folder with a &lt;code&gt;languages&lt;/code&gt; subfolder. In this subfolder, create stories for each language with any settings you can imagine. Just fetch this data like we did in the &lt;strong&gt;Step 2&lt;/strong&gt; example, and you're all set!&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.amazonaws.com%2Fuploads%2Farticles%2F2do60w5x3n273jg9uljb.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.amazonaws.com%2Fuploads%2Farticles%2F2do60w5x3n273jg9uljb.png" alt="Multilanguage configuration lines example" width="516" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another question you might have is, "Hey, what if some of my domains are multilanguage, and others aren't?" No worries! You can mix and match as needed. Storyblok's flexible structure allows you to adapt to various scenarios seamlessly.&lt;/p&gt;

&lt;p&gt;For example, you can create &lt;code&gt;configuration&lt;/code&gt; folder with &lt;code&gt;domains-settings&lt;/code&gt; subfolder which will have stories for each domain with settings like &lt;code&gt;isUsingLocales&lt;/code&gt; and &lt;code&gt;defaultHomepageSlug&lt;/code&gt;: &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.amazonaws.com%2Fuploads%2Farticles%2Fvf6p5zdx1485xuythppr.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.amazonaws.com%2Fuploads%2Farticles%2Fvf6p5zdx1485xuythppr.png" alt="Configuration lines with locales example" width="550" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, don't forget about Storyblok built-in conditional fields. They can be a lifesaver when you need to show or hide some fields from content managers.&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.amazonaws.com%2Fuploads%2Farticles%2Fa3l3iazrdrqt74j89kti.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.amazonaws.com%2Fuploads%2Farticles%2Fa3l3iazrdrqt74j89kti.png" alt="Configuration lines without locales example" width="540" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can fetch this configuration in your application and use it to determine how to handle multilanguage content for each domain. The possibilities are endless!&lt;/p&gt;

&lt;h3&gt;
  
  
  That's all, folks!
&lt;/h3&gt;

&lt;p&gt;And there you have it! With Storyblok and a bit of JavaScript magic, you can manage multiple domains under one CMS space with ease. So go forth and build amazing projects that span the digital realm. &lt;strong&gt;Happy hacking&lt;/strong&gt;!&lt;/p&gt;

</description>
      <category>multidomain</category>
      <category>nextjs</category>
      <category>storyblok</category>
      <category>vercel</category>
    </item>
    <item>
      <title>Vercel vs Netlify: How to Pick the Right One</title>
      <dc:creator>Alex Hramovich</dc:creator>
      <pubDate>Mon, 26 Aug 2024 08:37:43 +0000</pubDate>
      <link>https://forem.com/focusreactive/vercel-vs-netlify-how-to-pick-the-right-one-d1e</link>
      <guid>https://forem.com/focusreactive/vercel-vs-netlify-how-to-pick-the-right-one-d1e</guid>
      <description>&lt;p&gt;In today’s web development, choosing the right deployment platform is key to your project's performance, scalability, and ease of management. Vercel and Netlify stand out as top choices for developers building web applications efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing Between Vercel and Netlify: What You Need to Know
&lt;/h3&gt;

&lt;p&gt;When it comes to static site hosting and serverless deployment, Vercel and Netlify are top contenders, both built around the Jamstack architecture. They excel at delivering pre-rendered static content from CDNs, while adding dynamic capabilities through APIs and serverless functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Vercel&lt;/strong&gt; if you need lightning-fast global content delivery, especially for projects built with Next.js. Vercel’s deep integration with Next.js and strong support for server-side rendering (SSR) make it an excellent choice for dynamic content and SEO-driven sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go with Netlify&lt;/strong&gt; if you're looking for a great ecosystem packed with built-in tools like form handling, identity management, and a versatile deployment suite. Netlify, as one of the original pioneers of Jamstack, is perfect for static sites that can leverage its rich set of integrated features.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Decision Tree&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s a simple decision tree to help guide your platform choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Do you need Server-Side Rendering (SSR)?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt; → Choose &lt;strong&gt;Vercel&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt; → Move to the next question&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Are you using Next.js or prioritizing edge performance?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt; → Choose &lt;strong&gt;Vercel&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt; → Move to the next question&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Do you need built-in form handling, identity management, or A/B testing?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt; → Choose &lt;strong&gt;Netlify&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt; → Move to the next question&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Is pricing flexibility and built-in features important to you?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt; → Choose &lt;strong&gt;Netlify&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt; → Move to the next question&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Do you prefer using Docker for builds?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt; → Choose &lt;strong&gt;Netlify&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt; → Choose &lt;strong&gt;Vercel&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Comparison of Vercel and Netlify&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To make a smart decision between Vercel and Netlify, it's important to look at how they stack up in the areas that matter most for your project. In case you're interested, here is a &lt;a href="https://focusreactive.com/vercel-vs-netlify-how-to-pick-the-right-platform/" rel="noopener noreferrer"&gt;detailed Vercel vs Netlify comparison&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vercel</category>
      <category>netlify</category>
      <category>jamstack</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>7 Awesome Multi-Tenant Features in Headless CMS That'll Make Your Life Easier</title>
      <dc:creator>Oleg Proskurin</dc:creator>
      <pubDate>Sat, 24 Aug 2024 12:15:00 +0000</pubDate>
      <link>https://forem.com/focusreactive/7-awesome-multi-tenant-features-in-headless-cms-thatll-make-your-life-easier-2haa</link>
      <guid>https://forem.com/focusreactive/7-awesome-multi-tenant-features-in-headless-cms-thatll-make-your-life-easier-2haa</guid>
      <description>&lt;p&gt;Headless CMS platforms are not only matching traditional content management systems but are significantly surpassing them. These systems offer advanced multi-tenant features that traditional CMS platforms lack. Ready to enhance your web strategy? Let's delve into seven features that can transform your content management experience.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multilingual Content Management&lt;/strong&gt; 🌍&lt;br&gt;&lt;br&gt;
Eliminate language barriers effortlessly. Headless CMS platforms enable you to manage content in multiple languages within a single interface, making it seamless to reach a global audience. It's like hosting an international conference within your CMS. Learn more about &lt;a href="https://focusreactive.com/multiple-domains-with-a-headless-cms/#multilanguage" rel="noopener noreferrer"&gt;setting up a multilingual project in Storyblok&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Domain Support&lt;/strong&gt; 🏢&lt;br&gt;&lt;br&gt;
Managing multiple brands or clients? Headless CMS provides centralized control over several domains from one hub. It's akin to having a Swiss Army knife for websites—multiple tools in one compact package. Discover how to &lt;a href="https://focusreactive.com/multiple-domains-with-a-headless-cms/#the-scenario-managing-multiple-domains" rel="noopener noreferrer"&gt;configure a multi-domain setup with Vercel, NextJS, and Storyblok&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Regional Content Delivery&lt;/strong&gt; 🗺️&lt;br&gt;&lt;br&gt;
Go beyond translation by tailoring your content for different countries or regions, ensuring your message resonates with local audiences. This feature also helps navigate varying governmental requirements across countries or even states—crucial in industries like iGaming. Explore how we established CMS &lt;a href="https://focusreactive.com/sanity-cms-for-tipico-platform/#1-the-labels-system" rel="noopener noreferrer"&gt;sections for U.S. states in Sanity&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Built-In A/B Testing&lt;/strong&gt; 🧪&lt;br&gt;&lt;br&gt;
Some Headless CMS platforms include integrated A/B testing capabilities. Experiment with different content versions to optimize engagement, providing insights into what your audience prefers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personalized Content Delivery&lt;/strong&gt; 🎭&lt;br&gt;&lt;br&gt;
Imagine a CMS that delivers content based on user behavior and interests. This feature enhances user experience by providing relevant content. Learn how &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#24-getting-personal-using-data-to-improve-shopping-experiences" rel="noopener noreferrer"&gt;personalization can be implemented&lt;/a&gt; to improve engagement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Omnichannel Content Distribution&lt;/strong&gt; 📱&lt;br&gt;&lt;br&gt;
Distribute your content across websites, mobile apps, smart devices, and more, ensuring consistency and broad reach. This is especially beneficial for eCommerce platforms, maintaining product presentation across various channels. Read more about &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#23-omnichannel-retail-blending-online-and-offline-shopping" rel="noopener noreferrer"&gt;omnichannel retail and blending online and offline shopping&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customizable User Roles and Permissions&lt;/strong&gt; 🔐&lt;br&gt;&lt;br&gt;
Define who has access to what within your CMS. You can grant limited access to external contributors, perfect for collaborations without compromising security. See how you can &lt;a href="https://focusreactive.com/assigning-cms-users-to-sanity/" rel="noopener noreferrer"&gt;assign CMS users in Sanity&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These multi-tenant features showcase how Headless CMS is redefining content management. It's about creating dynamic experiences across multiple platforms and audiences.&lt;/p&gt;

&lt;p&gt;Development with Headless CMS is often more straightforward than you might think. It excels in performance and SEO optimization—key factors that make your website stand out in today's digital landscape.&lt;/p&gt;

&lt;p&gt;At FocusReactive, we've witnessed businesses transform with these features. Our team specializes in platforms like Storyblok and Sanity and is dedicated to helping you unlock their full potential.&lt;/p&gt;

&lt;p&gt;Interested in learning how to set up a multi-tenant Headless CMS project using Storyblok, NextJS, and Vercel? Refer to our comprehensive &lt;a href="https://focusreactive.com/multiple-domains-with-a-headless-cms/" rel="noopener noreferrer"&gt;technical guide on the FocusReactive blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ready to elevate your web presence with multi-tenant Headless CMS? Let's &lt;a href="https://focusreactive.com/#mail-us" rel="noopener noreferrer"&gt;discuss your project&lt;/a&gt; and how we can help you achieve digital excellence. The future of content management is here—are you ready to embrace it?&lt;/p&gt;

</description>
      <category>ecommerce</category>
      <category>headless</category>
      <category>storyblok</category>
      <category>webdev</category>
    </item>
    <item>
      <title>7 Key eCommerce Trends for 2024 You Need to Know</title>
      <dc:creator>Oleg Proskurin</dc:creator>
      <pubDate>Mon, 12 Aug 2024 08:19:07 +0000</pubDate>
      <link>https://forem.com/focusreactive/7-key-ecommerce-trends-for-2024-you-need-to-know-422j</link>
      <guid>https://forem.com/focusreactive/7-key-ecommerce-trends-for-2024-you-need-to-know-422j</guid>
      <description>&lt;p&gt;Through our research on modern eCommerce, we have identified key trends shaping the industry. For a comprehensive overview, please read our full article on &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/" rel="noopener noreferrer"&gt;Modern eCommerce Architecture Trends and Services&lt;/a&gt;. Below is a concise summary of the primary trends, including their business benefits and additional features.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. AI-Driven Personalization
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2F5kmkv34ti9y2tn928w4g.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.amazonaws.com%2Fuploads%2Farticles%2F5kmkv34ti9y2tn928w4g.png" alt="AI in eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn more about &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#21-ai-making-online-shopping-smarter" rel="noopener noreferrer"&gt;AI Making Online Shopping Smarter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Artificial Intelligence enhances customer experience through machine learning algorithms, predictive analytics, and customized user interactions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Increased conversions, enhanced customer experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: Small apparel shops can use AI to recommend outfits based on customer preferences, leading to higher sales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.dynamicyield.com/" rel="noopener noreferrer"&gt;Dynamic Yield&lt;/a&gt;&lt;/strong&gt; — AI personalization platform that tailors content, products, and offers to each customer's preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://useinsider.com/ai-personalization-tools/" rel="noopener noreferrer"&gt;Insider&lt;/a&gt;&lt;/strong&gt; — AI-powered personalization tool for websites, apps, email, and more.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: Medium complexity, requires data infrastructure and expertise.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. AR and VR Shopping Experiences
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2F2b1ki4ob3dnfky0y5xnp.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.amazonaws.com%2Fuploads%2Farticles%2F2b1ki4ob3dnfky0y5xnp.png" alt="AR and VR in eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discover how &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#22-ar-and-vr-bringing-online-shopping-to-life" rel="noopener noreferrer"&gt;AR and VR are Bringing Online Shopping to Life&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;AR and VR technologies bring products to life, allowing customers to virtually try on products or visualize them in their environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Reduced returns, increased customer confidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: Dress shops can use VR to allow customers to try on dresses virtually before purchasing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.zakeke.com/" rel="noopener noreferrer"&gt;Zakeke&lt;/a&gt;&lt;/strong&gt; — 3D product configurator and customizer plugin for eCommerce, allowing customers to craft their dream products.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.threekit.com/" rel="noopener noreferrer"&gt;Threekit&lt;/a&gt;&lt;/strong&gt; — Visual product configurator for brands and manufacturers, enabling 3D configuration, virtual photography, and augmented reality.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: High complexity, requires AR/VR development skills.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Omnichannel Retail Integration
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fzfwu1g5pmrx5cpu4uljp.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.amazonaws.com%2Fuploads%2Farticles%2Fzfwu1g5pmrx5cpu4uljp.png" alt="Omnichannel eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explore how &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#23-omnichannel-retail-blending-online-and-offline-shopping" rel="noopener noreferrer"&gt;Omnichannel Retail is Blending Online and Offline Shopping&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Omnichannel strategies blend online and offline shopping, providing a seamless experience across all platforms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Improved customer loyalty, consistent brand experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: A local bookstore can integrate online and offline shopping for a unified customer experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://help.shopify.com/en/manual/intro-to-shopify/pricing-plans/plans-features/shopify-plus-plan" rel="noopener noreferrer"&gt;Shopify Plus&lt;/a&gt;&lt;/strong&gt; — Offers features like unlimited staff accounts, customizable checkout, and expansion stores to support high-volume businesses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://magicfuse.co/blog/what-is-salesforce-commerce-cloud/" rel="noopener noreferrer"&gt;Salesforce Commerce Cloud&lt;/a&gt;&lt;/strong&gt; — Provides tools, mobile frameworks, and features to create responsive eCommerce websites and deliver personalized customer experiences across channels.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: Medium complexity, requires unified data management.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Data-Driven Personalization
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2F4cay12258hrcrbugnjjk.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.amazonaws.com%2Fuploads%2Farticles%2F4cay12258hrcrbugnjjk.png" alt="Data in eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find out more about &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#24-getting-personal-using-data-to-improve-shopping-experiences" rel="noopener noreferrer"&gt;Using Data to Improve Shopping Experiences&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Utilizing customer data to create personalized shopping experiences enhances engagement and satisfaction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Better customer insights, increased sales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: A coffee shop can tailor its offerings based on customer purchase history and preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://segment.com/" rel="noopener noreferrer"&gt;Segment&lt;/a&gt;&lt;/strong&gt; — Customer data platform that collects, unifies, and activates customer data across the stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.optimizely.com/" rel="noopener noreferrer"&gt;Optimizely&lt;/a&gt;&lt;/strong&gt; — Digital experience platform that enables A/B testing, feature flagging, and personalization.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: Medium complexity, requires robust data analytics capabilities.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  5. Advanced Delivery Solutions
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fq5008qhs9xnf4wgcrfur.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.amazonaws.com%2Fuploads%2Farticles%2Fq5008qhs9xnf4wgcrfur.png" alt="Delivery in eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn about &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#25-getting-your-stuff-faster-the-future-of-delivery" rel="noopener noreferrer"&gt;The Future of Delivery&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Innovations in last-mile delivery, such as autonomous vehicles and drone deliveries, speed up and streamline the delivery process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Faster deliveries, reduced costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: A local grocery store can offer drone deliveries for quicker and more efficient service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.starship.xyz/" rel="noopener noreferrer"&gt;Starship Technologies&lt;/a&gt;&lt;/strong&gt; — Autonomous robot delivery service that makes food and package deliveries more efficient, convenient, and sustainable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://mttr.net/" rel="noopener noreferrer"&gt;Matternet&lt;/a&gt;&lt;/strong&gt; — Drone delivery platform that enables on-demand delivery of medical supplies and other goods.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: High complexity, regulatory challenges.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. Mobile Commerce Expansion
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fpugsyzonnxgc6mmz15z0.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.amazonaws.com%2Fuploads%2Farticles%2Fpugsyzonnxgc6mmz15z0.png" alt="Mobile eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explore &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#26-shopping-in-your-pocket-the-mobile-commerce-boom" rel="noopener noreferrer"&gt;The Mobile Commerce Boom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The rise of mobile commerce is supported by technologies like Progressive Web Apps (PWAs) and mobile payment solutions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Higher conversion rates, improved user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: Small boutiques can leverage mobile commerce to reach customers on the go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://stripe.com/" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt;&lt;/strong&gt; — Online payment processing platform that supports mobile payments, including Apple Pay and Google Pay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.braintreepayments.com/" rel="noopener noreferrer"&gt;Braintree&lt;/a&gt;&lt;/strong&gt; — PayPal-owned payment gateway that offers mobile SDKs and supports one-touch checkout.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: Low complexity, primarily front-end development.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  7. Subscription-Based Models
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fvn0brxrq3kxyjhrookpl.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.amazonaws.com%2Fuploads%2Farticles%2Fvn0brxrq3kxyjhrookpl.png" alt="Subscription in eCommerce" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn more about &lt;a href="https://focusreactive.com/modern-ecommerce-architecture-trends-and-services-a-comprehensive-guide/#27-subscription-based-e-commerce-models" rel="noopener noreferrer"&gt;Subscription-Based E-Commerce Models&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Subscription services offer predictable revenue and personalized customer experiences through curated product boxes and digital content.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Recurring revenue, increased customer retention.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive Edge&lt;/strong&gt;: Beauty product stores can offer subscription boxes with personalized selections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://getrecharge.com/features/" rel="noopener noreferrer"&gt;ReCharge&lt;/a&gt;&lt;/strong&gt; — Subscription management platform that powers recurring orders for over 100 million subscribers globally, offering features like custom checkout domains and discount code analytics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://boldcommerce.com/shopify/subscriptions" rel="noopener noreferrer"&gt;Bold Subscriptions&lt;/a&gt;&lt;/strong&gt; — Shopify app that enables subscription-based business models, with features like recurring payments, subscriber management, and flexible subscription options.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration&lt;/strong&gt;: Medium complexity, requires subscription management systems.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;We are thrilled to share our insights and knowledge with you. For more in-depth content, visit our blog on &lt;a href="https://focusreactive.com/blog/category/headless-commerce/" rel="noopener noreferrer"&gt;Headless Commerce&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>storefront</category>
      <category>ecommerce</category>
      <category>webdev</category>
      <category>composable</category>
    </item>
    <item>
      <title>How to Survive If You Still Have a Traditional CMS</title>
      <dc:creator>Oleg Proskurin</dc:creator>
      <pubDate>Mon, 12 Aug 2024 06:16:39 +0000</pubDate>
      <link>https://forem.com/focusreactive/how-to-survive-if-you-still-have-a-traditional-cms-1860</link>
      <guid>https://forem.com/focusreactive/how-to-survive-if-you-still-have-a-traditional-cms-1860</guid>
      <description>&lt;p&gt;Let's face it: if you're still using a traditional CMS like Drupal, you're basically riding a dinosaur in the age of electric cars. Sure, it gets the job done (sort of), but is it really the best you can do for your business? It's time to talk about headless CMS and why you should make the switch before your competitors leave you in the dust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Traditional CMS Is Becoming Obsolete
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lack of Flexibility&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Traditional CMS platforms tie your content and presentation together, making it tough to deliver content across different platforms. Want to reuse that fantastic blog post for your app? Good luck!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Issues&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Monolithic systems can be slow, and in today's fast-paced world, a slow website is a sure way to lose visitors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Vulnerabilities&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Traditional CMS platforms are frequent targets for hackers. With every new plugin or update, there's a potential new security hole.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability Challenges&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
As your business grows, your CMS needs to grow too. Traditional CMS often struggle with scaling efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inconsistent Omnichannel Experience&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Providing a consistent experience across various channels (web, mobile, IoT) is a nightmare with traditional CMS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Competitive Advantages of Switching to Headless CMS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Flexibility and Freedom&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Headless CMS separates the backend from the frontend, allowing developers to use any technology stack they prefer. This means you can deliver content wherever and however you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Performance&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
APIs deliver content quickly, ensuring your users enjoy a fast and seamless experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved Security&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Decoupling the backend from the frontend minimizes security risks. Updates can be made without breaking the frontend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Scalability&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Headless CMS can grow with your business. Adding new content types or channels is a breeze.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Omnichannel Experience&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Easily repurpose and distribute content across multiple platforms, ensuring a unified brand experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple and Painless Migration Options
&lt;/h3&gt;

&lt;p&gt;Ready to make the switch? Here are some modern headless CMS options to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sanity&lt;/strong&gt;: Known for its real-time collaboration and flexible content modeling. &lt;a href="https://focusreactive.com/migration-from-drupal/#sanity" rel="noopener noreferrer"&gt;Sanity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storyblok&lt;/strong&gt;: Offers a visual editor and a component-based approach for creating reusable content blocks. &lt;a href="https://focusreactive.com/migration-from-drupal/#storyblok" rel="noopener noreferrer"&gt;Storyblok&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contentful&lt;/strong&gt;: Provides a robust API and extensive integration capabilities. &lt;a href="https://focusreactive.com/migration-from-drupal/#contentful" rel="noopener noreferrer"&gt;Contentful&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directus&lt;/strong&gt;: An open-source option that offers a dynamic API and customizable dashboard. &lt;a href="https://focusreactive.com/migration-from-drupal/#directus" rel="noopener noreferrer"&gt;Directus&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload&lt;/strong&gt;: Focuses on developer experience with a fully extendable and customizable backend. &lt;a href="https://focusreactive.com/migration-from-drupal/#payload-cms" rel="noopener noreferrer"&gt;Payload&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, we strongly recommend working with an experienced agency to ensure a smooth and successful migration. These experts can help you navigate the complexities and get your new system up and running without a hitch.&lt;/p&gt;

&lt;p&gt;Headless CMS is transforming the way we manage and deliver content. By adopting this modern approach, businesses can achieve greater flexibility, performance, and security while scaling seamlessly across multiple channels. For a comprehensive guide on migrating from Drupal to a headless CMS, check out the full article &lt;a href="https://focusreactive.com/migration-from-drupal/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cms</category>
      <category>headless</category>
      <category>migration</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
