Vibecoding a marketing site: WordPress is the problem, EmDash is the answer
For developers who already live in Cursor and Claude — why WordPress is structurally hostile to your workflow, and what a vibecode-native CMS actually feels like.
I’ll define “vibecoding” the way the people I know use it: writing software primarily through conversation with an AI agent. Not “AI-assisted coding” (autocomplete, copilots, occasional Claude lookups). The full thing — you describe what you want, the agent makes the changes, you review the diff, you ship. Cursor, Claude Code, Continue, Cline, Aider — pick your weapon.
If you’re already vibecoding day-to-day, you’ve already discovered that some codebases are a joy with this workflow and others are punishment. WordPress is, structurally, in the punishment category. Not because WordPress is bad — it’s not — but because every assumption baked into WordPress makes it hostile to AI agents.
This post is for people deciding what to scaffold the next greenfield client microsite on. If WordPress is on your shortlist for an AI-first build, this is why I’d cross it off.
What “AI-first” actually demands of a CMS
Five things, in priority order:
1. Typed schemas. The agent needs to know what fields exist, what types they have, what constraints apply. Without schemas, every edit is “look at the existing data, infer the shape, hope you’re right.” You’ll get 80% right and 20% will silently corrupt fields.
2. A standard interface. Some way for the agent to enumerate content, read it, write it back, validate it. MCP is the current best answer because it’s actually standardized. Custom REST APIs work too, but each new project requires teaching the agent what’s there.
3. Source-mapped editing. When the agent edits “the hero headline,” there should be exactly one place that maps to. Not five places — not “the hero is in the page builder, but there’s also one in the legacy ACF field, and a third that overrides them both via a shortcode.”
4. Local development that mirrors production. The agent runs code, tests, sees what happens. If your dev setup requires Docker, MAMP, a specific PHP version, and a manually-imported database, the agent can’t iterate. The agent can iterate if your dev environment is pnpm dev.
5. Side effects you can reason about statically. When the agent changes a config, it can predict what changes — without booting the runtime and watching for breakage.
Look at WordPress against that list and you can already see the answer.
Why WordPress fights every one of these
It’s worth being specific about why WordPress is hostile, because “WordPress is bad for AI” gets thrown around without enough detail.
Schemas don’t exist as first-class citizens. ACF gives you something close, but it’s a plugin, optionally installed, with no compile-time guarantees. Most WordPress sites have a mix of post fields, postmeta rows, ACF fields, page-builder JSON blobs, and theme customizer options. The “schema” is whatever shape the data happens to be in.
The interface is the WordPress REST API plus 27 plugins. Each plugin can add endpoints, modify endpoints, deprecate endpoints, or break endpoints. There’s no single MCP-equivalent endpoint that says “here’s everything on this site, typed.”
Editing is multi-source. The hero headline might be in the post title, a page-builder JSON blob, a customizer field, and a translated copy in WPML, all different. When you ask Claude “edit the hero headline,” it has to guess which source wins.
Local dev is a project. You need PHP, MySQL, a webserver, and the same plugin combination as production. Local by Flywheel is the best UX for this and it still takes 20 minutes to spin up a new site. Compare to pnpm create astro@latest taking 90 seconds.
Hooks and filters are runtime side effects. A plugin’s init action might swap a filter on a post-meta read, which changes how the next plugin reads the same field. The order of plugin activation matters. AI agents reasoning about a static codebase can’t predict what the runtime does.
That’s WordPress. None of it is intractable; people ship AI-edited WordPress sites. It’s just slow, frustrating work that fights the workflow.
What EmDash + Astro looks like, by contrast
Pick the same five attributes and you can see why I bet on it.
Typed schemas. Every content type is a TypeScript schema. hero.headline: string, max: 80. The agent reads it. Validation runs at write time.
// emdash/content-types/hero.ts
export default {
name: 'hero',
fields: {
headline: { type: 'string', required: true, max: 80 },
lede: { type: 'string', required: true, max: 240 },
},
};
Standard interface — MCP, in the box. EmDash ships an MCP server. Configure Claude Desktop or Cursor with the endpoint and your agent immediately knows every content type, every field, every constraint. No glue code.
Source-mapped editing. Each content type has a single source of truth. The hero headline is one place. Edits to it write to one file (or one D1 row). No multi-source ambiguity.
Local dev is pnpm dev. Astro project, SQLite locally, R2 mocked. 90 seconds to a running dev server. The agent can iterate freely.
Side effects are explicit. EmDash plugins declare their permissions upfront. A plugin can’t read a field it wasn’t granted. A plugin can’t fire a hook the rest of the system doesn’t expect. The static codebase is what it looks like.
The five-point checklist isn’t EmDash-specific; Sanity, Payload, Decap all do well on it. EmDash is the most aggressive in just shipping MCP support out of the box, which moves it from “AI-friendly” to “AI-native.” That’s the bet.
A real vibecode session, walked through
Concrete example. A client comes in: “Add a pricing page. Three tiers, the middle one featured. Use the brand colors. Match the existing hero style. Wire it into the nav.”
On WordPress, that’s a 30-minute project: open the page builder, find a pricing template, customize, publish, edit the menu. Most of the time is in the page-builder UI, plus the inevitable five minutes of “why is this column wider than that one” CSS hunting.
On the EmDash + Astro stack, vibecoding it:
Me: Add a pricing page at /pricing. Three tiers — Starter $99,
Pro $299 (featured), Enterprise (contact sales). Match the
service-card visual style. Wire it into the header nav.
Claude: I'll look at the existing service-card pattern first.
[reads src/components/blocks/ServiceCard.astro]
[reads src/pages/services/index.astro]
Got it. I'll create a pricing content type, add three entries,
and build a /pricing page using ServiceCard with featured=true
on Pro. I'll also update Header.astro to include the new link.
Sound right?
Me: Yes, but use a new <PricingCard> component — service cards
have different copy patterns. Otherwise yes.
Claude: [creates src/components/blocks/PricingCard.astro
creates src/pages/pricing.astro
creates src/content/pricing/{starter,pro,enterprise}.md
edits src/content.config.ts to add the pricing collection
edits src/components/layout/Header.astro to add /pricing]
Done. PR diff is in branch feat/pricing-page. The Pro card has
the featured ribbon. Lighthouse on a build is 96/100/100/100.
Want me to push?
Total elapsed: 4 minutes. The longest part was Claude reading the existing ServiceCard for the style pattern.
That isn’t possible on WordPress without a custom plugin or a full custom theme — and on a custom theme you’ve left the WordPress vibecoding question and entered “build a Next.js theme” territory. EmDash makes the simple case simple.
What still needs human thought
I want to be honest about the parts vibecoding doesn’t solve. If you go in expecting these to be free, you’ll be disappointed.
Visual design. Claude won’t tell you whether your pricing page should have three columns or stacked cards. It’ll happily implement either. You still need design judgment.
Copy. Claude will write copy if you ask. The copy will be average. If you want a marketing site that converts, the copy needs a human (or a much more directed AI session — and even then, review).
Decisions about scope. “Build a pricing page” sounds simple but hides decisions: which tiers, what features each gets, free trial yes/no, monthly vs annual toggle, etc. The agent doesn’t have product context; you do.
Performance trade-offs. Claude will happily import a 500KB charting library if you ask for “a pricing comparison chart.” You need to push back: “use SVG, no library, no JS.” The agent doesn’t know your performance budget unless you tell it.
Hosting and infra. “Make it deploy” is too vague for an agent to act on. You configure Cloudflare Pages, set env vars, attach the domain. The agent can write the CI workflow once you’ve told it which provider.
What vibecoding does free up is the muscle work — the syntax, the boilerplate, the “import the right thing, make the build pass.” That’s most of what made WordPress edits annoying. EmDash + Astro removes that pain. The thinking pain is still yours.
Setting up a vibecode-ready stack
If you want to scaffold this for the next greenfield client:
- Astro 6 with vanilla CSS, MDX for content, content collections for typed data.
- EmDash as the CMS, configured with content types matching your design system.
- Cloudflare Pages for hosting (and a separate Worker for forms).
- MCP wired up in Claude Desktop or Cursor.
- A README with the prompts that work — copy-paste recipes for “add a section,” “rename a field,” “deploy to a new domain.”
The README is the secret. Without it, every new project is rediscovery. With it, your next vibecode session starts where the last one ended.
We do this setup as a paid engagement when teams want a working starting point in a week instead of a month. That’s the vibecode setup service — $1,500, includes the stack provisioning, the MCP wiring, the README, and a walkthrough.
FAQ
Do I need Claude Pro or Max for vibecoding to work?
Yes. Claude Code requires an active Claude Pro, Max, or API plan to authenticate; the free tier won’t drive an agent loop. In our setup we run on Max for the higher rate limits, but Pro is enough to start. Cursor users can substitute their own Cursor Pro subscription for the same model access (Anthropic Claude Code docs, 2026).
Does this work the same way in Cursor?
Largely yes. Cursor speaks MCP natively, so an EmDash MCP server registered in Cursor’s settings exposes the same content-type tools that Claude Desktop sees. The vibe is slightly different — Cursor leans more on inline-edit flows, Claude Code on full-repo agents — but the schema-aware editing story is identical (Cursor MCP docs, 2026).
Will my AI agent write code I don’t understand?
It can, especially on first sessions in a new framework. The discipline that keeps this safe is reading every diff before merging — not skimming, reading. If a chunk feels opaque, ask the agent to explain it inline, or rewrite the prompt to constrain output to patterns you already know. Treat agent output like a junior pair, not a black box (Anthropic Claude Code docs, 2026).
What’s the cost of running this workflow daily?
For a solo developer in 2026: Claude Max at $100–200/month, Cloudflare Pages free tier for hosting, a domain at ~$12/year, and the EmDash project itself is open source. The real cost is your review time — figure 20–30% of saved coding time goes back into reading diffs. The net is still strongly positive on greenfield work (Astro deployment docs, 2026).
Can a non-developer marketer vibecode the site themselves?
No, and we don’t recommend trying. The split we ship to clients: developers vibecode the components and content schemas; marketers edit content through the EmDash MCP connection from their own Claude Desktop. That keeps the typed structure intact while still letting non-devs ship copy changes without a PR (Model Context Protocol spec, 2026).
When you should NOT vibecode this
Five cases where I tell people to slow down:
You don’t actually want to learn the stack. Vibecoding produces correct code, but if you can’t read or modify the diffs, you’re stuck the day Claude can’t fix something. Treat agent output as “cofounder writes code, you understand it” — not “code disappears into a black box.”
You’re new to the underlying tools. If you’ve never written Astro, the first vibecode session will produce code you don’t understand. That’s fine — but the first project shouldn’t be a high-stakes client site. Build something throwaway first.
The project genuinely needs WordPress. Membership site, complex e-commerce, a 50-person editorial team. Don’t try to vibecode your way out of a tool fit problem.
You don’t have a strong design. Vibecoding amplifies whatever direction you give it. If your direction is fuzzy, you’ll ship fuzzy work fast. Ship a Figma first, then vibecode against it.
You’re tempted to skip code review. Don’t. Read the diffs. The day an agent ships a subtle off-by-one to production is the day this whole movement loses credibility.
The honest summary
Vibecoding is a real productivity gain on a marketing site, in 2026, on the right stack. WordPress is the wrong stack — not because the AI can’t edit WordPress, but because the WordPress structure makes editing fragile. EmDash + Astro is the most aggressive bet on the right stack for AI-first development right now. It’s also six weeks old, so know what you’re signing up for.
If you’re choosing between learning EmDash now or waiting for the ecosystem to stabilize, my answer for the last six weeks has been: learn it now, ship one client on it, reassess in 90 days. We’re three clients in. The reassessment hasn’t surfaced anything fatal yet.
The case for migrating an existing WordPress site is a different post — start there. The case for a greenfield vibecode build, the post above is the case.
The intro call link is below if you want help running this on a real project.