<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Storyblok</title>
    <description>The latest articles on DEV Community by Storyblok (@storyblok).</description>
    <link>https://dev.to/storyblok</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%2F1739%2Fb33cb57b-b916-455f-a576-1fc490b5d104.jpeg</url>
      <title>DEV Community: Storyblok</title>
      <link>https://dev.to/storyblok</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/storyblok"/>
    <language>en</language>
    <item>
      <title>Designing Content Systems that Understand and Act</title>
      <dc:creator>Siddharth Dayalwal</dc:creator>
      <pubDate>Sat, 21 Mar 2026 04:16:19 +0000</pubDate>
      <link>https://dev.to/storyblok/designing-content-systems-that-understand-and-act-5fal</link>
      <guid>https://dev.to/storyblok/designing-content-systems-that-understand-and-act-5fal</guid>
      <description>&lt;p&gt;Modern JavaScript applications don’t just render UI anymore. They orchestrate search, personalization, analytics, AI services, localization workflows, and multi-channel publishing. And underneath all of it sits content.&lt;/p&gt;

&lt;p&gt;The problem is that most teams still treat content like static data, something you store, fetch, render, and then forget. That model worked when applications were simple. It breaks down when your system needs to reason about content, react to it, and automate around it.&lt;/p&gt;

&lt;p&gt;If publishing a page triggers five scripts, three webhooks, and two background jobs, you’re not managing content anymore, you are managing side effects.&lt;/p&gt;

&lt;p&gt;To scale without increasing fragility, content systems need to evolve in three ways: they need to &lt;strong&gt;understand meaning, react to events, and orchestrate durable workflows&lt;/strong&gt;. In this article, we’ll explore these three pillars and how they shape the architecture of modern, AI-native content systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI-Native actually means
&lt;/h2&gt;

&lt;p&gt;When people talk about AI-native systems, they often imagine assistants in the UI. But AI becomes far more useful when it’s embedded deeper in the architecture. &lt;/p&gt;

&lt;p&gt;For AI to work effectively in a content system, three capabilities are required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Meaning&lt;/strong&gt;, so AI can understand what content represents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Events&lt;/strong&gt;, so the system knows when something changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflows&lt;/strong&gt;, so AI output can trigger real actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without meaning, AI cannot reason about content. Without events, it doesn’t know when to act. Without workflows, its output has nowhere to go. These three capabilities turn a traditional CMS into an AI-native content system.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Store Meaning, Not Just Fields
&lt;/h2&gt;

&lt;p&gt;Traditional CMS architectures are built around fields: title, body, tags, metadata, and more. Search relies on keywords, and filters rely on attributes. When other systems need smarter logic, they rebuild their own interpretation of the content. Over time this leads to duplicated logic across the stack. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A semantic layer changes this&lt;/strong&gt;. *&lt;strong&gt;*Instead of representing content only through fields, the system also represents it through **meaning&lt;/strong&gt;; often using embeddings or vector indexing. This shared semantic representation allows different systems to operate from the same understanding of content. The same layer can power search relevance, AI agents, internal tools, and backend services. Meaning is modeled once and reused everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Publish Is a Signal
&lt;/h2&gt;

&lt;p&gt;Publishing content isn’t the end of a workflow. It’s a &lt;strong&gt;signal&lt;/strong&gt;. Content state changes usually trigger multiple processes: indexing, notifications, AI tagging, localization, or distribution. Many teams handle this through webhook chains or scripts. That works initially, but it becomes fragile as complexity grows. An event-driven approach scales better. &lt;/p&gt;

&lt;p&gt;Instead of embedding logic in the publish action, the system emits an event that other services can subscribe to. A simplified example might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// publish-content.js&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;eventBus&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;./eventBus.js&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;publishContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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;await&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&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;eventBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content.published&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locale&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;Subscribers can then react to that event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ai-tagging.js&lt;/span&gt;
&lt;span class="nx"&gt;eventBus&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;content.published&lt;/span&gt;&lt;span class="dl"&gt;"&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;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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;aiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;autoTag&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;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;// localization.js&lt;/span&gt;
&lt;span class="nx"&gt;eventBus&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;content.published&lt;/span&gt;&lt;span class="dl"&gt;"&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;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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;localizationWorkflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&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;id&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;Each responsibility remains isolated. New capabilities can subscribe without modifying existing logic. For JavaScript teams already familiar with event-driven systems, this pattern feels natural. Applying it to content workflows simply brings the same architectural discipline to another layer of the stack. &lt;strong&gt;Events scale. Scripts chains don’t.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is also where workflow automation tools begin to matter. Instead of wiring scripts together manually, modern systems are starting to orchestrate reactions visually. Features like &lt;a href="https://www.storyblok.com/lp/flowmotion" rel="noopener noreferrer"&gt;Storyblok FlowMotion&lt;/a&gt; allow teams to trigger structured workflows from content events, turning what used to be invisible automation into something observable and maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Orchestrate, Don’t Glue
&lt;/h2&gt;

&lt;p&gt;As systems grow, workflows become more complex. Publishing a piece of content might involve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AI classification&lt;/li&gt;
&lt;li&gt;Human review&lt;/li&gt;
&lt;li&gt;Localization&lt;/li&gt;
&lt;li&gt;Multi-channel distribution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If these steps live across scattered scripts, the process becomes hard to understand and maintain. Workflow orchestration solves this by making the process explicit.&lt;/p&gt;

&lt;p&gt;Instead of chaining handlers together, the system defines a clear workflow where each step has visible state. AI actions, human approvals, and system tasks all exist within the same flow. This makes automation easier to observe, easier to debug, and safer to evolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Systems, Not Side Effects
&lt;/h2&gt;

&lt;p&gt;JavaScript developers already understand APIs, events, and distributed systems. Applying the same architectural thinking to content unlocks a more resilient approach. When content systems model meaning, emit events, and orchestrate workflows, something important changes. &lt;/p&gt;

&lt;p&gt;Content stops being passive data. It becomes an active participant in the system, something that can &lt;strong&gt;understand context, trigger actions, and move through intelligent processes&lt;/strong&gt;. That’s the difference between static content and a living content system.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building a Custom Calendar with React + Storyblok: A Recap of Our Bryntum Integration Tutorial</title>
      <dc:creator>Siddharth Dayalwal</dc:creator>
      <pubDate>Fri, 12 Dec 2025 12:24:03 +0000</pubDate>
      <link>https://dev.to/storyblok/building-a-custom-calendar-with-react-storyblok-a-recap-of-our-bryntum-integration-tutorial-582k</link>
      <guid>https://dev.to/storyblok/building-a-custom-calendar-with-react-storyblok-a-recap-of-our-bryntum-integration-tutorial-582k</guid>
      <description>&lt;p&gt;At Storyblok, we love collaborating with teams building exceptional frontend experiences. Recently, we partnered again with &lt;a href="https://bryntum.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Bryntum&lt;/strong&gt;&lt;/a&gt; to bring you a hands-on tutorial on &lt;strong&gt;creating a custom &lt;a href="https://bryntum.com/products/calendar/" rel="noopener noreferrer"&gt;Bryntum Calendar&lt;/a&gt; React component for Storyblok&lt;/strong&gt;. This guide is great for React developers who want to integrate advanced UI components without building them from scratch, and for Storyblok users to make their interfaces mode dynamic and content-driven.&lt;/p&gt;

&lt;p&gt;To follow along, you will just need a basic React setup (React 18+), a Storyblok space with the React SDK, and access to the Bryntum Calendar (trial or license). Once you have these in place, the tutorial walks you through connecting structured Storyblok content to a fully-featured calendar UI in a straightforward and developer-friendly way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dive straight into the tutorial: Check out the complete guide on Integrating Bryntum Calendar + Storyblok + React Component&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Bryntum + Storyblok Works So Well
&lt;/h2&gt;

&lt;p&gt;Bryntum builds &lt;strong&gt;high-performance visual UI components&lt;/strong&gt;, including calendars, schedulers, and Gantt charts, that solve problems developers rarely want to rebuild from scratch. A calendar UI, in particular, hides a surprising amount of complexity: time zones, navigation, layouts, event logic, conflict resolution… the list goes on.&lt;/p&gt;

&lt;p&gt;Storyblok complements this perfectly with its &lt;strong&gt;headless CMS&lt;/strong&gt;, offering structured content, visual editing, and a schema that adapts to whatever your project needs.&lt;/p&gt;

&lt;p&gt;Together, they give you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fully functional &lt;strong&gt;calendar interface&lt;/strong&gt; powered by Bryntum&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;content-driven configuration layer&lt;/strong&gt; using Storyblok&lt;/li&gt;
&lt;li&gt;A smooth &lt;strong&gt;React developer experience&lt;/strong&gt; with the Storyblok React SDK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s the best of both worlds: editors manage content, while your components handle the logic.&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%2Fv0p4gdxzi6p5mmah9m6g.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%2Fv0p4gdxzi6p5mmah9m6g.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What You’ll Learn in Bryntum’s Tutorial
&lt;/h2&gt;

