<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Yevheni Kshevitskyi</title>
    <description>The latest articles on Forem by Yevheni Kshevitskyi (@kshevitsky).</description>
    <link>https://forem.com/kshevitsky</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%2Fuser%2Fprofile_image%2F2833910%2F9530f154-573d-454a-89b7-be971dc43e42.jpeg</url>
      <title>Forem: Yevheni Kshevitskyi</title>
      <link>https://forem.com/kshevitsky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kshevitsky"/>
    <language>en</language>
    <item>
      <title>Storyblok MCP Client</title>
      <dc:creator>Yevheni Kshevitskyi</dc:creator>
      <pubDate>Tue, 25 Mar 2025 13:29:00 +0000</pubDate>
      <link>https://forem.com/kshevitsky/storyblok-mcp-server-ai-powered-headless-cms-integration-2e7j</link>
      <guid>https://forem.com/kshevitsky/storyblok-mcp-server-ai-powered-headless-cms-integration-2e7j</guid>
      <description>&lt;h2&gt;
  
  
  Faster CMS Integration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Storyblok MCP Client&lt;/strong&gt; is a tool that connects &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/storyblokcom"&gt;@storyblokcom&lt;/a&gt;&lt;/strong&gt;, &lt;a href="https://www.storyblok.com/" rel="noopener noreferrer"&gt;a headless CMS&lt;/a&gt;, with an AI agent through &lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;&lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;&lt;/a&gt;, enabling AI agents to interact with the CMS using human language 🙊&lt;/p&gt;

&lt;p&gt;This makes it super easy to pull Storyblok content straight into the client app (eg. &lt;strong&gt;Cursor IDE&lt;/strong&gt;) without manual API calls or extra setup.&lt;/p&gt;




&lt;p&gt;📢 &lt;strong&gt;In this article:&lt;/strong&gt; I’ll walk you through setting up the &lt;strong&gt;Storyblok MCP Client&lt;/strong&gt; in the &lt;strong&gt;Cursor IDE&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a &lt;strong&gt;Storyblok Personal Access Token&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configuring &lt;strong&gt;Cursor IDE’s MCP Server&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create new Storyblok space from &lt;strong&gt;Cursor IDE&lt;/strong&gt; chat prompt and fetching component type definitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚡ TL;DR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;NPM Package:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@slvrio/storyblok-mcp-client" rel="noopener noreferrer"&gt;@slvrio/storyblok-mcp-client&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 &lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/kshevitskiy/mcp-tool/tree/main/packages/storyblok" rel="noopener noreferrer"&gt;Storyblok MCP Client&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

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




&lt;h2&gt;
  
  
  So, &lt;strong&gt;Storyblok MCP&lt;/strong&gt; ... wtf? 🤨
&lt;/h2&gt;

&lt;p&gt;Working with a headless CMS usually means managing API calls and dealing with custom integrations. &lt;strong&gt;Storyblok MCP Client (server)&lt;/strong&gt; flips all that on its head, letting AI agents access Storyblok content directly and interact with it using human language in chat prompts. 🙌&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Storyblok MCP Client (server)&lt;/strong&gt; acts as a bridge between Storyblok’s API and AI agents, providing additional context to the AI agents through MCP tools. ⚡&lt;/p&gt;

