Static site to EmDash: when to skip the migration and just rebuild
For the marketing lead at a small SaaS whose 30-page hand-coded HTML site has become a dev bottleneck: when migrating to a CMS makes sense, when starting fresh on EmDash + Astro is faster, and the surprisingly common third option — leave it alone.
We get a version of this email once a month. “We have a 30-page HTML site. Marketing emails me copy changes. I’m tired. Should we move to WordPress?”
The honest answer almost never starts with “yes.” Sometimes it’s “migrate to a CMS.” Sometimes it’s “rebuild from scratch on EmDash, faster than the migration.” And sometimes — more often than the CMS-vendor blogs admit — it’s “leave the site alone, fix one workflow, ship more important things.”
This post is about how we tell those three apart.
What a static site is and why this post even exists
A static site is HTML, CSS, and JavaScript that a server hands to a browser without rendering anything per request. No database query, no PHP, no React server bundle. Hand-coded HTML is static. So is anything output by Eleventy, Hugo, Jekyll, plain Astro with no CMS, or a Notion-to-HTML script you wrote in 2022. The Astro team’s own “What is a static site generator?” explainer is the canonical framing if you want a reference.
The reason this post exists: most “should I get a CMS?” content assumes you’re already on WordPress and the question is which other CMS to switch to. The market for people coming from a static site is just as big and gets way less honest writing. The HTTP Archive’s 2024 Web Almanac CMS chapter shows roughly 36% of sites use no detectable CMS at all — many of those are exactly the audience for this post.
We exist on the other end of that audience’s emails. So this is the framework we actually use on intro calls.
The honest case for staying static
Before we sell you a migration, here’s when you should walk away and not migrate at all.
Your content barely changes. If the homepage hero hasn’t been edited in 14 months, you don’t have a CMS problem. You have a “marketing isn’t producing copy” problem. A CMS will make that worse, not better — now there’s a new tool to forget the password to.
You only have one or two editors. A CMS earns its keep when 4+ people need to touch content. With one marketer and one founder, a shared Google Doc plus a 30-minute weekly “I’ll deploy these on Friday” cadence is cheaper than any CMS we know of, including ours.
Your site is under 15 pages. Below that threshold, opening the HTML file in VS Code and editing the copy is genuinely faster than logging into any CMS, finding the page, finding the field, hitting save, and waiting for a build. We’ve timed this on real client sites.
You don’t have $1,500 + ongoing maintenance budget. A migration is not a one-time cost. The CMS upgrades. The host changes pricing. Plugins drift. If the budget is “zero,” static is the rational answer.
So why does this post exist if a third of you should stay put? Because the other two-thirds genuinely have outgrown static, and the signals are concrete.
Three signals that say “you’ve outgrown static”
Walking through the last 18 months of inbound, the static-site teams who actually benefited from a move all hit at least two of these.
Signal 1: Marketing emails the dev team copy changes weekly
You know the email. “Hey, can you change the headline on the pricing page from ‘Built for teams’ to ‘Built for engineering teams’? Also the testimonial on /home, the founder’s title is wrong now.” It’s a 90-second edit followed by a 20-minute deploy followed by a “looks good” reply.
If you get more than one of these per week, your dev team is a content router. That’s the strongest single signal.
The dev-as-router pattern is sneakier than people think because no individual ticket feels expensive. It’s the interruption cost that bleeds you. A senior engineer pulled out of focused work to deploy a comma fix loses 23 minutes of velocity, not three. Ten of those a month is two engineering days, gone.
Signal 2: Content has shape, not just text
A typed CMS earns its money when content has structure that repeats — case studies with the same six fields, team members with the same eight, products with pricing tiers and feature lists.
If your “case studies” are six divs you copy-pasted six times and now have six different bug-flavors of broken margin, you don’t have a static-site problem. You have a structured-content problem that static rendering wasn’t designed to solve. EmDash content types (defined in defineContentType) handle this in 20 lines:
import { defineContentType } from "emdash";
export const caseStudy = defineContentType({
name: "case-study",
fields: {
title: { type: "string", required: true },
client: { type: "string", required: true },
industry: { type: "string" },
problem: { type: "richtext", required: true },
solution: { type: "richtext", required: true },
metrics: {
type: "array",
of: { label: "string", value: "string" },
},
publishedAt: { type: "datetime", required: true },
},
});
That schema is worth more than it looks. Marketing can add a case study without copying anything. Claude (via MCP) can read the schema and produce a draft. Your eight case studies all render through one component, so a margin fix happens once.
Signal 3: You want AI-editable content
If your team is already paying for ChatGPT, Cursor, or Claude and using them for adjacent work — drafts, internal tools, code review — the gap to “Claude can edit our marketing site” is a CMS with structured types and an MCP server. Static sites can’t do this. There is nothing for an MCP server to introspect; it’s just HTML files. EmDash’s built-in MCP support is the shortest path we know of from “we use AI internally” to “AI can ship copy changes.”
If you don’t use AI tools and have no plans to: ignore this signal, weight the other two.
Migration vs. rebuild — the decision framework
Here’s where the post earns its keep. Once you’ve decided you’ve outgrown static, the next question is not “which CMS.” It’s “do we port what we have, or rebuild from scratch?” These have very different price tags and very different timelines.
| Signal | Migration (port what you have) | Rebuild (start fresh on EmDash + Astro) |
|---|---|---|
| Dev-bottleneck weekly emails | Right call when the existing site has good information architecture and the IA shouldn’t change. | Right call when the IA itself is part of the problem (pages added ad-hoc over years, no consistent navigation). |
| Content has shape | Right call when 80%+ of pages use 5–6 repeating templates that map cleanly to content types. | Right call when current pages are bespoke divs and modeling them out is harder than designing from scratch. |
| Want AI-editable content | Right call when the site has 50+ pages — porting them beats re-writing all that copy. | Right call when the site has under 30 pages — the rebuild is literally cheaper than the migration audit. |
We tell prospects under 30 pages to consider the rebuild because the math actually flips. A migration includes a content audit, a content-type design pass, a redirect map, an Astro port, and a content move. A rebuild from scratch on a starter template skips the audit and the redirect map. For small sites, “migrate” is often more work than “redo.”
We did one of these last quarter for a 22-page hand-coded HTML site. The migration estimate was $2,800. The rebuild estimate — same content types, same Astro starter, retyping copy out of a Google Doc the founder already maintained — was $1,400. We did the rebuild. Two weeks later, marketing was editing copy through Claude Desktop. The founder told us, in writing, that he’d budgeted three months and was confused that we were already done.
What the rebuild path looks like on EmDash (compressed walkthrough)
If you go the rebuild route, this is the order it tends to run.
Day 1: content inventory. Not the existing HTML — the content that’s worth keeping. Founder writes a 1-page list. “Hero, three product features, pricing, FAQ, contact.” Anything not on that list doesn’t get rebuilt.
Day 2: content types. We translate that list to EmDash content types. Each type is 10–30 lines of TypeScript. The whole modeling pass is usually under 4 hours.
Day 3–5: Astro components. One Astro component per content type. Vanilla CSS — no Tailwind, no styled-components. Astro’s native content collections + integrations docs cover the wiring. Here’s the shape of the typical hero:
---
// src/components/Hero.astro
import { getEntry } from "astro:content";
const hero = await getEntry("hero", "home");
const { headline, subhead, ctaLabel, ctaHref } = hero.data;
---
<section class="hero">
<h1>{headline}</h1>
<p>{subhead}</p>
<a class="cta" href={ctaHref}>{ctaLabel}</a>
</section>
<style>
.hero { padding: 4rem 1rem; text-align: center; }
.hero h1 { font-size: clamp(2rem, 5vw, 3.5rem); }
.cta { background: var(--color-accent); color: white; padding: 0.75rem 1.5rem; }
</style>
For comparison, the same thing in the original hand-coded HTML often looked like this:
<!-- existing index.html, around line 240 -->
<section style="padding:64px 16px;text-align:center">
<h1 style="font-size:48px">Built for engineering teams</h1>
<p>The CI platform your team will not curse at.</p>
<a href="/signup" style="background:#0d6;color:#fff;padding:12px 24px">
Start free
</a>
</section>
Same output. Different editing story. The Astro version pulls copy from EmDash content; the HTML version requires editing the file.
Day 6–7: content-import + Claude wiring. We move copy from the Google Doc / old HTML / wherever it lives into EmDash. Then we configure the Claude Desktop MCP endpoint so the marketing lead can edit the live content from Claude. (See the vibecoding marketing-site post for what that workflow looks like in practice.)
Day 8–9: Cloudflare Pages deploy + DNS swap. The site goes live. Old DNS gets cut over. Old static host gets paused.
Day 10: 30-minute walkthrough with the team. That’s the whole rebuild.
What the migration-in-place path looks like
The migration path looks similar at the end but adds three steps in the middle.
- Audit pass. We document every page template and every content shape in your current site. For an Eleventy or Hugo site, this means reading every layout file. For hand-coded HTML, it means clicking every page and noting how the markup repeats. This is the time-consuming part.
- Redirect map. If URLs change — and they sometimes do, because a CMS imposes some structure your hand-coded site never had — we write a redirect map and ship it as part of Cloudflare Pages config.
- Content extraction. Pulling the actual copy out of the existing HTML, into a format we can import into EmDash. For Markdown sources (Hugo, Eleventy) this is fast. For HTML it’s slower because of inline styling and inconsistent structure.
Then the rebuild steps run on top — same Astro components, same MCP wiring, same deploy.
This is the path our /services/migrate-static engagement runs. The starting price is $1,500, and the typical timeline is two weeks. If your site is closer to 50–80 pages with consistent IA, this is almost always the right call. The migration playbook we use for WordPress sites — documented here — has a near-identical static-site variant.
When to call us, when to DIY
Not every project needs us. Here’s how we triage.
DIY territory. Your team has at least one developer comfortable with Astro and the basics of structured content. Your site is small (under 25 pages). You’re willing to read the EmDash docs and watch the vibecoding-a-site walkthrough. Honestly: do it yourself, save the money, ping us if you get stuck on a specific thing.
Call us. Your site is bigger (40+ pages), your IA is inconsistent, your existing build process is weird (custom Pug, Pandoc, sed scripts in a Makefile we’ve definitely seen this before), or your team doesn’t have time to drive a migration end-to-end. The two-week scope on /services/migrate-static absorbs most of those edge cases.
Probably skip both. You hit none of the three signals from earlier. Save the money for a feature your customers asked for.
FAQ
Is EmDash production-ready for a static-site rebuild in May 2026?
EmDash launched April 1, 2026 and is on v0.1.0 as of writing. We treat it as production-ready for marketing sites where the editorial team is small and we own the maintenance retainer. We would not put a 50-author publication on it yet. For 30-page hand-coded sites being rebuilt by a small team, the risk profile is fine — see our full WordPress vs EmDash comparison for the broader caveats.
Will SEO survive a static-to-EmDash rebuild?
Yes, with a real redirect map. Astro + Cloudflare Pages serves the same HTML to crawlers as a static host does — Googlebot can’t tell the difference. We preserve URLs whenever possible; when we can’t, we ship 301s in _redirects. The only SEO failure mode we’ve seen on these projects is people forgetting <title> tags, and that’s a checklist item, not a stack issue.
What if my site has a custom build pipeline?
Most weird build steps translate cleanly. Pug → Astro components. Pandoc/Markdown → Astro content collections. sed scripts → a build hook in astro.config.mjs. The only pipelines we’ve had real trouble porting are ones that depend on a server-side step we can’t replicate at build time — and those are rare on marketing sites. Tell us about it on the intro call.
How is this different from going headless WordPress?
Headless WordPress fixes the frontend delivery layer — you get fast pages — but the WordPress backend chaos stays. Plugins, serialized postmeta, hosting variability, all still there. EmDash fixes both ends: typed schemas in the backend and edge-served Astro on the frontend. See our WordPress comparison for the full breakdown.
Can I migrate myself and just hire you for the EmDash setup?
Yes — see /services/vibecode-setup. It’s the lighter engagement: we wire EmDash + MCP + Cloudflare and hand you the keys, you do the content port. Works well for teams with at least one developer who wants to learn the stack.
Bottom line
A static site is not a problem. A static site is a perfectly good way to ship a marketing presence, and the web has roughly 36% of itself running without a detectable CMS to prove it. The problem is when your specific site is now in the way of your specific team shipping copy.
If you’re hitting the three signals — dev-bottleneck emails, content with repeating shape, real interest in AI-editable content — moving is the right call. The further question of “migrate or rebuild” comes down to size and IA quality. Under 30 pages with messy structure, rebuild. Over 50 pages with clean structure, migrate. In between, it’s a judgment call we’re happy to make on a 20-minute intro.
If you’re not hitting the signals: stay static. Fix the workflow, not the stack. We’ll write a different post for you when you’re ready.