Marc Denning

Migrating My Website with Claude

I have been using Claude for various work tasks and some personal tasks for just about 9 months now. Call me an AI skeptic - that would be fair!

Now that I have more first-hand experience with Claude and Claude Code specifically, I tried turning Claude toward a personal project: migrating from AWS Amplify to Google's Firebase. The goal of the project was to consolidate cloud platforms I am using myself in order to lower the mental load and to consolidate cloud bills. In this post, I will 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 generative AI tools like Claude Code effectively is to provide enough context and the right context for 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 recommendation Claude came up with. I told Claude I wanted to:

I used the Sonnet 5 model and broke 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 was not expected to be! One gap in the plan stemmed from something that was not easily inspectable from the repo: the website has a sub-domain for testing changes before promoting it to production. 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 and starts, and I have learned that re-reading context history and repository files to get caught up burns tokens. By writing the plan to a file in the repo, I could point Claude directly at the plan to refresh itself when I was ready to execute at a lower cost.

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

Executing the plan

Part of the plan included Claude making a shell script to help with the migration which worked great. The script included steps to:

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 using the ! prefix in the Claude Code session. Claude then monitored the output and could respond with fixes to the script if necessary. I have found this technique helpful for debugging scripts that Claude writes because it gets immediate and direct feedback to debug and fix issues.

When manual intervention was needed (e.g. accepting terms and conditions in the browser or adding a secret to GitHub Actions for deployment), I stepped in to do that and then let Claude know to proceed with the next step.

Ultimately, the migration worked out great, and the migration script needed minimal adjustments. Those changes were primarily around logging output so Claude and I knew the outcome or errors. The sub-domain and primary domains were migrated successfully including new Firebase resources and GitHub Actions workflow. The migration script helped clean up the AWS resources, and I was able to close the AWS account after a few days of monitoring.

What I learned

I already knew that one of the most important facets of successful software engineering with generative AI is keeping a human in the loop. In this project, I was reviewing the plan, scripts, and artifacts, but I did not do enough cross-checking with how Firebase works.

The mistake arrived as I was updating the DNS records. What I did not know at the time is that Firebase uses a TXT record to validate 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. Since the TXT record was new, it took Firebase a little while to be able to read this DNS entry. As a consequence, the site went down for several minutes! For a personal site, this was a minor inconvenience, but if I were migrating an impactful production app, that would have been an unacceptable mistake.

To avoid the outage, what I should have done was:

  1. Add the TXT record and wait for Firebase to verify it.
  2. Then, update the A record for the primary domain.

In this experiment, I demonstrated to myself that Anthropic's models are capable of small architecture tasks like migrating the hosting platform of a website. I was also reminded that these tools, like humans, make mistakes and gloss over important details. I still need to think critically about the proposed plans and changes the agents make despite how complete and confident they sound. Next time, I will look at plans and steps for difficult-to-revert changes. I will also check the sequencing of infrastructure changes to ensure a smoother outcome.

Note: this post was authored by me with editorial review by Claude.