Migrating my own site with the Experience Modernization Agent
This story begins with a question that I asked myself: would I post to this site more often if it were easy (and enjoyable) to do so?
My last post to this blog was nearly 3 years ago to the day. In years prior I had a somewhat regular cadence of posts, with 2019 being the year where I made (and stuck with!) a New Year's resolution to publish a post per month1. With so much of a developer's time now spent reading and attempting to understand the work of their agents, I found that I was missing the deliberately "slow" process that I used to enjoy when I would sit down to write an article.
Would I really post more often if I didn't have to re-learn the mechanics of my Jekyll-based blog every time? How could I reduce the friction of getting a post published? What if all I needed to do was open up a browser tab and start drafting?
---
For the last two years I've worked on migration tooling backed by frontier LLMs, known as the Experience Modernization Agent (or EMA for short). The target of our migrations has always been AEM Edge Delivery Services. In the beginning it was document/Word-based sites, then Crosswalk (AEM Authoring), then Document Authoring (DA), and now Experience Workspace.
I'd previously pointed our tooling at this site for testing, but I'd never committed to a full migration. Thirteen years of posts, static slide decks, a resume and other stray assets made it seem like more trouble than it was worth. This changed when we integrated Opus 5.5 as the engine behind EMA. The quality of the results jumped immediately and noticeably. Not only were the fidelity and structure of the migrated sites better, but the number of prompts and "steering" required to get there was also reduced. The project went from "someday" to "this Friday."
In this post I'll walk through what I did to migrate this site to Edge Delivery Services using EMA. It's a relatively simple site, which helped me keep it timeboxed to a couple of days, end-to-end. Along the way I've included a few tips that I think unlock the tool's real strength.
If you want to follow along and have an Adobe ID associated with any organization, you can start using EMA today at https://aemcoder.adobe.io/ 2
Tip #1: Maximize agent agency
... while minimizing the blast radius.
I won't cover the nitty-gritty of project setup as it's detailed nicely in our official docs on Experience League. In short: use the boilerplate template (or this one for Crosswalk), then add the Code Connector and Code Sync apps to the repo. Before you provide your new site's preview URL to EMA, make two changes on EMA's Settings page.
First, on Github, generate a Personal Access Token (PAT) with access only to your new repo. I chose to add the Contents and Pull requests, read and write, like so:
When prompted in EMA to connect to GitHub, provide it with this newly minted PAT.
While you're on the Settings screen, I like to enable "Allow LLM to use my Adobe credentials for admin.hlx.page, Document Authoring, and repositories hosted outside GitHub", and "Allow LLM to use my git credentials".
Why? This allows EMA to upload to DA, preview pages, and commit code to git without requiring me to interact with the Sync button in the UI. I've found this to be a huge time saver, as the preview environment in EMA is not always a 100% match for the site as previewed on aem.page (try as we might). With this ability unlocked, the agent can load your actual site on aem.page, make code or content changes, commit and/or preview them, and see the result of its work directly as rendered by AEM.
Tip #2: Describe the outcome, not the steps
Here's how I kicked off this migration:
Migrate all the blog related pages on https://implementationdetails.dev/ to AEM. This site consists of listing pages (such as the index page and paginated listings like https://implementationdetails.dev/page2/), and blog article pages. Explore these pages and figure out how you can migrate them all such that there are no dead links once we flip to the migrated site. Create necessary Edge Delivery Services index such that the listing pages are dynamic based on the blog post pages and the date which they were originally posted. Ask any clarifying questions now.
I always find the clarifying questions that it comes back with to be interesting:
The first question will be familiar to anyone who has migrated a site where the origin URLs all end with a trailing /. Had I chosen "exact URLs", each page in Experience Workspace would have been named index in a folder bearing the article name ("slug") which I did not want, hence my choice of option 2.
While I initially did not want the "Legacy slide decks" and RSS feed to be migrated, EMA talked me out of it in a follow-up (as evidenced in the first PR).
And with that, the migration was underway. In just over 70 minutes, EMA had produced a PR that was ready for my review. In its words, abbreviated from a more detailed summary:
All 38 posts, the homepage listing, and the contact and thank-you pages are migrated and published. Every old URL I tested redirects to its new page on the live host. The code is in pull request #1, which needs to be merged before the switch: https://github.com/blefebvre/da-impl-det-blog/pull/1
This is where Tip #1 starts to pay off: the agent can get changes live, safely and reversibly, without waiting for me or requiring any clicking around in the UI or on GitHub.
The second phase of the migration was kicked off with a follow-up prompt, concise and to-the-point, which ended up doing quite a bit of work behind the scenes:
With that complete, I had a very faithful reproduction of my blog available on AEM: https://phase1--da-impl-det-blog--blefebvre.aem.page/
Before and after, viewing an article:
Simple as this migration was, the agent made a few smart moves worth highlighting:
- Paginated listing pages: everything on this site was previously static. EMA created a single dynamic homepage powered by a query index and query params (
?page=N). It set up the index and validated that it worked. The agent even set up a redirect sheet so the old/pageN/links redirect to the new location. - Clean URLs: all posts were moved to
/blog/YYYY/MM/DD/slugwith no trailing slash. Every old URL has an entry in the redirect sheet, too. Dead links bad! - Import scripts: turned every page into Edge Delivery content, broken down into 3 templates. Had this been a larger migration, the repeatability of declarative import scripts would be invaluable.
- Static files: the old reveal.js slide decks and (much outdated) resume were committed to the code repo exactly as they were. No content was abandoned in this migration.
- Sitemap, robots.txt, and RSS feed: these three assets are now generated from the site's query index instead of by Jekyll. The feed would almost certainly have been dropped had I done this move in a more manual way, yet now it lives on!
Tip #3: Let Stardust propose a redesign
With the migration technically complete, it dawned on me that my old blog was starting to look its age. We recently integrated Stardust into EMA, so I thought I would give it a chance at redesigning things via its "uplift" skill. I used the following prompt:
Checkout a new branch named v2, then enable the stardust skills and run them to propose an "uplift" redesign of this site.
A short while later I was presented with four options which I could browse directly in EMA's preview window. My initial favourite of the four:
With a bit of steering, I landed on a redesign of the homepage that I really like. EMA even proposed a very slick post browser/search:
To wrap things up I asked the following:
What are the next steps to go-live? I have a cloudflare account for this site's DNS
A detailed response was provided with steps linking to the relevant docs on aem.live. With a bit of time for DNS changes to propagate and some tinkering with Cloudflare Workers, my migrated site was live!
---
Back to the question I opened with: would I post more often if it were easy to do so? Only time will tell, but the early signs are good. I wrote this post entirely in Experience Workspace over two days, squeezed between my day job and hosting family dinner for Canadian Thanksgiving. No local build, no re-learning Jekyll.
What surprised me most about this little project was not that EMA could migrate my site, but that it made a series of good decisions based on a few high-level prompts. It added redirects for every old URL, talked me into keeping an RSS feed I'd planned to drop, and helped me with a redesign I'm genuinely excited about.
If you've been putting off a migration, or tried an earlier version of our tooling and got stuck, it might be time to take another look: https://aemcoder.adobe.io/
---
1 The discerning reader will note a post conspicuously missing from February 2019. But, I doubled up in June!
2 If you don't have an organization but want to start a migration, email me with your use case (firstname.lastname at my company's domain) and I'll see what we can do to get you set up :)