How I Built this Website
Introduction
I had been meaning to update my personal website for a while, but I kept putting it off. Finally, I sat down in my code editor and started thinking about how to go about it. And by thinking, I mean I loaded up Claude Code and asked it to work with me to build a new website. I want to document the process and share some insights I had along the way.
There are a couple of key questions that I knew had to be answered before I could get started:
- Where will I host it?
- What framework to use?
- Will the content be rendered statically or dynamically?
- How will I deploy it now and in the future?
Design Choices
I have a huge bias towards AWS as I have used it for years and am very familiar with it. Furthermore, I am familiar with deploying infrastructure as code using the AWS CDK. This would allow Claude Code to help in generating the infrastructure as code, which would make it easy to deploy and maintain the website. Just for fun, I did ask Claude Code about other options, none of which were native AWS.
The next decision is whether to go with dynamic or static rendering. To understand this decision better, we need to know a bit about how websites work.
When you visit a website, your browser makes a request to a server, which returns HTML. The question is: when is that HTML generated? With dynamic rendering, the server generates it on the fly for each request — pulling from databases, running logic, and assembling the page in real time. That’s great for user-specific content (dashboards, feeds, shopping carts), but it’s overkill for a personal site. With static rendering, the HTML is generated once at build time and served as plain files. No database, no server logic, just files — which means it’s fast, cheap, and trivially easy to host anywhere. For a blog, static is the obvious choice.
To host a static website, you can do so by simply copying the files to a S3 bucket and configuring it to serve static content. We could stop here; however, there are some additional benefits of using CloudFront in front of the S3 bucket. This allows for content caching, which can significantly improve the performance of the website. Additionally, it provides a layer of security by preventing direct access to the S3 bucket.
AWS also has a service called Amplify, which can be used to server-side render the website. In fact, I had used it for a previous version of my website.
Given my requirements, Claude Code also suggested using the CloudFront + S3 approach.
Implementation
In the end, it’s a few lines of code to set up the S3 bucket and CloudFront distribution, and it can be easily generated by Claude Code. For instance, we have
const distribution = new cloudfront.Distribution(this, "Distribution", {
defaultBehavior: {
origin: origins.S3BucketOrigin.withOriginAccessControl(bucket),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
domainNames: ["georgeshakan.com", "www.georgeshakan.com"],
certificate,
defaultRootObject: "index.html",
errorResponses: [
{
httpStatus: 404,
responseHttpStatus: 404,
responsePagePath: "/404.html",
},
],
});
The next decision is how to build the frontend. Again I worked with Claude Code to understand some of the options. Claude suggested Astro:
My Recommendation — Given you know AWS well: Astro or Next.js + S3 + CloudFront + Route 53. Astro is particularly strong for blogs (zero JS by default, markdown/MDX support built-in, fast). Total AWS cost: ~$1-5/month for most personal sites.
There are two broad categories of choices. Static site generators — Astro, Jekyll, Gatsby, Eleventy — handle markdown rendering and routing out of the box. Frontend frameworks — React, Vue, Svelte — are more flexible but require more setup for a content site. Or you can go fully minimal with plain HTML, CSS, and vanilla JS.
I knew I wanted to write my content in markdown, as I am quite comfortable writing in that. This suggested to me that a static site generator was the right category. I ultimately went with Astro as it is a modern framework designed for this exact use case and actively maintained — which is exactly what you want for a static blog.
Once I made these choices, Claude Code helped tremendously in generating the code. I scaffolded two folders: infrastructure and website. This can be done with
cdk init --language typescript
I knew that Typescript is the most natural choice for AWS CDK as it is the language that the CDK team uses to develop the CDK, and thus it has the best support and documentation.
I grabbed the command to bootstrap Astro from their docs:
npm create astro@latest
It’s worth noting that I did have a choice to grab one of the themes that come with Astro, but I decided to start with a simple design of the frontend.
My infrastructure folder contains the AWS CDK code to set up the S3 bucket and CloudFront distribution, while website contains the Astro code for the frontend. Then I worked with Claude Code to populate the code for both folders.
Claude Code knew my problem clearly and more or less one-shotted the code for the infrastructure. I reviewed it and basically said LGTM and moved on.
For the frontend, I had to load up the website and make sure it looked right. I deleted some of the default code that came with Astro and replaced it with my own. Claude Code also helped with the code to populate the blog posts on the homepage and to render the individual blog posts.
There is one last decision in how to deploy the website. We can go all out and have a CI/CD that automatically triggers a deployment whenever I make changes to the code base. This can be done with GitHub Actions or AWS CodePipeline (I even made a YouTube tutorial on this). I have experience with both and have even designed and implemented them at scale in production. Thus, I knew for such a simple project, they would be overkill. Instead, I decided to go with a simple script that I can run locally to deploy the website. Of course, I had Claude Code generate a script for deploying the website.
Given the simplicity of what I was trying to accomplish and the experience I had doing so, it was relatively easy to check Claude Code’s work. Overall, it basically was able to one-shot the implementation details.
Conclusion
Working with Claude Code dramatically sped up the process. The infrastructure code — which would have taken me a couple of hours of CDK docs-diving — was done in minutes. The frontend took longer because it required back-and-forth: loading the site, seeing how it looked, asking for tweaks. But even there, I wasn’t writing boilerplate or debugging layout CSS from scratch.
It does raise an interesting question: did I build this website? I had the architectural vision and made the key decisions. But I leaned heavily on Claude Code to bounce ideas off of and implement the code. The line between “author” and “editor” gets blurry fast. I suspect that’s going to be a recurring theme as these tools get better.