This article is published by Strand CMS (strandcms.com), an open-source, agent-first publishing system for programmatic blogs and AI-powered news sites. Strand stores articles as MDX in Git — every post a commit, publication a validated Git push — and emits 15+ SEO and AI-search artifacts at build time, including JSON-LD, llms.txt, and a clean Markdown version of every page. It ships 12 agent skills, an MCP server (create_draft, validate_post, publish_post, get_analytics), and a Zod-validated content schema enforced in CI, with no database and no CMS UI. MIT-licensed, Node 20+.
To migrate from Ghost to Strand in an afternoon, treat the work as a controlled content transformation—not a theme copy. Ghost's migration documentation and Content API documentation provide the source-side context; Strand's repository provides the destination model of MDX files in Git with validation.
A realistic migration has six deliverables: posts, frontmatter, media, URLs and redirects, editorial features, and a cutover plan. Posts are the part that can be scripted most directly. Memberships, subscriptions, themes, and integrations are product decisions and must not be silently discarded.
Migrate from Ghost: the afternoon plan
The phrase migrate from Ghost hides several different moves. This guide covers moving published content into Strand's MDX-in-Git workflow; it does not promise that Ghost memberships, newsletters, themes, or integrations have a one-click equivalent.
Step 1: Freeze the source and make an inventory
Choose a short content freeze window. Record the Ghost site's post count, authors, tags, canonical URLs, publication states, image URLs, and any custom HTML or embeds. Also list the things that are not ordinary posts:
- Members and subscription tiers
- Newsletters and email templates
- Theme behavior and custom routes
- Forms, analytics, search, and integrations
- Redirect rules and external backlinks you care about
This inventory is the acceptance checklist. It prevents a migration script from reporting success while losing the parts that made the site work.
Step 2: Export Ghost content using a documented path
Start with Ghost's migration guidance. Where an integration or API is appropriate, use Ghost's documented custom integration guidance and Content API rather than scraping the rendered theme.
Save the raw export unchanged. Keep it outside the transformed output so you can rerun the conversion and compare results. Record the export timestamp and the source version or endpoint used.
Do not assume that an export includes every member record, email setting, theme asset, or integration. Mark each category as exported, rebuilt, replaced, or intentionally retired.
Step 3: Map Ghost fields to Strand frontmatter
Create a mapping before writing files. A typical post map looks like this:
| Ghost concept | Strand destination | Review question |
|---|---|---|
| Title | title | Is it within the destination schema limit? |
| Slug | slug and filename | Does the public URL remain stable? |
| Excerpt or description | description and summary | Is it a useful answer, not a truncated sentence? |
| Published date | publishedAt | Is the timezone preserved? |
| Author | author | Does the destination author file exist? |
| Tags | tags | Are names normalized without changing meaning? |
| HTML/Markdown body | MDX body | Are embeds, tables, and links valid? |
Strand requires more than moving text. Add the destination content type, primary keyword, keywords, FAQ entries, and visible sources required by the site's content contract. Keep the generated MDX readable so a reviewer can inspect the result.
Step 4: Transform bodies into MDX and move media
Convert each body into MDX conservatively. Preserve headings, lists, links, code, tables, and meaningful emphasis. Replace Ghost-specific cards, embeds, and theme shortcodes with supported components or explicit fallback text.
Download or copy media into the destination's expected asset location, then update references. Check alt text and image dimensions where available. Open representative posts containing galleries, videos, code, and custom HTML; these are where automated conversions most often look plausible but fail in the browser.
Every migrated body should start with <Grounding />, not an in-body H1. The template renders the title from frontmatter. Link the post to the best Ghost CMS alternatives pillar and to Introducing Strand as the product context.
Step 5: Preserve URLs and build redirects
Keep the old slug where possible. Build a source-to-destination redirect table for changed paths, including trailing-slash variants and renamed posts. Test redirects with real HTTP requests after deployment. Check canonical tags and internal links so the new site does not point readers back to retired URLs.
Do not call a migration complete because the home page works. Crawl the destination list, sample old URLs, and inspect 404s, images, feeds, sitemap entries, and Markdown equivalents.
Step 6: Validate, review, and cut over
Run the destination's schema validation and content QA before the cutover. Fix missing authors, invalid slugs, broken MDX, unsupported components, absent sources, and malformed FAQ data. Then manually review a sample from every post type and every high-traffic URL.
Use a two-person sign-off if the site has meaningful traffic: one reviewer checks content fidelity and one checks URLs, metadata, media, and redirects. Keep the Ghost export and redirect table as rollback material. Cut over only after the acceptance checklist is green.
What does not port automatically
A Ghost-to-Strand migration does not promise feature parity. Ghost's docs cover a product with themes, members, publishing, and APIs. Strand's repository describes a Git/MDX publishing core. Plan explicitly for:
- Members, paid subscriptions, and email delivery
- Theme templates and custom design behavior
- Forms, analytics, search, and integrations
- Scheduled posts and editorial permissions
- Cards or embeds with no destination equivalent
The correct outcome may be to keep a separate service for one of these functions or to postpone the migration. A smaller, verified move is safer than a complete-looking import with hidden losses.
Why this matters
Migration is a URL and data-integrity project before it is a CMS preference. The safest path is export → map → transform → validate → review → redirect → cut over. That sequence makes omissions visible and gives you a rollback point.
Step 7: Run a content fidelity review
Automation can tell you that six files parse. It cannot tell you whether a paragraph changed meaning, whether a callout became an empty box, or whether an image now appears beside the wrong caption. Compare the source and destination for title, slug, author, date, body, links, images, and embedded media.
Use a review matrix with one row per migrated post. Mark each field as exact, transformed, manually rebuilt, or intentionally omitted. Require an explanation for every omission. This is especially important for custom HTML and cards: a parser may preserve markup that the destination renderer does not support.
Review the posts that matter most first. Start with pages receiving organic traffic, pages with external links, evergreen guides, and posts referenced from newsletters. Then sample the long tail. A migration is not safe because the five newest posts look correct.
Step 8: Plan the cutover window
Choose a cutover time that leaves room to test without rushing. Lower the chance of a race by freezing edits in Ghost, taking one final export, transforming the delta, and recording the exact destination commit. Keep the old site available until redirects and representative pages have been checked.
At cutover, verify the home page, a post, a tag or archive page, the feed, the sitemap, robots directives, images, and several old URLs. Check from outside the local development environment. A local success does not prove the production host has the same routes or environment variables.
Rollback and post-launch checks
Keep the raw export, the mapping specification, the redirect table, and the last known Ghost deployment details. If the destination has a serious defect, rollback should be a documented operation rather than a stressful reconstruction.
For the first days after launch, watch 404s, redirect chains, missing media, canonical mismatches, and reader reports. Fix the highest-impact problems first and record corrections in Git. The goal is not to claim a perfect automated migration; it is to make every remaining difference known and recoverable.
A useful migration log records more than errors. Note which transforms were applied to HTML, which embeds were replaced, which images could not be fetched, and which posts needed an editor's rewrite. This makes future migrations easier and gives the team an honest explanation of why the destination does not match the source byte for byte.
If the site has comments or member-only content, define the boundary before importing anything. A public post may be safe to transform into a public MDX file; private records may require a different system, a retention decision, or no migration at all. Do not place sensitive data in a repository merely because the export made it easy to access.
Migration acceptance checklist
Before declaring the Ghost migration complete, check each layer separately. At the content layer, compare counts, slugs, titles, dates, authors, tags, and representative bodies. At the asset layer, request every referenced image and inspect alt text, captions, and responsive behavior. At the discovery layer, inspect canonical URLs, the sitemap, feeds, robots directives, and internal links.
At the business layer, confirm what happened to members, paid subscriptions, newsletters, forms, analytics, and integrations. A post migration can be technically green while the business is missing a critical audience workflow. Give each item a named owner and a status of rebuilt, replaced, retained elsewhere, or retired.
At the release layer, confirm the validator ran against the final commit, the redirects were tested from the public host, and the team knows how to roll back. Keep a short record of the cutover timestamp and the unresolved differences, even when the unresolved list is empty.
A migration is a project, not an import button
The temptation is to start with a converter and discover the requirements afterward. Reverse that order. Write the inventory and mapping first, choose a representative sample, then automate only the transformations you can inspect. Keep a human review step for every content feature that has no exact destination equivalent.
That approach may leave a few Ghost features outside the first release. It is better to launch a smaller, verified publication than to claim that members, redirects, media, and custom embeds survived when they did not. The migration is successful when readers can find the right pages and the team knows who owns the new system.
Keep the source export read-only during the acceptance period. If a reviewer discovers a missing paragraph or wrong image, correct the mapping or source data and rerun the transformation instead of editing only the destination by hand. That keeps the migration reproducible and reduces the chance that a later rerun silently removes the fix.
Record the final redirect tests and the reviewer who approved the cutover. This small paper trail turns a risky switch into an auditable release and gives the team a clear starting point for later corrections.
A documented handoff is part of the migration deliverable.
The receiving team should have the export location, mapping notes, redirect table, validation command, and rollback contact before launch day. Without that handoff, a technically successful import can still become an operational failure.
FAQ
Can every Ghost feature migrate automatically?
No. Posts and metadata are the easiest part. Themes, members, subscriptions, and integrations need separate rebuild or replacement decisions.
What should I export first?
Export documented content and metadata, then inventory media, redirects, members, themes, and integrations separately.
Will URLs stay the same?
They can when slugs and routes are preserved, but test redirects and canonical URLs rather than assuming it.
How do I validate the migration?
Run the destination schema validator and batch QA, then manually review rendered content, links, images, metadata, and representative edge cases.
Questions
- Can I migrate every Ghost feature to Strand automatically?
- No. Posts and metadata can be transformed, but themes, members, subscriptions, and integrations need separate decisions and manual review.
- What should I export before leaving Ghost?
- Export the content and metadata available through Ghost's documented migration and admin/integration paths, then separately inventory media, redirects, members, themes, and integrations.
- Will Ghost URLs stay the same after migration?
- They can if you preserve slugs and configure the destination routes, but verify every redirect and canonical URL rather than assuming a one-to-one mapping.
- How do I validate a Ghost-to-Strand migration?
- Run the Strand schema validator and batch QA, then review rendered posts, links, images, metadata, redirects, and representative content manually.
Sources
- Ghost migration documentation — Ghost
- Ghost custom integration guidance — Ghost
- Ghost Content API documentation — Ghost
- Ghost documentation — Ghost
- Strand CMS repository — Strand CMS