DEV Community

Cover image for How to Migrate from Storyblok to Cosmic
Tony Spiro
Tony Spiro

Posted on • Originally published at cosmicjs.com

How to Migrate from Storyblok to Cosmic

A step-by-step guide for developers migrating from Storyblok to Cosmic: content model mapping, component-to-metafield conversion, media migration, API migration, and webhooks — with real TypeScript code examples.

Why Developers Are Migrating from Storyblok to Cosmic

Storyblok was a smart choice for teams who wanted a visual editor baked into their CMS. But as applications grow in complexity and AI becomes central to content operations, its limitations become harder to work around. Three pain points keep coming up in migration conversations:

Visual editor lock-in. Storyblok components are built around page presentation, which couples your content model to your frontend. When you need to reuse content across channels, that coupling becomes a bottleneck.

Pricing pressure. Seat fees, delivery limits, and add-on costs compound as teams grow. Budgeting for Storyblok at scale is unpredictable.

No native AI. Adding AI to a Storyblok workflow requires third-party integrations and significant custom engineering. Cosmic has AI Agents built in.

If any of those sound familiar, this guide will walk you through the full migration process: content model mapping, component-to-metafield conversion, media migration, API migration, and webhooks.

Before You Start: Understanding the Key Differences

Storyblok Concept Cosmic Equivalent
Story Object
Component/Block Object Type + Metafields
Component Field Metafield
Space Bucket
Asset Media
Datasource Object Type (for structured reference data)
Webhook Webhook (via add-on)

The most important conceptual shift: Storyblok organizes content around components on stories. Cosmic organizes content around Objects of a given Object Type. The result is more flexible — you're not constrained by what a visual editor can preview.

Step 1: Map Your Content Model

Start by auditing your Storyblok components. For each component, you'll create a corresponding Object Type in Cosmic with the right Metafields.

Field type mapping reference:

  • Storyblok richtext → Cosmic html-textarea or markdown
  • Storyblok asset → Cosmic file
  • Storyblok text → Cosmic text
  • Storyblok textarea → Cosmic textarea
  • Storyblok single select → Cosmic select
  • Storyblok multi select → Cosmic multi-select
  • Storyblok nested blocks → Cosmic relationship field or objects
  • Storyblok reference → Cosmic relationship field (object)

Step 2: Export Your Content from Storyblok

Use the Storyblok Management API to export your stories. You'll need your Storyblok API token.

const response = await fetch(
  `https://mapi.storyblok.com/v1/spaces/${SPACE_ID}/stories`,
  {
    headers: {
      Authorization: STORYBLOK_MANAGEMENT_TOKEN,
    },
  }
);
const { stories } = await response.json();
Enter fullscreen mode Exit fullscreen mode

Step 3: Migrate Media Assets

Before importing content objects, migrate your media. Storyblok stores assets on their CDN; you'll need to re-upload them to Cosmic's media library.

import { createBucketClient } from '@cosmicjs/sdk';

const cosmic = createBucketClient({
  bucketSlug: process.env.COSMIC_BUCKET_SLUG,
  readKey: process.env.COSMIC_READ_KEY,
  writeKey: process.env.COSMIC_WRITE_KEY,
});

async function migrateAsset(storyblokUrl: string, filename: string) {
  const response = await fetch(storyblokUrl);
  const buffer = await response.arrayBuffer();
  const file = new File([buffer], filename);

  const { media } = await cosmic.media.insertOne({ media: file });
  return media.imgix_url;
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Import Content to Cosmic

With your content model mapped and media migrated, import your stories as Cosmic Objects using the JavaScript/TypeScript SDK.

async function importStory(story: StoryblokStory, mediaMap: Record<string, string>) {
  await cosmic.objects.insertOne({
    title: story.name,
    type: 'your-object-type-slug',
    status: story.published ? 'published' : 'draft',
    metadata: {
      content: story.content.body,
      image: mediaMap[story.content.image?.filename] || '',
      // map other fields as needed
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Update Your API Calls

Storyblok and Cosmic have different API patterns. Here's how to update your frontend code.

Before (Storyblok):

import { storyblokInit, apiPlugin } from '@storyblok/react';

storyblokInit({
  accessToken: process.env.STORYBLOK_TOKEN,
  use: [apiPlugin],
});

const { data } = await storyblokApi.get('cdn/stories', {
  version: 'published',
});
Enter fullscreen mode Exit fullscreen mode

After (Cosmic):

import { createBucketClient } from '@cosmicjs/sdk';

const cosmic = createBucketClient({
  bucketSlug: process.env.COSMIC_BUCKET_SLUG,
  readKey: process.env.COSMIC_READ_KEY,
});

const { objects } = await cosmic.objects.find({
  type: 'your-object-type-slug',
}).props('id,title,slug,metadata');
Enter fullscreen mode Exit fullscreen mode

Important: Cosmic uses the REST API only. There is no GraphQL endpoint.

Step 6: Migrate Webhooks

If you use Storyblok webhooks to trigger builds or revalidation, you'll need to set up Cosmic webhooks. Cosmic webhooks are available as an add-on ($99/month, or included in the $199/month bundle). Once enabled, configure them in the Cosmic dashboard under Settings > Webhooks.

Migration Checklist

Content Model

  • [ ] Audit all Storyblok components and fields
  • [ ] Create corresponding Object Types in Cosmic dashboard
  • [ ] Map all field types (richtext → markdown, asset → file, etc.)
  • [ ] Test Object Type schemas with sample content

Media

  • [ ] Export list of all Storyblok assets
  • [ ] Run media migration script
  • [ ] Verify asset URLs in Cosmic media library
  • [ ] Build asset URL map for content import

Content

  • [ ] Export all Storyblok stories via Management API
  • [ ] Run content import script
  • [ ] Verify published/draft status is correct
  • [ ] Spot-check content in Cosmic dashboard

API Integration

  • [ ] Replace Storyblok SDK imports with Cosmic SDK
  • [ ] Update all API calls to use Cosmic REST API
  • [ ] Update environment variables
  • [ ] Test all content queries in development

Webhooks and Automation

  • [ ] Recreate Storyblok webhooks in Cosmic
  • [ ] Update webhook endpoints in your applications
  • [ ] Test build triggers and cache revalidation

Go Live

  • [ ] Run full content audit comparing Storyblok and Cosmic
  • [ ] Update DNS / CDN configuration if needed
  • [ ] Monitor error rates after launch
  • [ ] Deprecate Storyblok account once migration is confirmed

Supported Frameworks

Cosmic works with all major JavaScript frameworks:

  • Next.js — Full support including App Router and Pages Router
  • React — Works with any React setup
  • Vue — Full compatibility
  • Nuxt — Server-side rendering and static generation
  • Astro — Content collections and SSR
  • Remix — Loader-based data fetching
  • Svelte / SvelteKit — Full support
  • Gatsby — Static generation

The Cosmic JavaScript/TypeScript SDK works in any Node.js environment and in modern browsers.


This article was originally published on the Cosmic blog.

Top comments (0)