&lt;p&gt;This tutorial walks you step-by-step through building a working calendar UI using &lt;strong&gt;React, Storyblok, and Bryntum Calendar&lt;/strong&gt;. Here’s what you’ll take away:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. A Ready-to-Use Calendar Component&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Bryntum handles layout, event rendering, drag-and-drop interactions, and multiple views so you can focus on integrating, and not rebuilding the core functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Fetching and Rendering Storyblok Content in React&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You’ll learn how to work with Storyblok’s React SDK using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useStoryblokState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apiPlugin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a custom Storyblok client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These help you connect Storyblok entries (like Events or Calendars) directly to Bryntum’s configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Mapping CMS Content to Bryntum’s Data Model&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Bryntum Calendar expects a specific schema. The tutorial shows how to map Storyblok’s structured content to Bryntum’s data stores, an essential skill when building headless, UI-heavy applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Using Storyblok’s Visual Editor With Custom Components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You’ll integrate your calendar into the Visual Editor through the &lt;code&gt;StoryblokComponent&lt;/code&gt; renderer so editors can preview updates instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. A Clean, Reusable Integration Pattern&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By the end, you’ll have a self-contained React component that reads from Storyblok and renders a fully interactive Bryntum calendar. No hacks. No unnecessary complexity. Just a clean, scalable pattern you can reuse across projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for Developers
&lt;/h2&gt;

&lt;p&gt;Building a production-ready calendar UI is notoriously difficult and maintaining it is even harder.&lt;/p&gt;

&lt;p&gt;This tutorial gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A battle-tested calendar component you don’t need to rebuild&lt;/li&gt;
&lt;li&gt;A consistent data flow powered by Storyblok&lt;/li&gt;
&lt;li&gt;A scalable integration pattern you can apply to other Bryntum components&lt;/li&gt;
&lt;li&gt;A way to empower editors without sacrificing structure or performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building dashboards, booking systems, internal tools, or anything time or event-based, this integration gives you a huge head start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to Try It Out?
&lt;/h2&gt;

&lt;p&gt;If you want to explore how Storyblok and Bryntum work together in a real project, this tutorial is the perfect starting point. Try the build yourself, explore the code, and experiment with your own content types. You’ll learn a lot along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources &amp;amp; Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read the full tutorial&lt;/strong&gt;: &lt;a href="https://bryntum.com/blog/creating-a-custom-bryntum-calendar-react-component-for-storyblok/" rel="noopener noreferrer"&gt;Creating a custom Bryntum Calendar React component for Storyblok&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore the completed code&lt;/strong&gt;: &lt;a href="https://github.com/bryntum/bryntum-calendar-storyblok-quick-start/tree/completed-app" rel="noopener noreferrer"&gt;GitHub repository for the tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Join the &lt;a href="https://www.storyblok.com/join-discord" rel="noopener noreferrer"&gt;Storyblok Discord Community&lt;/a&gt;: Connect with other developers working on exciting projects.&lt;/li&gt;
&lt;li&gt;Read the earlier guide: &lt;a href="https://www.storyblok.com/mp/mastering-scheduling-and-gantt-charting-a-recap-of-bryntum-s-guide" rel="noopener noreferrer"&gt;Building a Bryntum Gantt UI component with React and Storyblok&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>storyblok</category>
      <category>react</category>
      <category>calendar</category>
      <category>component</category>
    </item>
    <item>
      <title>Global Financial Starter: Multilingual Template – Bejamas x Storyblok, Powered by Astro</title>
      <dc:creator>Siddharth Dayalwal</dc:creator>
      <pubDate>Wed, 17 Sep 2025 10:30:00 +0000</pubDate>
      <link>https://dev.to/storyblok/global-financial-starter-multilingual-template-bejamas-x-storyblok-powered-by-astro-5495</link>
      <guid>https://dev.to/storyblok/global-financial-starter-multilingual-template-bejamas-x-storyblok-powered-by-astro-5495</guid>
      <description>&lt;p&gt;Exciting news for Astro and Storyblok fans! With our friends at &lt;a href="https://bejamas.com/" rel="noopener noreferrer"&gt;Bejamas&lt;/a&gt;, we’ve launched the &lt;strong&gt;Global Financial Starter: Multilingual Template&lt;/strong&gt;, a production-ready Astro and Storyblok project that delivers fast, compliant, and global online presence for international sites.&lt;/p&gt;

&lt;p&gt;Whether you're a frontend team, an agency, or a solo developer, this starter is designed to help you spin up multilingual websites for financial brands, campaigns, or products.&lt;/p&gt;

&lt;p&gt;Storyblok and Bejamas share the same mission–to make it easier for developers to launch global digital experiences without compromising performance and flexibility. This starter is the result of one such partnership. It's not just a showcase, but a project you can clone, adapt, and ship to production.&lt;/p&gt;

&lt;p&gt;Keep reading to learn about the template's features, how it works, and how to get started building with it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Curious already? &lt;a href="https://astro-storyblok-finance-starter.netlify.app/" rel="noopener noreferrer"&gt;Explore the live demo&lt;/a&gt; before you dive in.&lt;/p&gt;
&lt;/blockquote&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%2Foq63nql735kia5xagval.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%2Foq63nql735kia5xagval.webp" alt="Global Financial Starter: Multilingual Template" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;Go from zero to a live project in minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork and clone the &lt;a href="https://github.com/bejamas/astro-storyblok-finance-starter" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign up to Storyblok and create a new space&lt;/li&gt;
&lt;li&gt;&lt;a href="https://astro-storyblok-finance-starter.netlify.app/.netlify/functions/clone-storyblok-space" rel="noopener noreferrer"&gt;Clone the Storyblok Space&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install dependencies and setup environment variables&lt;/li&gt;
&lt;li&gt;Create your project on Netlify and deploy!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To kick-start your project, follow the step-by-step guide on the &lt;a href="https://astro.build/themes/details/global-financial-starter-multilingual-template/" rel="noopener noreferrer"&gt;&lt;strong&gt;Astro Template page&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The highlights
&lt;/h2&gt;

&lt;p&gt;The Global Financial Starter is built with a modern, headless stack designed for performance, scalability, and ease of use: Astro, Storyblok, Netlify, and PostHog.&lt;/p&gt;

&lt;p&gt;It comes pre-configured with the essential features your team needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular content model&lt;/strong&gt; – pre-built blocks like hero, services, reports, testimonials, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial reports&lt;/strong&gt; – a dedicated content type with a report list page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual by default&lt;/strong&gt; – built-in language switcher with optional AI-assisted translations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual editing&lt;/strong&gt; – live preview with Storyblok’s block-based approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO ready&lt;/strong&gt; – every page includes metadata fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized performance&lt;/strong&gt; – responsive images, static output, and &lt;a href="https://pagespeed.web.dev/analysis/https-astro-storyblok-finance-starter-netlify-app/41ym06mwtn?form_factor=desktop" rel="noopener noreferrer"&gt;https://pagespeed.web.dev/analysis/https-astro-storyblok-finance-starter-netlify-app/41ym06mwtn?form_factor=desktop&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A/B testing&lt;/strong&gt; – PostHog integration to run experiments and A/B tests without extra setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  See it in action
&lt;/h2&gt;

&lt;p&gt;Don’t just take our word for it, explore the starter yourself with a &lt;a href="https://astro-storyblok-finance-starter.netlify.app/" rel="noopener noreferrer"&gt;live demo site&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=2hPhwubis7Q" rel="noopener noreferrer"&gt;watch a demo video on YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show us what you got
&lt;/h2&gt;

&lt;p&gt;We bring you this starter with Bejamas so you can move faster when building multilingual landing pages, creating campaign microsites, or scaling a global financial brand.&lt;/p&gt;

&lt;p&gt;Try it today, experiment with it, and let us know what you think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contributions on &lt;a href="https://github.com/bejamas/astro-storyblok-finance-starter" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; are welcome: issues, PRs, or any other feedback.&lt;/li&gt;
&lt;li&gt;Join the &lt;a href="https://www.storyblok.com/join-discord" rel="noopener noreferrer"&gt;Storyblok Discord&lt;/a&gt; community and share what you build.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Related resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.storyblok.com/docs/guides/astro/" rel="noopener noreferrer"&gt;Integrate Astro with Storyblok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storyblok/blueprint-core-astro" rel="noopener noreferrer"&gt;Storyblok's Astro blueprint repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.storyblok.com/docs/packages/storyblok-astro" rel="noopener noreferrer"&gt;Storyblok Astro SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>multilingual</category>
      <category>financial</category>
      <category>storyblok</category>
      <category>astro</category>
    </item>
    <item>
      <title>Introducing Storyblok CLI v4</title>
      <dc:creator>Alvaro Saburido</dc:creator>
      <pubDate>Thu, 19 Jun 2025 14:00:00 +0000</pubDate>
      <link>https://dev.to/storyblok/introducing-storyblok-cli-v4-2gdh</link>
      <guid>https://dev.to/storyblok/introducing-storyblok-cli-v4-2gdh</guid>
      <description>&lt;p&gt;An &lt;strong&gt;enterprise-ready&lt;/strong&gt;, open-source command line to leverage complex operations on top of Storyblok’s Management API with a friendly and renovated interface. &lt;/p&gt;

