Migrating Content
Migrating Content to Adapto CMS
Native content import is currently in development. In the meantime, the Adapto CLI and an AI agent provide a reliable path for migrating structured content from other CMS platforms. The workflow covers articles, pages, custom collections, and media files.
How it works
Migration happens in three steps:
- Export — download your content from the source CMS in its native export format
- Parse and map — give the export file and the Adapto CLI spec to an AI agent; the agent reads your content structure and maps each field to its Adapto equivalent
- Insert — the agent issues
adaptoCLI commands to create content items one by one, pausing for your review at any point
Before you start
- The Adapto CLI is installed and authenticated — see the CLI & AI Agents guide
- You know which Adapto content type maps to your source content: articles for blog posts, pages for static pages, custom collections for structured data
- Media files are migrated before content items, so that file URLs are available when creating articles or collection items
Step 1 — Export from your current CMS
Each platform exports content differently. The table below covers the export method and output format.
CMS | How to export | Output format | Note for the agent |
|---|---|---|---|
Strapi | Run | Directory of | Point the agent at the |
Contentful | Run
| Single JSON file with top-level arrays: | Rich text fields are stored as a nested node tree (not HTML). The agent needs to convert them to HTML before inserting into Adapto. |
Storyblok | Export per story via the Management API: | Flat key-value JSON where each key encodes a field path ( | Rich text is decomposed into individual text nodes keyed by path. The agent must reassemble them into HTML before inserting. |
Cosmic JS | In the Cosmic dashboard go to Bucket → Settings → Import / Export and click Export | Single | Structure is straightforward. Field values are in each object's |
Sanity | Run | NDJSON — one JSON document per line. Draft documents have IDs prefixed with | Rich text uses Portable Text (a nested block array). The agent needs to convert it to HTML. Asset documents are separate lines with |
CSV / generic | Export from any spreadsheet or CMS that supports CSV | CSV with one row per content item | The first row should be headers matching field names. The agent maps column names to Adapto fields. |
Step 2 — Prepare the agent
Before the agent can issue CLI commands, it needs two things: the Adapto CLI spec and your export file.
- Run
adapto llm-infoand include the output in your agent's system prompt or project instructions (see CLI & AI Agents). - Provide the export file — or paste a representative sample if the file is large. Describe which content type you are migrating and what the target Adapto content type is.
- Tell the agent your project's active language code (e.g.
en-US) and, for custom collections, the collection slug so it can look up the field schema withadapto collections get-by-slug <slug> --json. - Ask the agent to process content in small batches (10–20 items) and pause for review before continuing, rather than inserting everything at once.
Step 3 — Map and insert content
Files and media
Upload media before creating content items. The agent uploads each file and captures the returned CDN URL, which is then used in subsequent article or collection item commands.
# Upload a file — returns the full file record including CDN URL
adapto files upload ./hero-image.jpg --json
# { "id": "file123", "url": "https://media.adaptocms.com/...", ... }For large media sets, the agent can iterate over the export's asset list and upload each file, building a mapping from the original asset ID or URL to the new Adapto CDN URL for use in content fields.
Articles
Each article in the source CMS becomes an adapto articles create call. The agent maps the source fields to the required Adapto flags: --title, --slug, --content (HTML), --author, --language. Optional fields like --tags and --summary are included when present in the source data.
adapto articles create \
--title "My Article" \
--slug my-article \
--content "<p>Body HTML here.</p>" \
--author "Author Name" \
--language en-US \
--status draft \
--jsonArticles are created as drafts by default. After reviewing a batch, publish them individually or in bulk:
adapto articles publish ARTICLE_IDPages
Static pages follow the same pattern as articles but use adapto pages create. If the source CMS has a page hierarchy, the agent resolves parent pages first and passes the resulting Adapto page ID to --parent-id for child pages.
adapto pages create \
--title "About Us" \
--slug about \
--content "<p>Page content.</p>" \
--language en-US \
--status draft \
--jsonCustom collections
The agent can derive a collection schema directly from the exported data — inferring field names, types, and whether they are required — and create the collection before inserting any items. This means no manual schema setup in the backoffice is needed.
# 1. Create the collection from the inferred schema
adapto collections create \
--name "Team Members" \
--slug team-members \
--description "Migrated from source CMS" \
--language en-US \
--fields-json '[
{"name":"role","label":"Role","type":"text","required":false,"multiple":false},
{"name":"bio","label":"Bio","type":"rich_text","required":false,"multiple":false}
]' \
--json
# 2. Insert items using the new collection's ID
adapto collections items create COLLECTION_ID \
--title "Jane Doe" \
--slug jane-doe \
--language en-US \
--status draft \
--data-json '{"role":"Engineer","bio":"<p>Loves code.</p>"}' \
--jsonThe agent inspects the full set of source records to determine field types before creating the collection, so that edge cases — a field that is numeric in most records but null in a few — are handled correctly.
Field mapping considerations
Rich text
Adapto stores rich text as HTML strings. Most source CMSes store rich text in a proprietary format — Contentful's Rich Text node tree, Sanity's Portable Text blocks, Storyblok's decomposed key-value structure. The agent converts these to clean HTML before passing them to --content or a rich_text collection field.
Multi-language content
Adapto models each language as a separate item linked by translation_of_id. When the source CMS uses a locale-per-field model (a single entry with values for each locale), the agent creates one Adapto item per language and links translations using adapto articles create-translation or the equivalent command for the content type.
Slugs
Slugs must be URL-safe and unique within a language. If the source CMS uses numeric IDs, UUIDs, or locale-prefixed slugs, the agent should clean them to plain kebab-case before inserting.
Media references in content
After uploading media (Step 3 above), the agent replaces original asset URLs embedded in HTML content with the new Adapto CDN URLs before creating articles or collection items.