&lt;h3&gt;
  
  
  ✨ Available Tools (as of &lt;code&gt;v.0.0.1&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;spaces_create&lt;/code&gt;&lt;/strong&gt; — Create a new Storyblok space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;spaces_get&lt;/code&gt;&lt;/strong&gt; — Retrieve a list of Storyblok spaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;components_get&lt;/code&gt;&lt;/strong&gt; — Fetch all components within a space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;component_get&lt;/code&gt;&lt;/strong&gt; — Retrieve a specific component by ID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;typedefs_get&lt;/code&gt;&lt;/strong&gt; — Generate TypeScript type definitions for components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Let's get started with setting up everything we need for the &lt;strong&gt;Storyblok MCP Client&lt;/strong&gt;!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a Storyblok Personal Access Token (PAT)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure Cursor IDE’s MCP Server&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a new space directly from Cursor IDE’s chat prompt and fetch Storyblok component type definitions&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s walk through each step to get everything up and running smoothly! 😎&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 🔑 Create a Storyblok Personal Access Token (PAT)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;First of all make sure to create an account at &lt;strong&gt;&lt;a href="https://www.storyblok.com/" rel="noopener noreferrer"&gt;Storyblok.com&lt;/a&gt;&lt;/strong&gt;, if you dont have one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to: &lt;strong&gt;&lt;code&gt;My Account&lt;/code&gt;&lt;/strong&gt; 👉 &lt;strong&gt;&lt;code&gt;Account Settings&lt;/code&gt;&lt;/strong&gt; 👉 &lt;strong&gt;&lt;code&gt;Personal access token&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on &lt;strong&gt;&lt;code&gt;Generate new token&lt;/code&gt;&lt;/strong&gt;, fill in the fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; Any name&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiration:&lt;/strong&gt; Select token expiration date (default 30days)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;&lt;code&gt;Generate &amp;amp; Copy token&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note.&lt;/strong&gt; Please copy this personal access token now. It will be visible only once&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%2Fhtpqwwj7dbh2pwjsiw92.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%2Fhtpqwwj7dbh2pwjsiw92.png" alt="Storyblok PAT" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;View high resolution screenshot &lt;a href="https://a.storyblok.com/f/315596/2300x1350/3e0a106264/storyblok-pat.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. ⚙️ Configure Cursor IDE’s MCP Server
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;Cursor IDE&lt;/strong&gt; settings&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;MCP&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Add new MCP server&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill in the fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; Any name&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;command&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command:&lt;/strong&gt; &lt;code&gt;npx -y @slvrio/storyblok-mcp-client --token=&amp;lt;YOUR_STORYBLOK_PAT_FROM_STEP_1&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;&lt;code&gt;Save&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo04totqywfkykk2olqle.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%2Fo04totqywfkykk2olqle.png" alt="Cursor MCP Settings" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;View high resolution screenshot &lt;a href="https://a.storyblok.com/f/315596/2294x1528/42715e108a/cursor-mcp-settings.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  ⚠️ Cursor v0.47.8
&lt;/h4&gt;

&lt;p&gt;In &lt;strong&gt;Cursor&lt;/strong&gt; &lt;code&gt;v0.47.8&lt;/code&gt;, MCP server configurations are managed in &lt;code&gt;mcp.json&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;To setup &lt;strong&gt;Storyblok MCP Client&lt;/strong&gt;, simply add the following config under the &lt;code&gt;mcpServers&lt;/code&gt; object:&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="nl"&gt;"Storyblok"&lt;/span&gt;&lt;span class="p"&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;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&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;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@slvrio/storyblok-mcp-client"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"--token=&amp;lt;YOUR_STORYBLOK_PAT_FROM_STEP_1&amp;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;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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note.&lt;/strong&gt; You can also define the &lt;code&gt;STORYBLOK_PERSONAL_API_TOKEN&lt;/code&gt; as environment variable, if set you can omit &lt;code&gt;--token&lt;/code&gt; argument in the command.&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%2F2b9652zetfgcev94y982.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%2F2b9652zetfgcev94y982.png" alt="Storyblok MCP Client Configuration" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;View high resolution screenshot &lt;a href="https://a.storyblok.com/f/315596/2296x1528/fb912e9bac/cursor-mcp-setup.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. 🤖 Let's Chat
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1 Create new &lt;strong&gt;Storyblok&lt;/strong&gt; space
&lt;/h4&gt;

&lt;p&gt;To create a new space, go to the chat (&lt;code&gt;cmd+i&lt;/code&gt;), type the following prompt, and press &lt;strong&gt;&lt;code&gt;Enter&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create new storyblok space with name "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tool&lt;/em&gt; &lt;code&gt;spaces_create&lt;/code&gt;&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%2Fa53mnp9fj60b2c25ivvh.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%2Fa53mnp9fj60b2c25ivvh.png" alt="spaces_create Storyblok MCP Tool" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;View high resolution screenshot &lt;a href="https://a.storyblok.com/f/315596/2036x1498/3ac01e30a1/spaces_create.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the space is created, you'll see the metadata, including the &lt;code&gt;Space ID&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To view and list all your Storyblok spaces, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List my storyblok spaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tool&lt;/em&gt; &lt;code&gt;spaces_get&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  3.2 View available Storyblok components
&lt;/h4&gt;

&lt;p&gt;To view the components for your Storyblok space, type the following prompt and press &lt;strong&gt;&lt;code&gt;Enter&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List all components for space #&amp;lt;SPACE_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tool&lt;/em&gt; &lt;code&gt;components_get&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; The &lt;strong&gt;&lt;code&gt;SPACE_ID&lt;/code&gt;&lt;/strong&gt; is conditionally required. You can either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the Space ID from Step 1 and pass it with prompt text,&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;&lt;code&gt;STORYBLOK_SPACE_ID&lt;/code&gt;&lt;/strong&gt; environment variable,&lt;/li&gt;
&lt;li&gt;Or pass the &lt;strong&gt;&lt;code&gt;--space_id&lt;/code&gt;&lt;/strong&gt; argument directly in the command.&lt;/li&gt;
&lt;/ul&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%2Fmp7xo5v2vmn5zu7mt63a.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%2Fmp7xo5v2vmn5zu7mt63a.png" alt="components_get Styoryblok MCP Tool" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;View high resolution screenshot &lt;a href="https://a.storyblok.com/f/315596/2036x1498/aa06da08ec/components_get.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  3.3 Typescript. Fetch Storyblok component type definitions
&lt;/h4&gt;

&lt;p&gt;To generate TypeScript type definitions for your Storyblok components, type the following prompt and press &lt;strong&gt;&lt;code&gt;Enter&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fetch ts types for components in storyblok space #&amp;lt;SPACE_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tool&lt;/em&gt; &lt;code&gt;typedefs_get&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will fetch the type definitions, making it easier to integrate Storyblok components into your TypeScript-based project. 📦&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%2Fyjxs1ryagoz6o6y9bpe1.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%2Fyjxs1ryagoz6o6y9bpe1.png" alt="typedefs_get Styoryblok MCP tool" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Uff, that's it! With &lt;strong&gt;Storyblok MCP Client&lt;/strong&gt;, we’ve enabled natural language interactions with the Storyblok API directly in the &lt;strong&gt;Cursor IDE&lt;/strong&gt; chat. We’ve explored how to set up the MCP server, manage Storyblok spaces, and fetch component types.&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🙌&lt;/p&gt;

</description>
      <category>storyblok</category>
      <category>ai</category>
      <category>modelcontextprotocol</category>
      <category>cursor</category>
    </item>
    <item>
      <title>Using MCP in Cursor IDE: A Simple Tool for CrossFit WOD</title>
      <dc:creator>Yevheni Kshevitskyi</dc:creator>
      <pubDate>Mon, 24 Mar 2025 14:58:32 +0000</pubDate>
      <link>https://forem.com/kshevitsky/using-mcp-in-cursor-ide-a-simple-tool-for-crossfit-wod-47p8</link>
      <guid>https://forem.com/kshevitsky/using-mcp-in-cursor-ide-a-simple-tool-for-crossfit-wod-47p8</guid>
      <description>&lt;p&gt;I've been exploring &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, an innovative standard that enables AI agents to interact with external tools and data sources. MCP is particularly valuable in environments like &lt;strong&gt;Cursor IDE&lt;/strong&gt;, where AI-driven automation can simplify routine tasks and improve developer efficiency.&lt;/p&gt;

&lt;p&gt;To explore this, I built &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/@slvrio/wod" rel="noopener noreferrer"&gt;@slvrio/wod&lt;/a&gt;&lt;/strong&gt;, a simple &lt;strong&gt;MCP tool&lt;/strong&gt; that fetches the &lt;strong&gt;Workout of the Day (WOD)&lt;/strong&gt; from the CrossFit API. It's an example of how MCP can help bring external data into your workflow, specifically for AI agents.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For more detailed information about &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, refer to the &lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;Get started with the Model Context Protocol (MCP)&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built an &lt;strong&gt;MCP tool&lt;/strong&gt; to fetch the CrossFit &lt;strong&gt;Workout of the Day (WOD)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Published on&lt;/strong&gt; &lt;code&gt;npm&lt;/code&gt;: &lt;a href="https://www.npmjs.com/package/@slvrio/wod" rel="noopener noreferrer"&gt;@slvrio/wod&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code on GitHub&lt;/strong&gt;: &lt;a href="https://github.com/kshevitskiy/mcp-tool/tree/main/packages/wod" rel="noopener noreferrer"&gt;mcp-tool/wod&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setup MCP Server in Cursor IDE
&lt;/h2&gt;

&lt;p&gt;You can integrate &lt;code&gt;@slvrio/wod&lt;/code&gt; into &lt;strong&gt;Cursor IDE&lt;/strong&gt; by setting up an MCP server, enabling retrieval of CrossFit's WOD directly within the IDE 🙈&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Add a new MCP Server in Cursor IDE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;Cursor IDE&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Settings&lt;/strong&gt; ➡️ &lt;strong&gt;Features&lt;/strong&gt; ➡️ &lt;strong&gt;MCP&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;"+ Add New MCP Server"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the configuration dialog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; Enter a descriptive name, e.g., "CF WOD".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; Select &lt;strong&gt;"command"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command:&lt;/strong&gt; Enter the command to run the WOD tool:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @slvrio/wod
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;"Save"&lt;/strong&gt; to add the MCP server.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Use the WOD Tool in Cursor IDE
&lt;/h3&gt;

&lt;p&gt;With the MCP server configured:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;strong&gt;Chat&lt;/strong&gt; &lt;code&gt;(cmd+i)&lt;/code&gt; in Cursor IDE.&lt;/li&gt;
&lt;li&gt;In the chat interface, type &lt;code&gt;wod&lt;/code&gt; and execute the command.&lt;/li&gt;
&lt;li&gt;The tool will fetch and display the latest CrossFit WOD directly within the chat.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;This is just a small step in experimenting with &lt;strong&gt;MCP-powered AI tooling&lt;/strong&gt;. If you’re exploring &lt;strong&gt;AI agents, MCP, or automation&lt;/strong&gt;, I’d love to hear your thoughts!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>modelcontextprotocol</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Breaking Monoliths: Transforming Legacy Codebase with NX Monorepo</title>
      <dc:creator>Yevheni Kshevitskyi</dc:creator>
      <pubDate>Mon, 10 Mar 2025 11:37:50 +0000</pubDate>
      <link>https://forem.com/kshevitsky/breaking-monoliths-transforming-legacy-codebase-with-nx-monorepo-3n79</link>
      <guid>https://forem.com/kshevitsky/breaking-monoliths-transforming-legacy-codebase-with-nx-monorepo-3n79</guid>
      <description>&lt;p&gt;In any long-running software project, architecture is key to scalability, maintainability, and a smooth developer experience. This article dives into the story of a bold architectural shift that transformed a legacy monolith into a sleek, modular system—boosting flexibility, future-proofing the codebase, and making development a whole lot more enjoyable 🚀.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Challenge: A Legacy Codebase Under Pressure
&lt;/h2&gt;

&lt;p&gt;The legacy project in question had been in operation for approximately four years. Over time, it evolved into a multi-app frontend ecosystem built atop a modern stack—primarily Vue—integrated with REST APIs. While the setup allowed for rapid prototyping and delivery, it also became a bottleneck as the project scaled. The following issues surfaced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance Decline&lt;/strong&gt;: Adding new apps slowed builds and affected performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development Experience (DX)&lt;/strong&gt;: With multiple developers working on the same codebase, merge conflicts became a regular occurrence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bugs&lt;/strong&gt;: Unexpected bugs surfaced due to intertwined dependencies and a lack of clear boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: A monolithic structure hindered the team's ability to iterate and grow efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These challenges made it clear that the project's architecture needed a serious rethink.&lt;/p&gt;

&lt;h2&gt;
  
  
  Researching Solutions: Modularization with NX monorepo
&lt;/h2&gt;

&lt;p&gt;Determined to address these pain points, I began researching ways to modularize the codebase while adhering to domain-driven design (DDD) principles. The goal was to split the monolithic codebase into self-contained, maintainable modules without sacrificing the integrity of the system.&lt;/p&gt;

&lt;p&gt;My research led me to &lt;strong&gt;NX&lt;/strong&gt;, a powerful &lt;strong&gt;monorepo&lt;/strong&gt; tool designed for scalable application development. NX offered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modularization&lt;/strong&gt;: Clear separation of apps and libraries into distinct domains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Performance&lt;/strong&gt;: Incremental builds and caching reduced build times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Collaboration&lt;/strong&gt;: Logical module boundaries reduced merge conflicts and allowed teams to work independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Tooling&lt;/strong&gt;: Built-in support for advanced frontend frameworks like Vue and Svelte, combined with testing and linting capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Proof of Concept: Bringing the Team on Board
&lt;/h2&gt;

&lt;p&gt;To validate the potential benefits of NX, I created a proof-of-concept (PoC) demonstrating how the legacy codebase could be restructured. The PoC showcased:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear separation of features into libraries aligned with DDD principles.&lt;/li&gt;
&lt;li&gt;Incremental builds, which significantly reduced build times.&lt;/li&gt;
&lt;li&gt;Simplified collaboration, as each team could now focus on their module without affecting others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Presenting the PoC to the team was a &lt;strong&gt;turning point&lt;/strong&gt;—it got everyone aligned on the vision for a more modular, scalable future. &lt;/p&gt;

&lt;h2&gt;
  
  
  Making It Happen: The Migration 🚀
&lt;/h2&gt;

&lt;p&gt;Following the approval of the PoC, the team embarked on implementing the NX monorepo structure. The transformation involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Migration&lt;/strong&gt;: Gradually moving apps and shared functionality into NX libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring&lt;/strong&gt;: Aligning components and services with DDD principles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization&lt;/strong&gt;: Leveraging NX's caching and dependency graph to improve build and test processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This change had a huge impact:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Improved DX&lt;/strong&gt;: Developers reported fewer merge conflicts and an overall smoother workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster Builds&lt;/strong&gt;: Incremental builds slashed build times significantly ⚡.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: The modular architecture made it easier to onboard new apps and developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;This journey underscores the importance of re-evaluating architectural decisions as projects evolve. By introducing NX into the legacy project, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shifted from a monolithic, hard-to-scale structure to a modular, domain-driven architecture.&lt;/li&gt;
&lt;li&gt;Future-proofed our frontend, making it more maintainable and adaptable.&lt;/li&gt;
&lt;li&gt;Boosted developer productivity and collaboration in ways that were immediately felt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For teams struggling with monolithic setups, &lt;strong&gt;embracing a monorepo strategy like NX can be a total game-changer&lt;/strong&gt;. The migration might take effort, but the long-term benefits—for both the codebase and the people working on it—are &lt;strong&gt;100% worth it&lt;/strong&gt; 💡&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>nx</category>
    </item>
    <item>
      <title>Automatically Generating TypeScript Types from Storyblok Components</title>
      <dc:creator>Yevheni Kshevitskyi</dc:creator>
      <pubDate>Mon, 10 Mar 2025 10:08:36 +0000</pubDate>
      <link>https://forem.com/kshevitsky/automatically-generating-typescript-types-from-storyblok-components-28ee</link>
      <guid>https://forem.com/kshevitsky/automatically-generating-typescript-types-from-storyblok-components-28ee</guid>
      <description>&lt;h2&gt;
  
  
  ⚡ TL;DR
&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;Storyblok CLI&lt;/strong&gt; and &lt;strong&gt;emeraldwalk.runonsave&lt;/strong&gt; to automate TypeScript type generation for Storyblok components.&lt;/p&gt;

&lt;p&gt;Find the full source code here: &lt;a href="https://github.com/kshevitskiy/storyblok-ts-types" rel="noopener noreferrer"&gt;Storyblok TypeScript Types Generator&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you're using &lt;strong&gt;Storyblok&lt;/strong&gt; with TypeScript, ensuring type safety can significantly enhance your development experience. Instead of manually defining types, you can &lt;strong&gt;automatically generate&lt;/strong&gt; TypeScript types from your Storyblok component schema. This tutorial will guide you through setting up a Storyblok TypeScript types generation.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Setting Up the Type Generator
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install Dependencies
&lt;/h3&gt;

&lt;p&gt;First, ensure that you have Node.js v20+ installed. Then, install the necessary packages:&lt;br&gt;
&lt;/p&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;-D&lt;/span&gt; storyblok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Authenticate with Storyblok
&lt;/h3&gt;

&lt;p&gt;You'll need to log in to Storyblok CLI to fetch your component schemas. Run the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx storyblok login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Configure Your Space ID
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env.local&lt;/code&gt; file in your project root and add your &lt;strong&gt;Storyblok Space ID&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;&lt;span class="nv"&gt;STORYBLOK_SPACE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_space_id_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Create the Type Generation Script
&lt;/h3&gt;

&lt;p&gt;If you haven't cloned the repository, create a new script file to generate Storyblok types. Inside your project, create a directory called &lt;code&gt;scripts/&lt;/code&gt; and a file named &lt;code&gt;storyblok.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; scripts &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;scripts/storyblok.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, open &lt;code&gt;scripts/storyblok.sh&lt;/code&gt; and add the following content:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Let's break down what this script does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loads the Storyblok Space ID from &lt;code&gt;.env.local&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pulls component schemas from &lt;strong&gt;Storyblok&lt;/strong&gt; and saves them to &lt;code&gt;__storyblok__/components.schema.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Runs &lt;code&gt;storyblok generate-typescript-typedefs&lt;/code&gt; to generate TypeScript types inside &lt;code&gt;types/storyblok.d.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure the script is executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x scripts/storyblok.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add a corresponding script in &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"scripts"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"storyblok:types"&lt;/span&gt;: &lt;span class="s2"&gt;"bash scripts/storyblok.sh"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚡ Generating TypeScript Types
&lt;/h2&gt;

&lt;p&gt;To manually generate TypeScript types, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run storyblok:types
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch components from &lt;strong&gt;Storyblok&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Save them to &lt;code&gt;__storyblok__/components.schema.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Generate TypeScript types inside &lt;code&gt;types/storyblok.d.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏗 Automating Type Updates with VS Code
&lt;/h2&gt;

&lt;p&gt;You can automate type generation every time you update your Storyblok schema. But there's a catch—it won’t just work out of the box. You’ll need to install the &lt;strong&gt;emeraldwalk.runonsave&lt;/strong&gt; VS Code extension and configure it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install the Extension
&lt;/h3&gt;

&lt;p&gt;Install &lt;strong&gt;emeraldwalk.runonsave&lt;/strong&gt; from the VS Code marketplace.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Configure &lt;strong&gt;settings.json&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add the following configuration to your VS Code &lt;code&gt;settings.json&lt;/code&gt; file:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"emeraldwalk.runonsave"&lt;/span&gt;&lt;span class="p"&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;span class="nl"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"match"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"__storyblok__/.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.json$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bash scripts/storyblok.sh"&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="p"&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;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;p&gt;This setup ensures that whenever a &lt;code&gt;.json&lt;/code&gt; file inside &lt;code&gt;__storyblok__/&lt;/code&gt; is saved, the &lt;code&gt;storyblok.sh&lt;/code&gt; script runs automatically, keeping your TypeScript definitions up to date.&lt;/p&gt;

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

&lt;p&gt;And that's it! With just a little setup, you now have &lt;strong&gt;fully automated TypeScript types&lt;/strong&gt; for your Storyblok components. No more manual type definitions—just clean, reliable, and always up-to-date types.&lt;/p&gt;

</description>
      <category>storyblok</category>
      <category>typescript</category>
      <category>vscode</category>
    </item>
    <item>
      <title>List Strava Activities in a Next.js App</title>
      <dc:creator>Yevheni Kshevitskyi</dc:creator>
      <pubDate>Sat, 08 Feb 2025 15:25:02 +0000</pubDate>
      <link>https://forem.com/kshevitsky/list-strava-activities-in-a-nextjs-app-14i1</link>
      <guid>https://forem.com/kshevitsky/list-strava-activities-in-a-nextjs-app-14i1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A basic understanding of Next.js and TypeScript&lt;/li&gt;
&lt;li&gt;An active Strava account&lt;/li&gt;
&lt;li&gt;Access to the Strava API (client ID, client secret, and refresh token)&lt;/li&gt;
&lt;li&gt;A GitHub repository for your Next.js project&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up Strava API Service
&lt;/h2&gt;

&lt;p&gt;To simplify Strava API integration, we'll create a new service:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Step 2: Fetching and Displaying Activities in a Component
&lt;/h2&gt;

&lt;p&gt;To display activities on the frontend, you’ll need to fetch the necessary data and pass it to your React component. In this step, we fetch the data using &lt;code&gt;getStaticProps&lt;/code&gt;, which allows the page content and activities to be pre-rendered at build time.&lt;/p&gt;

&lt;p&gt;Eg. in &lt;code&gt;pages/index.tsx&lt;/code&gt;, the data is fetched by calling &lt;code&gt;fetchExtendedActivities&lt;/code&gt;, which retrieves activities data from Strava API. The fetched data is then returned as props, which are passed to the component.&lt;/p&gt;

&lt;p&gt;Here’s how you can implement this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Step 4: Configuring GitHub Cron Job
&lt;/h2&gt;

&lt;p&gt;To automate tasks like data fetching, deployments, or updates on a regular basis, you can use a GitHub cron job by configuring a scheduled &lt;a href="https://github.com/slvrdigital/resume/blob/4f4fa64983c8b0ff78c4fbee55343004cfcc008a/.github/workflows/nextjs.yml#L15-L17" rel="noopener noreferrer"&gt;workflow&lt;/a&gt;. This will allow you to trigger your workflow at specific times, such as once a day, at a specific hour, or on particular days of the week.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Trigger the workflow once a day (adjust the schedule as needed)
schedule:
  - cron: "0 0 * * *" # run the workflow at midnight UTC every day
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the job runs, you can monitor the results and logs from the Actions tab in your GitHub repository. If the cron job fails or produces unexpected results, the logs will help you troubleshoot and adjust the workflow accordingly.&lt;/p&gt;


&lt;h2&gt;
  
  
  Adding an API Route (Optional)
&lt;/h2&gt;

&lt;p&gt;Since we're using Next.js with SSG mode to generate distribution artefacts for GitHub Pages, we'll call the &lt;code&gt;fetchExtendedActivities&lt;/code&gt; method inside &lt;code&gt;getStaticProps&lt;/code&gt;. However, if you want to serve data (activities) from Strava API dynamically to your frontend, consider adding an API route in your Next.js app:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



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

&lt;p&gt;You’ve now set up a Next.js app that pulls in Strava activities, built a backend service, and set up a GitHub cron job to keep things updated regularly. This setup is super flexible, so you can tweak and expand it however you need as your project grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refs.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/slvrdigital/resume" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.strava.com/docs/reference/" rel="noopener noreferrer"&gt;Strava API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Image Credits&lt;/strong&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@lukechesser" rel="noopener noreferrer"&gt;Luke Chesser&lt;/a&gt; on &lt;a href="https://unsplash.com" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>strava</category>
      <category>nextjs</category>
      <category>api</category>
    </item>
  </channel>
</rss>