&lt;p&gt;Today, we’re launching &lt;strong&gt;Storyblok CLI v4, a complete rebirth of our developer toolkit&lt;/strong&gt; built for the scale, performance, and polish that modern enterprises expect, yet intuitive and fun for every developer who interacts with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features you will love ✨
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Full make-over
&lt;/h3&gt;

&lt;p&gt;Who said command line interfaces need to be plain and boring 😜? We present you with a new design for this version.&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%2Fly5a2l3g4fo78pinu6vy.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%2Fly5a2l3g4fo78pinu6vy.png" alt="Image showing the new design for the Storyblok CLI v4" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Color-coded domain badges&lt;/strong&gt; – instantly see whether you’re in Components, Migrations, or Types land.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time progress spinners&lt;/strong&gt; + timing – watch each step finish and know exactly how long it took.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success/error icons at a glance&lt;/strong&gt; – ✅ for done, ❌ for issues, with zero &lt;code&gt;[Object object]&lt;/code&gt; noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy-paste-ready paths&lt;/strong&gt; – the CLI prints where files were saved (e.g. &lt;code&gt;.storyblok/components/…&lt;/code&gt;), so you can jump there in one click.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readable in any theme&lt;/strong&gt; – tested on dark, light, and high-contrast terminals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent typography &amp;amp; padding&lt;/strong&gt; – no more jittery line breaks when you resize the window.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Domain-first command design
&lt;/h2&gt;

&lt;p&gt;The new &lt;code&gt;storyblok &amp;lt;domain&amp;gt; &amp;lt;verb&amp;gt;&lt;/code&gt; format keeps related actions together and makes discovery a breeze.&lt;/p&gt;

