This page was translated from the original by AI.

I've been blogging on and off for quite a few years now, though I never stuck with it consistently. I tried WordPress, Jekyll, and Ghost, but eventually settled on Astro for my blog, which has held up for a decent stretch. When Cloudflare announced their WordPress replacement EmDash, I didn't jump on it right away since it was in preview. After a few months, seeing that it was still getting regular updates and that quite a few people had already migrated, I decided to start the move myself.

Migrating with Claude Code

As of September 2026, most people are probably doing migrations through AI. The AI is good enough now that I just opened up Claude Code and typed:

https://docs.emdashcms.com/existing-project/

参考这个, 把现有的astro 更改成使用 emdash 管理的CMS

The AI then starts installing EmDash based on the docs and the existing project structure. I installed the Cloudflare Connector, and Claude Code even went ahead and created D1 and R2 for me. It really saves both time and effort.

emdash-setup-1.png
emdash-setup-2.png
emdash-setup-3.png



After a while, I successfully deployed EmDash to Cloudflare and got the admin panel set up with PassKey login (which turned out to be a trap—more on that in a later post).

Two Key Takeaways from the Initial Deployment

Even though Claude Code made the whole deployment pipeline buttery smooth, based on my actual experience there are two crucial lessons I need to flag upfront:

1. Your existing MDX posts: make absolutely sure they're in EmDash before you delete anything!

Your local Markdown/MDX files are your absolute asset in Git. After importing content into EmDash, go through the Admin panel and the frontend to confirm every piece of data is fully present in the Cloudflare D1 database. Whatever you do, don't rush to delete your local files the moment deployment succeeds. Keep a complete archive backup first, and only clean up once you've verified there's no data loss.

2. Strong recommendation: configure your custom domain first, then set up PassKey login!

This is a sneaky pitfall that most people (myself included) are very likely to trip over:

- Many people, right after deployment, habitually complete the admin initialization on the default *.workers.dev temporary domain and casually bind their device's PassKey.

- However, PassKey (WebAuthn) is strictly bound to the access domain (Origin / rpId). Once you later bind your own custom domain, the PassKey created under workers.dev will simply stop working when you access via the custom domain—you won't be able to log in with it!

Next up: The PassKey trap that nearly locked me out of my own admin panel

The second point from the previous section is actually the most painful lesson I learned firsthand during this deployment:

I happily set up my PassKey under workers.dev, but when I bound my custom domain, the admin panel on the custom domain couldn't pull up that PassKey at all.

At that point the system suggested logging in with an email verification code—and here's the awkward part—I hadn't configured any email provider yet!

PassKey wouldn't work, email codes weren't arriving, and I nearly locked myself out of the admin panel I'd just built with my own hands...

How did I get out of that jam? And how do you configure email plugins in Cloudflare's edge environment? In the next post, we'll dig deep into this ridiculous PassKey and authentication saga.

Epona
Written byEpona

There's nothing wrong with having a little fun

x.com/simura_epona

Loading comments…