storypane.

Migrate from Storyblok

Keep the block-based content model. Move the application and data into your own hands. Spaces, stories, reusable blocks, nested content, and locales have close counterparts in Storypane. At that conceptual level, the mapping is nearly 1:1. Your existing content gives an agent a useful starting point instead of a blank sheet.

Our migration started with a local Storypane installation, our Storyblok space ID, and a personal access token. Our agent migrated the block definitions and content. This guide turns that approach into a repeatable workflow for your space: inspect, map, import, and verify using Storypane’s existing APIs.

1. Give your agent the right access

Start with an installed local CMS and a dedicated, empty Development space for rehearsal. Use your CMS URL, such as http://localhost:3130; storypane.dev is the marketing website.

Setting What to provide
Storypane checkout The local source repository, including AGENTS.md, contracts, SDK, and docs.
STORYBLOK_SPACE_ID The numeric source space ID.
STORYBLOK_PAT A personal access token with permission to read the required source resources.
Source region The region containing that space; use its documented Management API base URL.
STORYPANE_URL The running local CMS origin.
STORYPANE_SPACE_ID The empty rehearsal space’s UUID.
STORYPANE_MANAGEMENT_TOKEN A space-scoped token created in Settings → API & preview → Management API.

Store secrets in an ignored local file, such as .env.storyblok-migration.local, or your agent’s local secret configuration. That filename is ignored by this repository. Have your agent load it locally; do not paste tokens into the prompt. Use restrictive file permissions and keep exports and ID maps out of Git too.

The Storyblok PAT is a Management API credential, distinct from a Content Delivery API access token. Start with read access to the source; the importer has no reason to edit it. Follow Storyblok’s current authentication, region, pagination, and rate-limit documentation.

For the target, grant read and the write scopes actually needed for content, schemas, assets, datasources, and settings. Schema deployment also requires the appropriate admin capability. Leave content:publish out of the initial import token. All token scopes still intersect the issuer’s current permissions. See the management guide.

2. Inventory the space before importing

Ask the agent to export and count all required resources, across every page of each endpoint. Record which exports are drafts, published snapshots, or release versions, along with the export time. If editors keep changing the source, plan a final delta export before cutover.

Include:

Use the components API and stories API as source references. Respect the documented rate limits and retry reads with backoff after a 429. An incomplete first page of results is not a complete export.

3. Map the familiar parts

The core concepts line up closely; the persistence model and API contracts differ. Create a mapping manifest instead of treating a Storyblok JSON export as a Storypane write request.

Storyblok Storypane Mapping work
Space Space with its own Postgres database Create the target explicitly; map source and target IDs.
Component technical name Block definition technical name Keep names where valid. Review root/nestable usage when choosing Content type, Nestable, or Universal.
Component groups Block-library hierarchy Map the grouping intent to parents in the library; do not confuse library parents with nested content.
Text, textarea, markdown, rich text Text with the corresponding format Map validation/defaults. Convert rich-text nodes and marks where their representations differ.
Number, boolean, date/time Number, Boolean, Date/Datetime Normalize numeric values and UTC timestamps to the target contracts.
Blocks field Blocks field and ordered child block instances Preserve field names and order. Resolve allowed block names/groups/tags to target restrictions.
Single/multiple options, datasources Option/Options with the appropriate source Preserve option values; map datasource IDs and story-backed choices.
Asset Private asset plus an Asset reference Copy the original, then map its ID and per-use alt text.
Story, URL, email, or asset link Typed Link value or story-backed options Rewrite identifiers and handle anchors/custom attributes explicitly.
Folder hierarchy and stories Content folders and stories Preserve paths where representable; explicitly map start pages and translated slugs.
Translated fields or folder-based language variants Independent story locales, or an explicitly chosen folder model Materialize each locale’s values. Review fallback and shared-field behavior.

Storypane delivers nested block content with the familiar component and _uid keys. For ordinary text and block nesting, this shape will look familiar:

