You're reading this on a blog that was built, deployed, and launched with the help of an AI — specifically, Claude Code, Anthropic's coding assistant that lives in your terminal. No drag-and-drop website builders. No WordPress. Just a conversation in a terminal and an AWS free tier account.
This is the story of how that happened, step by step. Whether you're a developer curious about AI-assisted workflows or someone who's never touched a terminal, I hope this gives you a feel for what's possible today.
The Starting Point
Here's what I had before we began:
- A Flask blog app called Polarden sitting on my laptop — already written, never deployed
- An AWS account with the CLI (command-line interface) installed
- A domain name (
polarden.io) registered through AWS Route 53 - Claude Code running in my terminal
That's it. No server running anywhere. No database. Just code on a laptop and a dream.
I typed a simple message to Claude: "I want you to control all my AWS setup using AWS CLI."
And we were off.
Step 1: Making Sure AWS Can Hear Us
Before building anything, we needed to verify that my laptop could actually talk to AWS. Think of the AWS CLI as a remote control for Amazon's cloud — but it only works if it's paired to your account.
Claude ran a single command to check:
aws sts get-caller-identity
First attempt? Failed. My credentials had expired. After I regenerated fresh access keys in the AWS console and reconfigured, we tried again:
{
"UserId": "AIDA2CV22TLJQ5S6AEUDL",
"Account": "692955290323",
"Arn": "arn:aws:iam::692955290323:user/claude-code"
}
We had a connection. AWS knew who we were.
A Security Catch
Before moving on, Claude spotted something I'd missed — my .env.example file (a template that gets shared publicly in git repositories) contained real AWS credentials. That's like leaving your house key taped to the front door with a label that says "HOUSE KEY."
Claude flagged it immediately and recommended keeping real secrets in .env (which is hidden from git) and only placeholders in .env.example. A small thing that could have been a big problem.
Step 2: Launching a Server in the Cloud
Next, I asked Claude to create a free-tier EC2 instance. EC2 is Amazon's virtual server service — essentially, a computer in the cloud that runs 24/7 so your website is always available.
Here's what Claude set up:
| Setting | Value |
|---------|-------|
| Instance type | t2.micro — free for 12 months |
| Operating system | Amazon Linux 2023 |
| Region | us-west-1 (N. California) |
| Storage | 8 GB |
But before launching the server, Claude needed to create two things:
An SSH Key Pair — Your Server's Front Door Key
SSH is how you securely connect to a remote server. Claude generated a key pair and saved it to my machine:
aws ec2 create-key-pair --key-name polarden-key \
--query 'KeyMaterial' --output text > ~/.ssh/polarden-key.pem
chmod 400 ~/.ssh/polarden-key.pem
That .pem file is the only way to log into the server. Lose it, and you're locked out. Share it, and anyone can get in.
A Security Group — The Server's Firewall
A security group defines who can access the server and how. Claude asked me: "Do you want to restrict SSH to your current IP only?"
Yes. Absolutely.
Claude looked up my public IP, then created rules:
- Port 22 (SSH): Only my IP address —
108.53.187.224/32. Nobody else on Earth can SSH in. - Port 80 (HTTP): Open to everyone — so people can visit the blog.
- Port 443 (HTTPS): Open to everyone — for secure, encrypted connections.
Launch
With the key and firewall in place, Claude launched the instance:
aws ec2 run-instances --instance-type t2.micro \
--image-id ami-0e2de80e7636c4837 \
--key-name polarden-key \
--security-group-ids sg-0a3b3d35ea0188409 \
--tag-specifications '[{"ResourceType":"instance","Tags":[{"Key":"Name","Value":"polarden"}]}]'
Thirty seconds later:
Instance ID: i-071d58f8cc8413661
Public IP: 54.177.226.69
State: running
We had a server.
Step 3: Setting Up the Database
Every blog needs a place to store posts, comments, and user accounts. Polarden uses SQLite — a lightweight database that lives as a single file on the server. No separate database server needed. No monthly fees.
This step required some problem-solving. The app was built on my Mac (osx-arm64), but the server runs Linux (linux-64). Claude updated the project config to support both platforms, then:
- Copied the app to the server using
rsync - Installed the Python package manager (
pixi) on the server - Installed all dependencies — Flask, SQLAlchemy, Gunicorn, and friends
- Initialized the database — creating three tables:
| Table | What it stores |
|-------|---------------|
| posts | Blog posts — title, content, slug, cover image, timestamps |
| comments | Reader comments — author name, body, approval status |
| admins | Admin accounts — username and hashed password |
A quick verification:
ssh -i ~/.ssh/polarden-key.pem ec2-user@54.177.226.69 \
"sqlite3 ~/polarden/instance/polarden.db '.tables'"
admins comments posts
Database: ready.
Step 4: Pointing the Domain
Having a server at 54.177.226.69 is fine, but nobody wants to type an IP address into their browser. I already had polarden.io registered with AWS Route 53, so I asked Claude to connect it.
Claude checked my hosted zones, found polarden.io, and created two A records — DNS entries that tell the internet "when someone types this domain, send them to this IP address":
aws route53 change-resource-record-sets --hosted-zone-id Z0433781REMOI64VF527 \
--change-batch '{
"Changes": [
{"Action":"CREATE","ResourceRecordSet":{"Name":"polarden.io","Type":"A","TTL":300,"ResourceRecords":[{"Value":"54.177.226.69"}]}},
{"Action":"CREATE","ResourceRecordSet":{"Name":"www.polarden.io","Type":"A","TTL":300,"ResourceRecords":[{"Value":"54.177.226.69"}]}}
]
}'
After about 30 seconds, DNS propagated:
dig +short polarden.io
# 54.177.226.69
Both polarden.io and www.polarden.io now pointed to our server.
Step 5: Going Live
This was the big one. Four things needed to happen:
1. Nginx — The Traffic Director
Nginx (pronounced "engine-x") is a web server that sits in front of your app and directs traffic. It handles incoming requests from the internet and forwards them to your application. Claude configured it to:
- Listen on ports 80 and 443
- Forward requests to Gunicorn (the Python app server) running on port 8000
- Serve static files (CSS, images) directly for better performance
2. Gunicorn — The App Runner
Gunicorn is the engine that actually runs the Python blog application. Claude set it up as a systemd service — meaning it starts automatically when the server boots and restarts itself if it crashes:
[Service]
User=ec2-user
WorkingDirectory=/home/ec2-user/polarden
ExecStart=/home/ec2-user/.pixi/bin/pixi run serve
Restart=always
A quick health check confirmed it was alive:
HTTP 200 ✓
3. HTTPS — The Padlock
No modern website should run without HTTPS. It encrypts everything between your browser and the server. Claude installed Certbot (from Let's Encrypt) and obtained a free SSL certificate:
sudo certbot --nginx -d polarden.io -d www.polarden.io \
--email inki1104@gmail.com --agree-tos --redirect
Successfully deployed certificate for polarden.io
Successfully deployed certificate for www.polarden.io
The --redirect flag means anyone visiting http://polarden.io automatically gets redirected to https://polarden.io. The certificate auto-renews, so we never have to think about it again.
4. Admin Account — The Keys to the Blog
Finally, Claude created an admin account so I could actually log in and write posts:
pixi run python create_admin.py den <password>
The Result
From first message to live blog: one conversation. Here's what we ended up with:
- A t2.micro EC2 instance running Amazon Linux 2023 — free for 12 months
- SQLite database with posts, comments, and admin tables
- Nginx reverse proxy with static file serving
- Gunicorn application server running as a self-healing systemd service
- HTTPS via Let's Encrypt with automatic renewal and HTTP-to-HTTPS redirect
- DNS configured through Route 53 —
polarden.ioandwww.polarden.io - SSH access locked down to a single IP address
- Total monthly cost: $0 (within AWS free tier)
What I Learned
AI doesn't replace understanding — it accelerates it. I still needed to know what I wanted (a blog, on AWS, with a custom domain). But Claude handled the parts that usually send people down hours-long rabbit holes: the right AMI ID for my region, the correct Nginx config syntax for Amazon Linux vs. Ubuntu, the exact Certbot flags for non-interactive mode.
Security comes up naturally in conversation. Claude caught the credentials in my .env.example before I pushed them to a public repo. It asked before opening SSH to the world. These aren't things I would have forgotten — but they're things I might have gotten to later, which in security often means too late.
The AWS CLI is more approachable than the console. Clicking through the AWS web console feels like navigating a maze. But expressed as CLI commands in a conversation, each step is one line with a clear purpose. You can see exactly what's happening.
Want to Build Your Own?
Here's the minimal shopping list:
- An AWS account — aws.amazon.com (free tier available)
- AWS CLI —
brew install awsclion Mac - A domain — register one through Route 53 or any registrar
- Claude Code — claude.ai/claude-code
- Your app — or fork Polarden and make it your own
Then open your terminal and start talking.
This is the first post on Polarden, and yes — even this post was drafted with Claude's help. The words are mine. The deployment pipeline was a team effort.