&lt;p&gt;For example, imagine you need to pull components from a space (&lt;strong&gt;1234&lt;/strong&gt;), make local changes, and then push them to a second space (&lt;strong&gt;5678&lt;/strong&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;storyblok components pull &lt;span class="nt"&gt;--space&lt;/span&gt; 1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command saves your space components in a dedicated local &lt;code&gt;.storyblok&lt;/code&gt; folder. You can later push these changes to our target space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;storyblok components push &lt;span class="nt"&gt;--space&lt;/span&gt; 5678 &lt;span class="nt"&gt;--from&lt;/span&gt; 1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Granular, precision-targeted operations
&lt;/h2&gt;

&lt;p&gt;Ship exactly what you intend. Nothing more, nothing less.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use-case&lt;/th&gt;
&lt;th&gt;What it looks like&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Push a &lt;strong&gt;single component&lt;/strong&gt; to production&lt;/td&gt;
&lt;td&gt;&lt;code&gt;storyblok components push button --space 78910&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sync &lt;strong&gt;only components matching a glob&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;storyblok components pull "marketing-*" --space 78910&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run a migration on &lt;strong&gt;stories matching a query&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;storyblok migrations run --query "[highlighted][in]=true" --space 78910&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Combine filters &amp;amp; dry-run&lt;/td&gt;
&lt;td&gt;&lt;code&gt;storyblok migrations run  --starts-with "/en/blog/" --dry-run&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These scoped commands are CI-friendly, lightning-fast, and reduce “blast radius” during hot-fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. File Organization that sparks joy
&lt;/h2&gt;

&lt;p&gt;Good-bye, root-folder clutter. All artifacts now live under a tidy &lt;strong&gt;&lt;code&gt;.storyblok&lt;/code&gt;&lt;/strong&gt; directory  organised by space, by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.storyblok/
├─ components/
        └── YOUR_SPACE_ID/
                ├── components.json      # All components
                ├── groups.json         # Component groups
                ├── presets.json        # Component presets
                └── tags.json           # Component tags
├─ migrations/
└─ types/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can keep them version-controlled for traceability, or add a single line to &lt;code&gt;.gitignore&lt;/code&gt;. Override paths if you need something bespoke by using the &lt;code&gt;--path&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Sign-up directly from the CLI
&lt;/h2&gt;

&lt;p&gt;First-time user? Kick things off with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;storyblok signup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;storyblok signup&lt;/code&gt; command opens a secure registration page in &lt;strong&gt;your default browser&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;storyblok login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it, you’re ready to pull components or run your first migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Better error handling &amp;amp; support
&lt;/h3&gt;

&lt;p&gt;Remember those &lt;code&gt;[Object object]&lt;/code&gt; stack traces? Use &lt;code&gt;—verbose&lt;/code&gt; to get full error details&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;storyblok components push hero-banner &lt;span class="nt"&gt;--space&lt;/span&gt; 5678 &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actions now yield errors like the example below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; 

&lt;/span&gt;&lt;span class="err"&gt;▲&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hero-banner"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;found.&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="err"&gt;▲&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Error:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hero-banner"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;found.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Error'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;message:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hero-banner"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;found.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;stack:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Error:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hero-banner"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;found.\n'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Command.&amp;lt;anonymous&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(file:///Users/alvarosabu/Projects/storyblok/storyblok-cli-next/dist/index.mjs:&lt;/span&gt;&lt;span class="mi"&gt;2206&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="err"&gt;)'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Actionable logs&lt;/strong&gt; – perfect for CI pipelines or reporting an issue on &lt;a href="https://www.storyblok.com/trust-center/service-support" rel="noopener noreferrer"&gt;Support&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart retries &amp;amp; back-off&lt;/strong&gt; – long jobs finish even on flaky networks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict typing&lt;/strong&gt; – predictable error objects your scripts can catch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migrating from v3 in one minute 🕒
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Commands structure
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;v3 command&lt;/th&gt;
&lt;th&gt;v4 command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pull-components&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;components pull&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;push-components&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;components push&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generate-migration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;migrations generate&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;run-migration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;migrations run&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generate-typescript-typedefs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;types generate&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Swap &lt;strong&gt;verb-domain →  &lt;/strong&gt;, check all the available flags using &lt;code&gt;--help&lt;/code&gt;, and you’re done.&lt;/p&gt;

&lt;p&gt;For a full overview of all commands available, please refer to the &lt;a href="https://github.com/storyblok/storyblok-cli/blob/next/src/README.md#api" rel="noopener noreferrer"&gt;API README in the CLI repository&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about the old &lt;code&gt;sync&lt;/code&gt; command?
&lt;/h3&gt;

&lt;p&gt;This command has &lt;strong&gt;not&lt;/strong&gt; made the jump to v4.&lt;/p&gt;

&lt;p&gt;We’re currently re-imagining it as a brand-new, server-side endpoint that will deliver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster synchronization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;higher reliability&lt;/strong&gt; (the heavy lifting runs on our backend),&lt;/li&gt;
&lt;li&gt;Better handling of large-scale operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until that ships you have two options:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Recommended approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Schema-only transfer&lt;/strong&gt; (components, groups, tags, presets)&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;components pull&lt;/code&gt; from the source space, commit the files (or keep them local), then &lt;code&gt;components push&lt;/code&gt; to the target space.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Full “everything” sync&lt;/strong&gt; (stories, folders, roles, datasources)&lt;/td&gt;
&lt;td&gt;Stay on CLI v3 for this specific job: &lt;code&gt;npm i -g storyblok@v3.36.1&lt;/code&gt; and keep following the v3 docs. &lt;a href="https://github.com/storyblok/storyblok-cli/raw/next/src/README.md" rel="noopener noreferrer"&gt;github.com&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We’ll announce the new &lt;code&gt;sync&lt;/code&gt; as soon as the new API endpoint is live—watch this space!&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started today
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; storyblok@latest          &lt;span class="c"&gt;# install v4&lt;/span&gt;

storyblok signup &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; storyblok login     &lt;span class="c"&gt;# onboard and authenticate&lt;/span&gt;
storyblok &lt;span class="nt"&gt;--help&lt;/span&gt;                        &lt;span class="c"&gt;# explore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Found a bug? Want to help shape the future?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Report issues &amp;amp; feature requests&lt;/strong&gt; – open a ticket in our GitHub tracker&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/storyblok/monoblok/issues" rel="noopener noreferrer"&gt;https://github.com/storyblok/monoblok/issues&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feeling adventurous?&lt;/strong&gt; Fork the repository, follow the contributor setup in the root &lt;code&gt;README.md&lt;/code&gt;, and submit a pull-request. We review PRs weekly and love community contributions!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to enjoy faster workflows and world-class support?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Storyblok CLI v4 now&lt;/strong&gt; and see what an enterprise-ready command line feels like. 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Announcing Storyblok Svelte SDK v5: now fully compatible with Svelte 5</title>
      <dc:creator>Edoardo Dusi</dc:creator>
      <pubDate>Mon, 28 Apr 2025 09:34:22 +0000</pubDate>
      <link>https://dev.to/storyblok/announcing-storyblok-svelte-sdk-v5-now-fully-compatible-with-svelte-5-3j3i</link>
      <guid>https://dev.to/storyblok/announcing-storyblok-svelte-sdk-v5-now-fully-compatible-with-svelte-5-3j3i</guid>
      <description>&lt;p&gt;We're thrilled to announce the release of &lt;a href="https://github.com/storyblok/storyblok-svelte" rel="noopener noreferrer"&gt;storyblok-svelte v5&lt;/a&gt;, a complete refactoring of our dedicated SDK built specifically for Svelte 5 and its &lt;a href="https://svelte.dev/blog/runes" rel="noopener noreferrer"&gt;runes system&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This new version takes full advantage of Svelte's latest innovations to provide you with the most powerful, developer-friendly tools to integrate your Storyblok content into your Svelte applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embracing the future with Svelte 5
&lt;/h2&gt;

&lt;p&gt;Svelte always stood out for its compiler-focused approach that delivers exceptional performance with minimal runtime overhead.&lt;/p&gt;

&lt;p&gt;With the introduction of &lt;strong&gt;runes&lt;/strong&gt;, the framework took another leap forward into simplicity and power.&lt;/p&gt;

&lt;p&gt;As passionate supporters of the Svelte ecosystem, we've &lt;a href="https://github.com/storyblok/storyblok-svelte/pull/1127" rel="noopener noreferrer"&gt;completely rebuilt our SDK&lt;/a&gt; to embrace these innovations, ensuring that Storyblok users can take full advantage of these new features, while maintaining compatibility with previous versions.&lt;/p&gt;

&lt;p&gt;Let's see what's changed!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleaner component integration
&lt;/h2&gt;

&lt;p&gt;Working with Storyblok components in Svelte 5 is now more elegant than ever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Before (Svelte 4) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;blok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- After (Svelte 5) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;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;blok&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplified syntax makes your components more concise while fully leveraging Svelte 5's reactive system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhanced Rich Text rendering
&lt;/h2&gt;

&lt;p&gt;Our rich text renderer is now fully compatible with Svelte 5's reactivity system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;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;renderRichText&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;@storyblok/svelte&lt;/span&gt;&lt;span class="dl"&gt;'&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;blok&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Automatically updates when content changes&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;richTextContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;renderRichText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blok&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rich text content now updates seamlessly when edited in the Visual Editor without any extra code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seamless Visual Editor experience
&lt;/h2&gt;

&lt;p&gt;The integration with Storyblok's Visual Editor is smoother than ever with our improved &lt;code&gt;storyblokEditable&lt;/code&gt; action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;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;storyblokEditable&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;@storyblok/svelte&lt;/span&gt;&lt;span class="dl"&gt;'&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;blok&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;use:storyblokEditable=&lt;/span&gt;&lt;span class="s"&gt;{blok}&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"feature"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;{blok.headline}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{blok.text}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures your components are properly highlighted while you edit your content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improved error messages
&lt;/h2&gt;

&lt;p&gt;The new error messages will help you solve issues within your integration faster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Component "feature" not found. Please register it in storyblokInit:
storyblokInit({
  accessToken: "&amp;lt;your-token&amp;gt;",
  components: {
    "feature": YourComponent
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of generic messages, you'll now receive helpful guidance on how to fix problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improved TypeScript support
&lt;/h2&gt;

&lt;p&gt;For TypeScript users, we've enhanced our type definitions for better autocomplete and error checking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SbBlokData&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;@storyblok/svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FeatureBlok&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SbBlokData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;headline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;// Type-safe blok access&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;blok&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$props&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;blok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FeatureBlok&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting Started with v5
&lt;/h2&gt;

&lt;p&gt;Ready to upgrade? Here's how to get started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @storyblok/svelte@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update your initialization code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;storyblokInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apiPlugin&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;@storyblok/svelte&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;Feature&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;$lib/Feature.svelte&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;Grid&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;$lib/Grid.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;storyblokInit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;apiPlugin&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Grid&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;For components, update your scripts to use the new Svelte 5 syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;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;storyblokEditable&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;@storyblok/svelte&lt;/span&gt;&lt;span class="dl"&gt;'&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;blok&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;use:storyblokEditable=&lt;/span&gt;&lt;span class="s"&gt;{blok}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;{blok.headline}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{blok.content}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Learn by example
&lt;/h2&gt;

&lt;p&gt;We've created a comprehensive SvelteKit playground that demonstrates all the new features in action.&lt;/p&gt;

&lt;p&gt;Check out our &lt;a href="https://github.com/storyblok/storyblok-svelte" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; to see the example code and learn best practices for building with Storyblok and SvelteKit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking forward
&lt;/h2&gt;

&lt;p&gt;This release reassures our commitment to provide first-class support for modern web frameworks.&lt;/p&gt;

&lt;p&gt;We believe that Svelte's approach to building web applications aligns perfectly with Storyblok's mission to make content management more efficient and enjoyable.&lt;/p&gt;

&lt;p&gt;We're excited to see what you build with this new version of our SDK, and we're already working on more features to improve your Storyblok + Svelte experience.&lt;/p&gt;

&lt;p&gt;For more information, check out our &lt;a href="https://www.storyblok.com/docs" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; or join our &lt;a href="https://discord.gg/jKrbAMz" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; to share your feedback and questions.&lt;/p&gt;

&lt;p&gt;Happy building!&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>storyblok</category>
    </item>
    <item>
      <title>Storyblok unveils new PHP packages in collaboration with SensioLabs</title>
      <dc:creator>Edoardo Dusi</dc:creator>
      <pubDate>Thu, 27 Mar 2025 14:28:40 +0000</pubDate>
      <link>https://dev.to/storyblok/storyblok-unveils-new-php-packages-in-collaboration-with-sensiolabs-khp</link>
      <guid>https://dev.to/storyblok/storyblok-unveils-new-php-packages-in-collaboration-with-sensiolabs-khp</guid>
      <description>&lt;p&gt;At Storyblok, we firmly believe in PHP and the power of open source software. Both have shaped the web as we know it today and continue to be crucial in its evolution.&lt;/p&gt;

&lt;p&gt;That's why we're thrilled to announce that long with our partners &lt;a href="https://sensiolabs.com/" rel="noopener noreferrer"&gt;SensioLabs&lt;/a&gt;, creators of &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt;, we've completely rebuilt our PHP packages from the ground up.&lt;/p&gt;

&lt;p&gt;This collaboration represents more than just an update. It's a complete re-imagining on how PHP developers can interact with Storyblok. By working with SensioLabs, we've ensured these new packages adhere to modern practices, offer excellent Symfony support, and provide a significantly improved developer experience.&lt;/p&gt;

&lt;p&gt;Today, we're announcing four brand-new PHP packages designed to make integrating Storyblok into your projects seamlessly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/storyblok/php-content-api-client" rel="noopener noreferrer"&gt;Content Delivery API Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storyblok/symfony-bundle" rel="noopener noreferrer"&gt;Symfony Bundle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storyblok/php-management-api-client" rel="noopener noreferrer"&gt;Management API Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/storyblok/php-tiptap-extension" rel="noopener noreferrer"&gt;Tiptap Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our previous PHP client and associated packages will be deprecated as we move forward with these improved solutions.&lt;/p&gt;

&lt;p&gt;Let's explore each package and what it brings to the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Delivery API Client
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/storyblok/php-content-api-client" rel="noopener noreferrer"&gt;Content Delivery API Client&lt;/a&gt; is a type-safe PHP SDK designed to retrieve content from Storyblok. It provides an elegant way to interact with your Storyblok space, with built-in support for fetching &lt;strong&gt;stories&lt;/strong&gt;, &lt;strong&gt;links&lt;/strong&gt;, &lt;strong&gt;datasources&lt;/strong&gt;, &lt;strong&gt;tags&lt;/strong&gt;, and &lt;strong&gt;assets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Use this client to easily fetch content for your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\Api\StoriesApi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\Api\StoryblokClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\Api\Request\StoryRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StoryblokClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;baseUri&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;https://api.storyblok.com&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'your_storyblok_token'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$storiesApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StoriesApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$storiesApi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;bySlug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'folder/slug'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StoryRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'de'&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;More advanced features like filtering, pagination, and sorting, are also supported, giving you precise control over the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symfony Bundle
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/storyblok/symfony-bundle" rel="noopener noreferrer"&gt;Storyblok Symfony Bundle&lt;/a&gt; takes integration to the next level for Symfony applications. Developed in direct collaboration with SensioLabs, it leverages the Content Delivery API Client while adding Symfony-specific features like automatic client configuration and Symfony Profiler integration.&lt;/p&gt;

&lt;p&gt;Get started by adding these lines to your &lt;code&gt;config/packages/storyblok.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;storyblok&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;base_uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%env(STORYBLOK_API_BASE_URI)%'&lt;/span&gt;
  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%env(STORYBLOK_API_TOKEN)%'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this minimal setup, the bundle handles all the configuration, allowing you to immediately inject and use Storyblok's APIs within your controllers and services.&lt;/p&gt;

&lt;p&gt;The bundle also handles environment-specific configuration, making it easy to switch between development and production environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Management API Client
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/storyblok/php-management-api-client" rel="noopener noreferrer"&gt;Management API Client&lt;/a&gt; allows you to programmatically manage your Storyblok content, providing you with a comprehensive set of tools for creating, updating, and organizing content within your spaces.&lt;/p&gt;

&lt;p&gt;This client simplifies complex content management tasks with an intuitive API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\ManagementApi\ManagementApiClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\ManagementApi\Endpoints\StoryApi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\ManagementApi\Data\Story&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\ManagementApi\Data\StoryComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ManagementApiClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$accessToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$storyApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StoryApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$spaceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StoryComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"article-page"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"New Article"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"This is the content"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Story&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"An Article"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"an-article-slug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$content&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$storyCreated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$storyApi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$story&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Story created, ID: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$storyCreated&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package is especially valuable for content migration, bulk operations, and building custom editorial workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  PHP Tiptap Extension
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/storyblok/php-tiptap-extension" rel="noopener noreferrer"&gt;PHP Tiptap Extension&lt;/a&gt; provides an extension specifically designed for Storyblok's rich text fields processing.&lt;/p&gt;

&lt;p&gt;This framework-agnostic package makes rendering rich text fields from Storyblok straightforward and flexible in any PHP project, whether you're using Symfony, Laravel, or any other PHP framework.&lt;/p&gt;

&lt;p&gt;You can easily transform Storyblok's rich text content into HTML with customizable rendering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tiptap\Editor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Storyblok\Tiptap\Extension\Storyblok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Editor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'extensions'&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;new&lt;/span&gt; &lt;span class="nc"&gt;Storyblok&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="nv"&gt;$editor&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Content from your API&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$editor&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHTML&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also allows you to provide your own Block renderer, and it is included in our Symfony Bundle package.&lt;/p&gt;

&lt;p&gt;With all these releases comes a renewed PHP Technology Hub in our official website, a starting point for all your future integrations between your PHP projects and Storyblok.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important note about legacy packages
&lt;/h2&gt;

&lt;p&gt;As part of this launch, the following PHP packages are now entering a deprecation phase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/storyblok/php-client" rel="noopener noreferrer"&gt;storyblok/php-client&lt;/a&gt; (our original PHP Client)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/storyblok/storyblok-php-richtext-renderer" rel="noopener noreferrer"&gt;storyblok/storyblok-php-richtext-renderer&lt;/a&gt; (for handling richtext fields)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your current projects use these packages, don't worry, they will continue to work.&lt;/p&gt;

&lt;p&gt;That said, we strongly encourage all users to move to these new solutions, which offer significant advantages including modern PHP 8+ features, better type safety, and extensive testing.&lt;/p&gt;

&lt;p&gt;We'll be providing migration guides to help with the transition. Support for legacy packages will continue in the meantime, but all new features will exclusively target these new packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future ahead
&lt;/h2&gt;

&lt;p&gt;These packages represent a renewed commitment to the PHP ecosystem and the open source community, and we want to express our sincere gratitude to &lt;strong&gt;SensioLabs&lt;/strong&gt; for their expertise and collaboration in this endeavor.&lt;/p&gt;

&lt;p&gt;This release is just the beginning. We're actively working on expanding our PHP support and have exciting plans for the future (to our &lt;strong&gt;Laravel&lt;/strong&gt; users: stay tuned!.&lt;/p&gt;

&lt;p&gt;We invite our wonderful community to try these packages, provide feedback, and contribute to their ongoing development. Get involved at &lt;a href="https://www.storyblok.com/community" rel="noopener noreferrer"&gt;Storyblok Community&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>php</category>
      <category>symfony</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Mastering Scheduling and Gantt Charting: A Recap of Bryntum's Guide</title>
      <dc:creator>Siddharth Dayalwal</dc:creator>
      <pubDate>Fri, 14 Feb 2025 09:19:36 +0000</pubDate>
      <link>https://dev.to/storyblok/mastering-scheduling-and-gantt-charting-a-recap-of-bryntums-guide-17li</link>
      <guid>https://dev.to/storyblok/mastering-scheduling-and-gantt-charting-a-recap-of-bryntums-guide-17li</guid>
      <description>&lt;p&gt;Building a Gantt chart from scratch is no easy task—it can quickly become a complex challenge or even a blocker for your team. Fortunately, you don’t have to tackle it alone. That’s where the &lt;a href="https://bryntum.com/products/gantt/" rel="noopener noreferrer"&gt;&lt;strong&gt;Bryntum Gantt chart&lt;/strong&gt;&lt;/a&gt; comes in, providing a robust, pre-built scheduling solution that saves countless development hours. But what if you could take it a step further? Imagine seamlessly integrating it with Storyblok, allowing content editors to control project timelines without requiring developer intervention.&lt;/p&gt;

&lt;p&gt;To help you achieve this, we collaborated with &lt;a href="https://bryntum.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Bryntum&lt;/strong&gt;&lt;/a&gt; to create a step-by-step guide on building a &lt;a href="https://bryntum.com/blog/creating-a-custom-bryntum-gantt-react-component-for-storyblok/" rel="noopener noreferrer"&gt;Bryntum Gantt UI component with React and Storyblok&lt;/a&gt;. Here’s why this guide is a game-changer for developers using Storyblok.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Perfect Match: Storyblok and Bryntum
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Storyblok’s&lt;/strong&gt; joyful headless CMS empowers developers and content teams to create, scale, and deliver impactful digital experiences. &lt;strong&gt;Bryntum&lt;/strong&gt;, on the other hand, specializes in visual UI components like &lt;strong&gt;Gantt charts&lt;/strong&gt;, built for seamless integration with modern web frameworks.&lt;/p&gt;

&lt;p&gt;With Bryntum’s Gantt component, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;fully customizable UI&lt;/strong&gt; to match your project’s unique needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Powerful scheduling and tracking&lt;/strong&gt; for better project visibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seamless integration with Storyblok’s React SDK&lt;/strong&gt;, enabling effortless rendering and updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining Storyblok’s structured content management with Bryntum’s interactive Gantt charts, you get a powerful system for planning and tracking projects with precision.&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%2F4jefb6eonb7n6rs6b3lr.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%2F4jefb6eonb7n6rs6b3lr.png" alt="Custom Bryntum Gantt React component for Storyblok" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What You’ll Learn from Bryntum's Guide
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fundamentals of Scheduling and Gantt Charting:&lt;/strong&gt; Understand how Gantt charts work and why they are essential for visualizing complex project timelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrating Bryntum Gantt with React:&lt;/strong&gt; Learn how to use Bryntum’s pre-built Gantt chart UI component to save hours of development effort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizing and Extending the Gantt Chart:&lt;/strong&gt; Discover how to customize event rendering and align integration with Storyblok’s API-first architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building a Fully Functional Gantt-Driven UI:&lt;/strong&gt; Create a dynamic, Gantt-powered UI that enables non-developers to manage project schedules effortlessly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By the end of this guide, you will have a ready-to-use &lt;strong&gt;Gantt chart UI powered by Storyblok + Bryntum Gantt + React&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters for Developers
&lt;/h3&gt;

&lt;p&gt;Developing a Gantt chart UI component from the ground up is probably one of the most complex frontend challenges. It involves handling dependencies, interactions, and rendering large datasets efficiently. With the Bryntum chart, you get a completely optimized and feature-rich solution up straight. &lt;/p&gt;

&lt;p&gt;On top of it, its effortless integration with Storyblok enables content editors and non-technical users to manage tasks as per their needs without requiring code changes—making developers’ lives easier. This means you can focus on building innovative and powerful solutions rather than reinventing the wheel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ready to Try It Out?
&lt;/h3&gt;

&lt;p&gt;To conclude, the best way to see how Storyblok and Bryntum work together is to build something yourself. It’s time to explore Bryntum’s guide and see how it can complement your Storyblok experience by putting it into action. Dive in and take your project management skills to the next level!&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources &amp;amp; Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Checkout the &lt;a href="https://bryntum.com/blog/creating-a-custom-bryntum-gantt-react-component-for-storyblok/" rel="noopener noreferrer"&gt;comprehensive guide&lt;/a&gt; on creating a custom Bryntum Gantt React component for Storyblok.&lt;/li&gt;
&lt;li&gt;You can find the code for the complete tutorial in this &lt;a href="https://github.com/bryntum/bryntum-gantt-storyblok-starter/tree/completed-app" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Don’t forget to join &lt;a href="https://discord.gg/jKrbAMz" rel="noopener noreferrer"&gt;Storyblok Discord Community&lt;/a&gt; and connect with other developers working on exciting projects.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>storyblok</category>
      <category>react</category>
      <category>projectmanagement</category>
      <category>uicomponents</category>
    </item>
    <item>
      <title>Announcing Stable Live Preview for Storyblok’s Astro SDK</title>
      <dc:creator>Dipankar Maikap</dc:creator>
      <pubDate>Mon, 03 Feb 2025 13:56:27 +0000</pubDate>
      <link>https://dev.to/storyblok/announcing-stable-live-preview-for-storybloks-astro-sdk-333c</link>
      <guid>https://dev.to/storyblok/announcing-stable-live-preview-for-storybloks-astro-sdk-333c</guid>
      <description>&lt;p&gt;We are absolutely thrilled to announce that starting with version &lt;code&gt;6.0.0&lt;/code&gt;, our Astro SDK, &lt;a href="https://github.com/storyblok/storyblok-astro" rel="noopener noreferrer"&gt;@storyblok/astro&lt;/a&gt;, now includes a &lt;strong&gt;stable live preview feature&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;With this major release, we’ve introduced some breaking changes as well. Let’s take a look at what’s new and how you can update your code to work seamlessly with the latest release.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Module import changes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this release, we’ve removed the default export in favor of a named export. This change primarily affects your &lt;code&gt;astro.config.mjs&lt;/code&gt; file, so make sure to update it as shown below:&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;//astro.config.mjs&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;storyblok&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;@storyblok/astro&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;integrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;storyblok&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OsvN....&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bridge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;resolveRelations&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;featured-articles.posts&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;enableFallbackComponent&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="na"&gt;livePreview&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="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;h2&gt;
  
  
  &lt;strong&gt;Removal of &lt;code&gt;useStoryblok&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In our experimental release, &lt;code&gt;useStoryblok&lt;/code&gt; required extensive configuration, even if you didn’t use all live preview features, to maintain consistency with our other SDKs. Additionally, we used AST code parsing, which made the implementation more complex.&lt;/p&gt;

&lt;p&gt;In this version, &lt;code&gt;useStoryblok&lt;/code&gt; has been completely removed and replaced with a new function: &lt;code&gt;getLiveStory&lt;/code&gt;. Here’s how you can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;// pages/[...slug].astro&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;getLiveStory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useStoryblokApi&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;@storyblok/astro&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;StoryblokComponent&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;@storyblok/astro/StoryblokComponent.astro&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;BaseLayout&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;../layouts/Layout.astro&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="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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Astro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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;story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;liveStory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getLiveStory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Astro&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;liveStory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;liveStory&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sbApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStoryblokApi&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;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;sbApi&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;slug&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&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="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="s1"&gt;draft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resolve_relations&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;featured-articles.posts&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="nx"&gt;story&lt;/span&gt; &lt;span class="o"&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="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BaseLayout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StoryblokComponent&lt;/span&gt; &lt;span class="na"&gt;blok&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BaseLayout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re using &lt;code&gt;resolve_relations&lt;/code&gt;, pass it directly in the &lt;code&gt;bridge&lt;/code&gt; configuration in &lt;code&gt;astro.config.mjs&lt;/code&gt;. Refer to the first code example above for details.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Listening for live preview updates&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When the live preview updates content in the Storyblok editor, a custom event (&lt;code&gt;storyblok-live-preview-updated&lt;/code&gt;) is triggered. You can listen for this event in your application like this:&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;// pages/[...slug].astro&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="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storyblok-live-preview-updated&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="o"&gt;=&amp;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Live preview: body updated&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&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 is particularly useful if you need to regenerate CSS or handle other custom tasks when the content updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;We’re excited for you to try out this &lt;strong&gt;stable live preview feature&lt;/strong&gt;! We would absolutely love to see your projects built with Storyblok and Astro, and hear your feedback.&lt;/p&gt;

&lt;p&gt;Would you like to contribute to the development of &lt;a href="https://github.com/storyblok/storyblok-astro" rel="noopener noreferrer"&gt;@storyblok/astro&lt;/a&gt;? Feel free to create an issue or submit a PR in the &lt;a href="https://github.com/storyblok/storyblok-astro" rel="noopener noreferrer"&gt;official GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/storyblok/storyblok-astro" rel="noopener noreferrer"&gt;@storyblok/astro GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://npmjs.com/package/@storyblok/astro" rel="noopener noreferrer"&gt;@storyblok/astro NPM package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.storyblok.com/tp/the-storyblok-astro-ultimate-tutorial" rel="noopener noreferrer"&gt;Astro Ultimate Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://storyblok.com/docs" rel="noopener noreferrer"&gt;Storyblok Learning Hub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>astro</category>
      <category>livepreview</category>
      <category>opensource</category>
      <category>integration</category>
    </item>
    <item>
      <title>Announcing Official Storyblok Richtext Support in our Frontend SDKs</title>
      <dc:creator>Alvaro Saburido</dc:creator>
      <pubDate>Fri, 31 Jan 2025 08:28:54 +0000</pubDate>
      <link>https://dev.to/storyblok/announcing-official-storyblok-richtext-support-in-our-frontend-sdks-1301</link>
      <guid>https://dev.to/storyblok/announcing-official-storyblok-richtext-support-in-our-frontend-sdks-1301</guid>
      <description>&lt;p&gt;Last summer, we announced a brand new &lt;code&gt;@storyblok/richtext&lt;/code&gt; package, offering the community a more powerful way to parse Richtext content into their websites and apps using Storyblok. Thanks to you, this new library was greatly adopted, reaching around 130k monthly downloads at the time of this writing.&lt;/p&gt;

&lt;p&gt;Although the library can be used directly in your projects, it is about time you could benefit from Storyblok's major frontend SDK developer experience to use it. The time has come, and we are thrilled to present you Official Richtext Support for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React/Next SDK (starting from &lt;a href="https://github.com/storyblok/storyblok-react/releases/tag/v4.3.0" rel="noopener noreferrer"&gt;v4.3.0&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Vue SDK (from &lt;a href="https://github.com/storyblok/storyblok-vue/releases/tag/v8.1.0" rel="noopener noreferrer"&gt;v8.1.0&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Nuxt SDK (from &lt;a href="https://github.com/storyblok/storyblok-nuxt/releases/tag/v6.2.0" rel="noopener noreferrer"&gt;v6.2.0&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React/Next SDK
&lt;/h3&gt;

&lt;p&gt;To begin using it on your Next projects, make sure to install the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @storyblok/react@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can render rich text fields using the &lt;code&gt;StoryblokRichText&lt;/code&gt; component and pass the content to the prop doc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;StoryblokRichText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useStoryblok&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;@storyblok/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStoryblok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&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;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;draft&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="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;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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StoryblokRichText&lt;/span&gt; &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;richText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;Or you can have more control by using the &lt;code&gt;useStoryblokRichText&lt;/code&gt; hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useStoryblokRichText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;convertAttributesInElement&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;@storyblok/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;Codeblock&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;./Codeblock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStoryblokRichText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;//Options like resolvers&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;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&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;formattedHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;convertAttributesInElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// JSX&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formattedHtml&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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;For a comprehensive list of options you can provide to the &lt;code&gt;useStoryblokRichText&lt;/code&gt;, please consult the &lt;a href="https://github.com/storyblok/richtext?tab=readme-ov-file#options" rel="noopener noreferrer"&gt;Full options&lt;/a&gt; documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue/Nuxt SDK
&lt;/h2&gt;

&lt;p&gt;You can access this new functionality by installing the latest version of the Vue SDK&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @storyblok/vue@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the Nuxt module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @storyblok/nuxt@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can render rich text fields in Vue/Nuxt by using the &lt;code&gt;StoryblokRichText&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;StoryblokRichText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useStoryblok&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;@storyblok/vue&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;story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStoryblok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&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;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;draft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;StoryblokRichText&lt;/span&gt; 
    &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"story.content"&lt;/span&gt; 
    &lt;span class="na"&gt;:doc=&lt;/span&gt;&lt;span class="s"&gt;"story.content.richText"&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can have more control by using the useStoryblokRichText composable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;useStoryblokRichText&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;@storyblok/vue&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStoryblokRichText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Options like resolvers&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;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;render&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;richText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;root&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Overriding the default resolvers
&lt;/h2&gt;

&lt;p&gt;It’s fairly a common use-case to replace the default resolvers (the functions that map Storyblok’s field types to the component to be rendered by the framework) with a custom one on your project, for example, using Next’s &lt;code&gt;Link&lt;/code&gt; component as a replacement for all the anchors inside of the Richtext field or swapping Code Blocks for a custom local component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;StoryblokRichText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useStoryblok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MarkTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StoryblokRichTextNode&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;@storyblok/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;CodeBlock&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;./components/CodeBlock&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;Link&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;next/link&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;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Replace anchors with Next's Link&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MarkTypes&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="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StoryblokRichTextNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;return&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;linktype&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;story&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;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;// Replace code blocks with a custom component&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BlockTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CODE_BLOCK&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CodeBlock&lt;/span&gt;
      &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CodeBlock&lt;/span&gt;&lt;span class="p"&gt;&amp;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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StoryblokRichText&lt;/span&gt; 
        &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;richText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;resolvers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same object can be passed to composables/hooks and the Vue component.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about other SDKs?
&lt;/h2&gt;

&lt;p&gt;Great, we now have official support for React/Next and Vue/Nuxt combos, but what about the other Storyblok SDKs like &lt;a href="https://github.com/storyblok/storyblok-astro" rel="noopener noreferrer"&gt;Astro&lt;/a&gt; or &lt;a href="https://github.com/storyblok/storyblok-svelte" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;The quick answer is: that we are working on providing official support for the new Richtext package on these frameworks. Both have slightly different ways to render so we are still deciding the best way to integrate it. In the meantime, if the need arises, we suggest using NordVPN’s &lt;a href="https://github.com/NordSecurity/storyblok-rich-text-astro-renderer" rel="noopener noreferrer"&gt;storyblok-rich-text-astro-renderer&lt;/a&gt; package which is highly adopted by the Astro + Storyblok community.&lt;/p&gt;

&lt;p&gt;If you need a rich-text renderer for the Svelte SDK, please let us know via a request ticket on &lt;a href="https://github.com/storyblok/storyblok-svelte/issues/new/choose" rel="noopener noreferrer"&gt;the official repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the previous Richtext approach?
&lt;/h2&gt;

&lt;p&gt;As mentioned in the &lt;a href="https://www.storyblok.com/mp/announcing-official-storyblok-richtext-package#what-about-the-previous-approach" rel="noopener noreferrer"&gt;Richtext package announcement&lt;/a&gt; we will gradually sunset it in due time to facilitate the migration and adoption of the new approach, so for now, both solutions will co-exist in the ecosystem for a period of time until the next major version of &lt;code&gt;storyblok-js-client&lt;/code&gt; (v7.0) lands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;We hope you are as excited as we are with the official Richtext support. We would love to see your projects built with Storyblok and hear your feedback&lt;/p&gt;

&lt;p&gt;Want to contribute to this feature or do you have an issue to report? Feel free to create a new issue with a minimal reproduction in the correspondent repository listed below:&lt;/p&gt;

&lt;p&gt;Happy OSS!&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Storyblok Richtext &lt;a href="https://github.com/storyblok/richtext" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Next/React SDK &lt;a href="https://github.com/storyblok/storyblok-react" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Vue SDK &lt;a href="https://github.com/storyblok/storyblok-vue" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Nuxt SDK &lt;a href="https://github.com/storyblok/storyblok-nuxt" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>SymfonyCon Vienna 2024: Recap of our Experience</title>
      <dc:creator>Edoardo Dusi</dc:creator>
      <pubDate>Wed, 18 Dec 2024 08:37:30 +0000</pubDate>
      <link>https://dev.to/storyblok/symfonycon-vienna-2024-recap-of-our-experience-mj0</link>
      <guid>https://dev.to/storyblok/symfonycon-vienna-2024-recap-of-our-experience-mj0</guid>
      <description>&lt;p&gt;My personal and professional journey with &lt;strong&gt;PHP&lt;/strong&gt; spans many years, though I've spent recent times focusing on JavaScript frameworks. On the 5th of December, I had the privilege of attending &lt;a href="https://live.symfony.com/2024-vienna-con/" rel="noopener noreferrer"&gt;SymfonyCon&lt;/a&gt; in Vienna with my manager Alex Jover Morales, courtesy of &lt;a href="https://sensiolabs.com/" rel="noopener noreferrer"&gt;SensioLabs&lt;/a&gt;. This conference wasn't just a technical event for me, it was a heartwarming return to the PHP community that has evolved tremendously over the years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conference Highlights
&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%2F021brnmjw4mwnfni2vn8.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%2F021brnmjw4mwnfni2vn8.png" alt="SymfonyCon Keynote by Fabien Potencier" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The conference kicked off with an inspiring keynote by &lt;strong&gt;Fabien Potencier&lt;/strong&gt;, the author of &lt;a href="https://symfony.com/" rel="noopener noreferrer"&gt;Symfony&lt;/a&gt;. His presentation focused on &lt;a href="https://twig.symfony.com/" rel="noopener noreferrer"&gt;Twig&lt;/a&gt;, Symfony's powerful templating engine that allows developers to write clean, maintainable templates. The upcoming Twig release introduces exciting features that showcase the continuous innovation in the PHP ecosystem.&lt;/p&gt;

&lt;p&gt;One particularly fascinating technical session dove deep into &lt;strong&gt;HTTP compression algorithms&lt;/strong&gt;. The speaker compared different compression methods including &lt;em&gt;Zstandard&lt;/em&gt; (a high-performance compression algorithm developed by Facebook), &lt;em&gt;Brotli&lt;/em&gt; (Google's compression algorithm optimized for the web), and the widely-used &lt;em&gt;gzip&lt;/em&gt;. Understanding these compression techniques is &lt;strong&gt;crucial for optimizing web application performance&lt;/strong&gt; and reducing bandwidth usage.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ux.symfony.com/" rel="noopener noreferrer"&gt;Symfony UX&lt;/a&gt; presentation revealed promising statistics and future directions for this frontend framework. For those unfamiliar, &lt;strong&gt;Symfony UX&lt;/strong&gt; is a collection of JavaScript components that integrate seamlessly with Symfony applications, bringing reactive features to traditional server-rendered applications. The numbers shared during the talk suggest a &lt;strong&gt;bright future for this technology&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Platform.sh&lt;/em&gt;, a cloud hosting platform specialized in PHP applications, showcased their latest features, demonstrating how &lt;strong&gt;modern PHP deployment&lt;/strong&gt; can be both powerful and developer-friendly.&lt;/p&gt;

&lt;p&gt;A standout presentation came from Paul Dragoonis about &lt;a href="https://dagger.io/" rel="noopener noreferrer"&gt;Dagger&lt;/a&gt;, a programmable CI/CD engine created by the author of Docker, &lt;strong&gt;Solomon Hykes&lt;/strong&gt;. The talk illustrated how PHP developers can leverage Dagger to define their CI/CD pipelines as code, creating and managing Docker containers programmatically, a significant &lt;strong&gt;step forward for PHP deployment automation&lt;/strong&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%2Fjcncqd655vw491ge06ri.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%2Fjcncqd655vw491ge06ri.png" alt="Illustrating Dagger" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "Strict PHP" session resonated strongly with my own philosophy of &lt;strong&gt;writing code for humans&lt;/strong&gt;, not machines. It emphasized the importance of clear, maintainable code that future developers (including ourselves) can easily understand and modify.&lt;/p&gt;

&lt;p&gt;Rob Allen's comparative analysis of &lt;strong&gt;GraphQL&lt;/strong&gt; (a query language for APIs), &lt;strong&gt;REST&lt;/strong&gt; (Representational State Transfer), and &lt;strong&gt;RPC&lt;/strong&gt; (Remote Procedure Call) provided valuable insights into choosing the right API architecture for different use cases.&lt;/p&gt;

&lt;p&gt;This is just a quick overview of some of the talks at the conference to give you an idea of some of the most interesting topics that I found there. There were many more over the two days and across three tracks.&lt;/p&gt;

&lt;h2&gt;
  
  
  SensioLabs
&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%2Fdlo3hwh7kbjpkaadmo9j.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%2Fdlo3hwh7kbjpkaadmo9j.png" alt="SensioLabs logo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to extend special thanks to &lt;strong&gt;Oskar Stark&lt;/strong&gt; and &lt;strong&gt;Silas Joisten&lt;/strong&gt; from SensioLabs for their incredible hospitality. Our discussions went beyond casual conference chat—we dove deep into technical conversations about PHP, Symfony, and some exciting collaborative projects in the works. &lt;strong&gt;SensioLabs has been using Storyblok&lt;/strong&gt; for their website and recently published &lt;a href="https://sensiolabs.com/blog/2024/sensiolabs-goes-headless-with-storyblok" rel="noopener noreferrer"&gt;a wonderful piece&lt;/a&gt; about their experience. While I can't reveal details yet, we're working on something remarkable together that we're eager to share with the community soon!&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming Full Circle
&lt;/h2&gt;

&lt;p&gt;It was great to be back in the PHP community!&lt;/p&gt;

&lt;p&gt;It felt like coming home. This experience, along with my role as MC at &lt;strong&gt;phpday&lt;/strong&gt; in Italy this year, has reinforced my view that what makes the PHP ecosystem special is the &lt;strong&gt;passion and technical expertise&lt;/strong&gt; of its community members. Physical events like &lt;strong&gt;SymfonyCon&lt;/strong&gt; are priceless because they create chances to make meaningful connections and share knowledge that you just can't get online.&lt;/p&gt;

&lt;p&gt;The PHP community is still growing and coming up with new ideas, guided by the &lt;a href="https://thephp.foundation/" rel="noopener noreferrer"&gt;PHP Foundation&lt;/a&gt; and supported by frameworks like Symfony. Being part of this growth, even for a short time, reminds me why &lt;strong&gt;PHP is still a key part of web development&lt;/strong&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%2Fuoee4efu8y4osqskvpf9.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%2Fuoee4efu8y4osqskvpf9.png" alt="Storyblok and SensioLabs" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>storyblok</category>
      <category>php</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>Announcing React SDK v4 with full support for React Server Components</title>
      <dc:creator>Edoardo Dusi</dc:creator>
      <pubDate>Fri, 22 Nov 2024 11:38:42 +0000</pubDate>
      <link>https://dev.to/storyblok/announcing-react-sdk-v4-with-full-support-for-react-server-components-3ld1</link>
      <guid>https://dev.to/storyblok/announcing-react-sdk-v4-with-full-support-for-react-server-components-3ld1</guid>
      <description>&lt;p&gt;The introduction of the &lt;a href="https://nextjs.org/docs/app" rel="noopener noreferrer"&gt;App Router paradigm in Next.js&lt;/a&gt; brought significant changes to the way developers build and structure applications. While it opened the door to exciting features like &lt;a href="https://react.dev/reference/rsc/server-components" rel="noopener noreferrer"&gt;React Server Components (RSC)&lt;/a&gt; and finer control over rendering, it also introduced complexity for packages that needed to seamlessly support both client-side and server-side environments.&lt;/p&gt;

&lt;p&gt;With the release of &lt;a href="https://github.com/storyblok/storyblok-react" rel="noopener noreferrer"&gt;@storyblok/react&lt;/a&gt; version 4.0.0, we are proud to offer full support for React Server Components in Next.js. This update simplifies implementation, enables live preview functionality in our Visual Editor, and ensures robust server rendering, all in a single, unified setup.&lt;/p&gt;

&lt;p&gt;Start using it now with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @storyblok/react@4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you are using &lt;code&gt;@storyblok/react&lt;/code&gt; v3 with App Router, there are some breaking changes. Please continue reading this article to learn how to update your app.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  What's new in @storyblok/react 4.0.0?
&lt;/h3&gt;

&lt;p&gt;Here's a quick rundown of the major improvements in this release:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unified RSC support&lt;/strong&gt;&lt;br&gt;
Previously, React Server Components in Next.js required two different implementations for compatibility. With version 4.0.0, we've streamlined this and consolidated everything into one consistent approach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Live preview with Visual Editor&lt;/strong&gt;&lt;br&gt;
Developers using the App Router can now enjoy live preview capabilities directly in the Storyblok Visual Editor, enhancing the development and content editing experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seamless Server Rendering&lt;/strong&gt;&lt;br&gt;
Leverage the full server rendering capabilities of Next.js for improved performance and scalability of your applications&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Step 1: Initialize the SDK
&lt;/h4&gt;

&lt;p&gt;Start by creating a new file &lt;code&gt;lib/storyblok.js&lt;/code&gt; to initialize the SDK. Make sure to export the &lt;code&gt;getStoryblokApi()&lt;/code&gt; function.&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;// lib/storyblok.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Page&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;@/components/Page&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;Teaser&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;@/components/Teaser&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;apiPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;storyblokInit&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;@storyblok/react/rsc&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;getStoryblokApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storyblokInit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_ACCESS_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;apiPlugin&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;teaser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Teaser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&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;The &lt;code&gt;getStoryblokApi()&lt;/code&gt; function returns a shared instance of the Storyblok client that works across server and client components.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Wrap Your Application with StoryblokProvider
&lt;/h4&gt;

&lt;p&gt;Next, create a &lt;code&gt;StoryblokProvider&lt;/code&gt; component to enable live editing on the client side. Wrap your entire app with this provider in the &lt;code&gt;app/layout.jsx&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="c1"&gt;// app/layout.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;StoryblokProvider&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;@/components/StoryblokProvider&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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;StoryblokProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/body&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="sr"&gt;/html&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="sr"&gt;/StoryblokProvider&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;Now, create the &lt;code&gt;StoryblokProvider&lt;/code&gt; component:&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;// components/StoryblokProvider.jsx&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;getStoryblokApi&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;@/lib/storyblok&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;StoryblokProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getStoryblokApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Re-initialize on the client&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;children&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;Note that the &lt;code&gt;StoryblokProvider&lt;/code&gt; is a client component. This ensures that your client-side components can interact with Storyblok, including live editing in the Visual Editor.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Fetch Content and Render Components
&lt;/h4&gt;

&lt;p&gt;In server components, use the &lt;code&gt;getStoryblokApi()&lt;/code&gt; function to fetch content from &lt;code&gt;Storyblok&lt;/code&gt;. Here’s an example &lt;code&gt;app/page.jsx&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="c1"&gt;// app/page.jsx&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;getStoryblokApi&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;@/lib/storyblok&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;StoryblokStory&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;@storyblok/react/rsc&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&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;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="nf"&gt;fetchData&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StoryblokStory&lt;/span&gt; &lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="o"&gt;=&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="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="sr"&gt;/div&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchData&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;return&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cdn/stories/home&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;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;draft&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Use StoryblokServerComponent for server rendering
&lt;/h4&gt;

&lt;p&gt;For rendering components dynamically, always use the &lt;code&gt;StoryblokServerComponent&lt;/code&gt; from &lt;code&gt;@storyblok/react/rsc&lt;/code&gt;.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storyblokEditable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryblokServerComponent&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;@storyblok/react/rsc&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;Page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;blok&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nf"&gt;storyblokEditable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blok&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="nx"&gt;blok&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nestedBlok&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;StoryblokServerComponent&lt;/span&gt; &lt;span class="nx"&gt;blok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nestedBlok&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nestedBlok&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_uid&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;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="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures compatibility with server-side rendering, even if you declare the component as a client component.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;We’re preparing an updated official documentation to make adopting version 4 even smoother. In the meantime, all the essential steps are included in the &lt;a href="https://github.com/storyblok/storyblok-react?tab=readme-ov-file#nextjs-using-app-router" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your feedback and contributions are vital to improving &lt;code&gt;@storyblok/react&lt;/code&gt;! If you have suggestions or issues, feel free to open an &lt;a href="https://github.com/storyblok/storyblok-react/issues" rel="noopener noreferrer"&gt;issue&lt;/a&gt; or contribute directly to the project.&lt;/p&gt;

</description>
      <category>storyblok</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Are you attending ViteConf 2024?</title>
      <dc:creator>Alex Jover</dc:creator>
      <pubDate>Tue, 24 Sep 2024 16:01:27 +0000</pubDate>
      <link>https://dev.to/storyblok/are-you-attending-viteconf-2024-340g</link>
      <guid>https://dev.to/storyblok/are-you-attending-viteconf-2024-340g</guid>
      <description>&lt;p&gt;It’s safe to say that ViteConf is the biggest online conference on the Web Development these days, gathering the main experts from all the frameworks and technologies in the industry. And it makes sense… which web project is not using Vite these days?&lt;/p&gt;

&lt;p&gt;We’re really thrilled about &lt;a href="https://viteconf.org/" rel="noopener noreferrer"&gt;ViteConf 24&lt;/a&gt;, happening &lt;strong&gt;3rd &amp;amp; 4th October&lt;/strong&gt;! As last year, we’re proud to be an official community partner. But that’s not all - our dear &lt;a href="https://x.com/alvarosabu" rel="noopener noreferrer"&gt;Alvaro Saburido&lt;/a&gt; is speaking at the conference! About what? Well… you wanted to know.&lt;/p&gt;

&lt;p&gt;Before that - we just &lt;a href="https://www.youtube.com/watch?v=sW6BHBIN-vk" rel="noopener noreferrer"&gt;published in Youtube&lt;/a&gt; an &lt;strong&gt;interview with &lt;a href="https://patak.dev/" rel="noopener noreferrer"&gt;Matias (Patak)&lt;/a&gt;&lt;/strong&gt;, Vite core team member and the mastermind behind ViteConf, and Alvaro sharing a few sneak peeks on the conference. Make sure not to miss it!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/sW6BHBIN-vk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Main talk - How the ViteConf Pyraminx 3D Puzzle Was Built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://x.com/alvarosabu" rel="noopener noreferrer"&gt;Alvaro&lt;/a&gt;, DX Engineer at Storyblok and author or the &lt;a href="https://tresjs.org/" rel="noopener noreferrer"&gt;Tres.js ecosystem&lt;/a&gt;, will dive deep into the technical creation of a fully interactive &lt;strong&gt;3D Pyraminx puzzle&lt;/strong&gt; that you’ll see at ViteConf. &lt;/p&gt;

&lt;p&gt;Would you believe that such immersive creation is built purely with Vue and TresJS? But that’s not all: it also leverages &lt;strong&gt;Web Containers&lt;/strong&gt;, a tool that enables running full-stack JavaScript environments directly in the browser.&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%2Fnpdec37m8z5le0vx6rm1.gif" 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%2Fnpdec37m8z5le0vx6rm1.gif" width="760" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spoiler alert: Alvaro will reveal the process behind turning this random crazy idea into a working, interactive 3D app. Expect to learn about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to integrate &lt;strong&gt;TresJS&lt;/strong&gt; with &lt;strong&gt;Vue&lt;/strong&gt; to streamline 3D development.&lt;/li&gt;
&lt;li&gt;The magic behind &lt;strong&gt;Web Containers&lt;/strong&gt; and how they allow JavaScript to run directly in the browser—yes, including server-side code!&lt;/li&gt;
&lt;li&gt;The creative process behind that made the Pyraminx project an immersive reality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Innovative, uh? The web is amazing and full of potential… really a talk not to miss! Check out &lt;a href="https://viteconf.org/24/speaker/alvarosabu" rel="noopener noreferrer"&gt;all details about Alvaro’s talk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One more thing… Did you know you can customize your ticket? Look at the fancy Storyblok custom ticket &lt;a href="https://viteconf.org/24/ecosystem/storyblok" rel="noopener noreferrer"&gt;https://viteconf.org/24/ecosystem/storyblok&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vite</category>
      <category>techtalks</category>
      <category>astro</category>
    </item>
  </channel>
</rss>
