Implementing a custom URL shortener using Claude Code in less than a day

Yesterday, I re-implemented my custom URL shortener glez.me
from scratch. I have a Claude Pro plan with Claude.ai, and just a week or so ago, they announced that it includes access to Claude Code as well, which is Anthropic’s agentic AI coding tool, so I decided to let Claude Code do it for me. I was done in less than a day (including walking the dog multiple times, fixing lunch and some other household chores).
Here are a few observations:
The project
Maybe “URL shortener” is a bit of an exaggeration, because the architecture is super simple: each short URL is an Amazon S3 redirect object, and the URL shortener itself is a CLI tool that generates these URLs. At the very beginning of my conversation with Claude, I emphasized that simplicity is the most important principle here. That’s why I chose this S3/CloudFront/CLI architecture. Initially, it was only S3/CLI, but then we realized that CloudFront is necessary for adding HTTPS support to the architecture.
The full project scope turned out to be a bit more elaborate:
- An AWS CDK (Python) stack for managing the S3 bucket, a CloudFront distribution on top of that, and an AWS ACM certificate for supporting HTTPS.
- The CLI tool (a Python tool with Click) that lists and generates new short URLs as needed.
- A migration of my previous (similar, but old and stale) short URLs that used to live in a similar S3 bucket scheme.
- All of the necessary project scaffolding, including documentation, Python project/virtual env/package management using uv, etc.
The architecture scales completely automatically, thanks to how S3 and CloudFront are built. Certainly much more scalable than I would ever need for my humble little URL shortener. Also, the cost side is negligible: Storage cost on S3 is minimal, even if I had hundreds of thousands of URLs stored there. Data transfer to CloudFront is free, and since CloudFront is a caching service, transaction costs for GET requests are minimal as well. The only cost that matters are the CloudFront costs, which offers the first TB of data transfer out for free, and less than 10 cents for the next 9 TB. Similarly, the first 10 million HTTP(S) requests are free, and then it’s less than a cent per 10K HTTP(S) requests. So, negligible for a personal blog.
The most important thing: planning
The biggest amount of time I spent was actually chatting back and forth with Claude Code in order to get the details planned out properly. And that’s my biggest advice when coding with AI: start with a good plan
I started basically dumping my ideas for how to set this up (S3, CloudFront, migration requirements, CDK, Python, uv, etc.) into its chat interface, and explicitly told it to not implement anything but instead to ask me questions and help me identify blind spots instead. Which proved to be critical. Things we came up with included:
- CloudFront or not?: Initially, it felt to me like adding CloudFront would be overkill, but then Claude reminded me that it’s required to also support HTTPS. So CloudFront became part of the scope.
- URL shortening algorithm: In the beginning, I wanted something simple, like start with very short alphanumeric strings for short URLs. Over time, we agreed that we want to avoid ambiguous characters (the letter “O” vs. the number “0”, but also “Z” vs. “7” or “b” vs. “6”, which may look too similar in some fonts). I also realized that generating random or sequential alphanumeric combinations might accidentally create awkward or offensive words, so we came up with a scheme where short URLs are made up of triplets, each of which starts with a digit, then two letters. We can then concatenate triplets and cut them to a desired length. This scheme almost guarantees that no words are formed at all.
- Migration approach: Claude initially proposed an extra migration command for the CLI. However, I felt that it would be overkill to add a whole subcommand for something that is likely going to be done only once. Instead, thinking more about it, I realized that by breaking down the migration process into separate bulk export/import steps makes it more useful. Now we have bulk export, which enables backups, and bulk import, for cases where I may want to add many URLs at once.
- CLI user experience: Thinking more about the day to day use of the URL shortener and talking to Claude about it also helped me streamline the CLI experience.
- Default pages: I also realized that it would be good to have some default and user-friendly
index.html
and404.html
pages, in case people try out the domain only or mistype any short URLs. Claude helped me create quite nice versions of those, too.
After this detailed conversation, I asked Claude to create a NOTES.md
and a TODO.md
file to document our decisions and to serve as context for future implementations.
Christian Bonzelet, who is a real software engineer, agrees. He wrote:
I start every feature with a conversation. But this isn’t just any conversation—it’s a structured engineering discussion using proven prompt frameworks to write a technical specification.
And that is the most important thing: developing code with AI is not about the code writing itself, it is about careful planning. I actually spent more than an hour chatting with Claude Code before we had an initial plan, and then we added a couple of iterations to narrow down some details, before a single line of code was written. This aligns with a key lesson I learned at Amazon: good writing is clear thinking.
The actual implementation
The actual implementation was almost boring: Claude wrote a working CDK stack for the infrastructure and proceeded with testing and deploying it. It’s funny to see how it runs into the same little mishaps that we humans tend to encounter, like forgetting to execute the CDK CLI with uv run
to get the right environment, or realizing that S3 buckets need to be deleted by hand after the CDK stack is rolled back, etc. The classic mistake? I forgot to tell Claude that I prefer the eu-central-1
(Frankfurt) region, so we had to tear down everything down from the default us-east-1
region and deploy it all over in Frankfurt again.
Bug fixing
Despite careful planning, there were inevitable bugs, but Claude is great at testing, diagnosing and fixing. It’s quite nice to watch it thinking and trying out things, while it’s meticulously fixing stuff. After we were about 90% done, my Pro usage limits kicked in (I also had a different conversation running on the Claude.ai app, which was eating into those limits as well), so I used a few on-demand tokens with Claude inside Zed’s agent to finish everything.
Which revealed a more obscure bug: The original architecture used Amazon S3 as an S3 native origin for CloudFront. It turns out that in this configuration, CloudFront does not support HTTP redirects. Claude correctly identified this as an issue (after I told it that a few example redirects didn’t work), and it changed the CDK stack to configure S3 in website mode instead. Then everything worked as expected.
Conclusion
It’s not perfect yet, but does it have to be? It works, my old URLs are successfully migrated, I have a useful CLI, and some ideas in NOTES.md
and TODO.md
for some future additions, like analytics, etc. The super simple and static S3/CloudFront architecture is secure, so no worries there as well, so, success!
If you’re planning to build something with AI assistance, here’s my biggest takeaway: invest heavily in the planning phase. Don’t rush to code. Spend time articulating your requirements, exploring edge cases, and thinking through the architecture. The planning conversation is where the real value lies—that’s where you and the AI can collaborate most effectively to create something that truly meets your needs. The coding part? That’s just execution.
P. S.: If you’d like to try it out: This post has this short URL: https://glez.me/3aa3