Marc Denning

Migrating a Website with Claude

I have been using Claude for various work tasks and some personal tasks for about 9 months now. Call me an AI skeptic - that would be fair! I recognize the capabilities of generative AI to produce code quickly and to assist developers, but I was slow to pick up a tool as a daily driver. A lesson I picked up from my dad is to wait for the first patch release of a new system - if you are optimizing for stability, you never want to be an early adopter.

At work, Claude is our primary Gen AI platform followed by Atlassian's Rovo and Microsoft's Copilot. I started using Claude slowly and more earnestly toward the beginning of the year. At that point, it was clear that tools like Claude are going to persist in the software development space for a while and I felt behind in building skills for using the tool.

Now that I have more first-hand experience with Claude and Claude Code specifically, I have been turning the tool toward some personal projects that have been on the backburner because they feel like they will take more time than I can devote to them. One of these was projects was migrating from AWS Amplify to Google's Firebase. The goal of the project was to consolidate cloud platforms being used personally in order to lower the mental load and to consolidate cloud bills. I decided to turn Claude toward this project to help me migrate without having to dive into the details and rebuild scripts and infrastructure myself. In this blog, I'll take you through what the process looked like: what worked, what didn't, and what I learned.

Setting up the context

One of the top tips you can find about using gen AI tools like Claude Code effectively is to provide enough context and the right context on your project. For this website, I already had an AGENTS.md with some instructions about how to build the project, how content is organized, and how the site is deployed. The CLAUDE.md file points directly at AGENTS.md since as of this writing, Claude Code does not read AGENTS.md by default.

Starting from this point, I described my goals and asked Claude Code to create a plan to migrate to Google Cloud hosting. I did not even name Firebase, but that was the recommedation Claude came up with. I told Claude I wanted to:

I used the Sonnet 5 model to break up the project into two steps: create a plan and then execute the plan.

Developing the plan

Claude reviewed the repo and the GitHub Actions workflow for deploying the site and provided a plan which is abbreviated here:

  1. Script the creation of Firebase hosting resources including GCP APIs and billing account
  2. Update the GitHub Actions workflow
  3. Cutover the domain
  4. Clean up AWS resources

Claude wrote a thorough plan document and covered elements I did not expect including some of the specific DNS changes that would be needed to cut over or the association to a Google Cloud Billing Account. However, the plan was not perfect - and it is not expected to be! Something not easily inspectable from the repo is that the website has a sub-domain for testing changes. I had to tell Claude about this sub-domain to include it in the plan.

I also had Claude commit the plan to the repo. I was working on this project in fits snd starts, and refreshing context has cost, so by writing the plan to a file in the repo, Claude could refresh itself cheaper when I was ready to execute.

I also asked Claude to add the tools I would need to the plan so that I could install those and walk through execution with Claude as a partner.

Executing

Part of the plan included Claude making a shell script to help with the migration, but other steps required manual intervention in the GCP or Firebase consoles. I installed and authenticated the tools that Claude needed including the gcloud and firebase CLIs, and I reviewed the script for what it would do. Then, I turned control over to Claude to execute the script, monitor the output, and respond with fixes to the script if necessary. I have found this helpful for debugging scripts that Claude writes because it gets the necessary context on its own to debug and fix many issues.

When manual intervention was needed (ex. accepting terms and conditions in the browser), I stepped in to do that and then let Claude know to proceed with the next step.

Ultimately, the migration worked out great. The sub-domain and primary domains were migrated successfully including new Firebase resources and GitHub Actions workflow.

What I learned

Sometimes, we need to review in more detail the plan that Claude presents including external references. I learned this when I was updating DNS. Firebase uses a TXT record to validate your ownership of a custom domain and to start provisioning a TLS certificate. There was a subtle note about this in Claude's plan doc, but I did not catch that when I updated the A record, Firebase would not yet recognize the traffic until it could validate the TXT record. As a consequence, the site went down for several minutes! For a personal site, this was a minor inconvenience, but if I was migrating an impactful production app, that would have been an unacceptable mistake.