{
  "component": "page",
  "_uid": "target-page-block-uuid",
  "body": [
    {
      "component": "hero",
      "_uid": "target-hero-block-uuid",
      "title": "Bring your blocks with you."
    }
  ]
}

The IDs above illustrate the delivered shape; actual target IDs are UUIDs returned by Storypane. Keep maps for source story IDs/UUIDs, definitions, fields, blocks, locales, folders, datasources, and assets. Do not force numeric source IDs into UUID fields or assume _uid values survive a copy unchanged.

Review the parts that need adaptation

Use the current core validation contracts and management client as the target reference.

4. Import in dependency order

Keep the importer small and specific to your space. Use the management API/SDK, CLI, or MCP tools behind those APIs so validation, authorization, history, and notifications remain intact. Stage definitions in a schema migration, review it, and deploy it transactionally through the CMS migration API. Content migration does not require bypassing the store with raw SQL.

  1. Create locales, folders, and datasources; map their target IDs.
  2. Stage all block definitions and fields, then resolve definition dependencies, defaults, nested-block restrictions, and library parents. Review and deploy the schema migration before creating stories from it. Schema defaults that refer to content/assets may need a second migration after those dependencies exist.
  3. Copy original assets through the asset upload API. Map duplicate originals deliberately and replace source IDs/URLs, including images inside rich text.
  4. Create story shells and their locales. Record target IDs before filling fields.
  5. Fill scalar fields and build nested content through structural commands. Preserve child order and map the created block IDs before writing references.
  6. Resolve story/asset links and validate the resulting snapshots. Finish with all imported content as drafts and an exceptions report.

In Storypane, saveBlock writes a complete editable field map; preserve all fields you intend to keep. Blocks fields are structural, not a nested JSON value to pass to saveBlock. Read current revisions and schema versions, and persist mutation IDs and exact command bodies for safe retries. Resource creation is not generally idempotent: reconcile an ambiguous response before retrying a create. Keep a durable source-to-target manifest so reruns resume rather than duplicate records.

Never repurpose importBlocks as a Storyblok upload endpoint: it imports existing Storypane blocks between locales. See the management API guide for commands, multipart assets, pagination, conflicts, and retry behavior.

5. Check it in the editor

Before the full run, exercise a representative sample: a deep nested page, a translated story, a story with incoming/outgoing references, an image-rich page, and a draft that differs from its publication. Check:

Have the agent leave the export, mapping report, manifest, importer, fixture tests, and validation summary available locally. Keep private content exports out of Git; commit reusable importer code and sanitized tests only after review.

6. Preserve live content separately from drafts

Importing a story that is marked published in Storyblok does not prove its latest draft is the published content. If preserving publication state, export the actual published snapshot separately. The Storyblok Content Delivery API can retrieve the published version with an appropriate delivery token; a Management API PAT is not a substitute for that token.

After reviewing the import, load and publish the mapped source published snapshot, then apply any newer source draft as an unpublished edit. Publish only reviewed Storypane checkpoints, with explicit reference choices where required. Do not publish unfinished drafts to make a reference resolve. If published snapshots cannot be verified, keep the target in draft and report the gap.

7. Move to production and connect your frontend

For a team installation, use linked development and production spaces. Author the schema in dev, review/promote it to protected production, and import the content into production with a separate target manifest and credentials. Cloning a dev space excludes bulk content/media; promotion does not carry your rehearsal content into production.

Update delivery calls, generated types, asset handling, and live preview for the Storypane SDK. Familiar component names can make block renderers reusable, but review their props and integration code. A schema/content import alone does not switch your website. Follow the SDK, Astro, or Next.js guide and check actual routes, redirects, media variants, preview, and locale URLs.

Reconcile a final source delta, verify the production result, and switch the frontend when ready. Keep Storyblok and its export intact until you have checked the new site and a rollback path. Revoke migration credentials when the work is finished.

Instructions checked against Storypane revision 46eb0b5 on November 6, 2026. Agents should re-read the contracts in the checkout they are actually migrating to.

View this guide on GitHub ↗