Case studies

How I Used Claude to Build claudefan.dev

A deep dive into building a modern tech blog using Claude AI as my pair programming partner. From architecture decisions to deployment — here's how AI-assisted development actually works.

Mohan Kumar

Mohan Kumar

Author

Building claudefan.dev with Claude

Building a website from scratch is no small feat. Building one while documenting every decision, implementing modern best practices, and shipping in a single day? That’s where AI-assisted development changes the game.

This post is a technical deep-dive into how I built claudefan.dev using Claude Opus as my pair programming partner. If you’re a developer curious about what AI-assisted development actually looks like in practice, this is for you.

The Tech Stack

Before diving into the implementation, here’s what powers this site:

TechnologyPurpose
Astro 5Static site framework
Tailwind CSS 4Utility-first styling
MDXMarkdown with components
TypeScriptType safety
VercelDeployment & hosting
Google AnalyticsTraffic analytics
n8n WebhooksEmail subscription handling

Architecture Overview

The site follows a clean, component-based architecture:

src/
├── components/
│   ├── blog/          # Article cards, TOC, navigation
│   ├── layout/        # Header, Footer, Sidebar
│   └── ui/            # Buttons, forms, theme toggle
├── content/
│   └── blog/          # MDX blog posts
├── layouts/
│   ├── BaseLayout.astro
│   └── BlogLayout.astro
├── pages/
│   ├── index.astro
│   ├── about.astro
│   └── blog/[...slug].astro
├── lib/
│   ├── config.ts      # Site configuration
│   └── utils.ts       # Helper functions
└── styles/
    └── global.css     # Tailwind + custom styles

The Claude-Assisted Development Flow

Here’s what my workflow looked like:

  1. Describe the goal — I tell Claude what I want to build
  2. Claude implements — It writes the code, often across multiple files
  3. I review and test — Check the browser, verify the behavior
  4. Iterate — Request adjustments or fixes as needed

This tight feedback loop is incredibly productive. Let me walk through some concrete examples.

Building the Blog Layout

One of the more complex features was the three-column blog layout, inspired by OpenAI’s blog design:

┌──────────────────────────────────────────────────────────┐
│  Header (Fixed)                                          │
├──────────────────────────────────────────────────────────┤
│           │                              │               │
│  (empty)  │    Article Content           │   Table of    │
│           │    - Title                   │   Contents    │
│           │    - Body                    │   (Fixed)     │
│           │    - Tags                    │               │
│           │                              │               │
└──────────────────────────────────────────────────────────┘

Here’s the key CSS structure I landed on:

<div class="relative pt-24 pb-12">
  <!-- Table of Contents (Fixed Right Side) -->
  {headings.length > 0 && (
    <aside class="hidden xl:block fixed right-8 top-24 w-56">
      <TableOfContents headings={headings} />
    </aside>
  )}

  <!-- Main Article Content -->
  <article class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
    <!-- Content here -->
  </article>
</div>

The key insight: using fixed positioning for the TOC keeps it visible during scroll, while max-w-3xl mx-auto centers the content naturally. No complex grid calculations needed.

Dark Mode with Tailwind CSS 4

Tailwind CSS 4 introduces a new approach to theming. I used CSS custom properties combined with the new @theme directive:

@theme {
  /* Brand Colors */
  --color-bg: #F4F1ED;
  --color-bg-dark: #1a1a1a;
  --color-text-main: #1D1D1D;
  --color-text-main-dark: #F4F1ED;
  --color-accent: #D97757;
  
  /* Fonts */
  --font-heading: 'Playfair Display', serif;
  --font-sans: 'Inter', sans-serif;
}

/* Dark mode variable overrides */
html.dark {
  --color-bg: var(--color-bg-dark);
  --color-text-main: var(--color-text-main-dark);
}

The theme toggle persists to localStorage and respects system preferences on first load.

Subscribe Form with Webhook Integration

Instead of a complex backend, I used n8n webhooks for email collection. Here’s the subscribe form implementation:

const WEBHOOK_URL = 'https://n8n.neupilot.com/webhook/...';

async function handleSubscribe(form, emailInput, button) {
  const email = emailInput.value.trim();
  
  // Validation
  if (!isValidEmail(email)) {
    showMessage(form, 'Please enter a valid email.', true);
    return;
  }
  
  // Show loading state
  button.disabled = true;
  button.innerHTML = 'Subscribing...';
  
  try {
    const response = await fetch(WEBHOOK_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, source: 'claudefan.dev' })
    });
    
    if (response.ok) {
      showMessage(form, 'Thanks for subscribing!', false);
      emailInput.value = '';
    }
  } catch (error) {
    showMessage(form, 'Something went wrong.', true);
  }
}

This keeps the frontend simple while offloading email handling to a no-code automation platform.

Branding: The Little Details

The site branding uses a simple but effective approach:

<a href="/" class="text-lg font-bold tracking-tight">
  claudefan<span class="text-accent">.dev</span>
</a>

The .dev suffix in terracotta (#D97757) creates visual interest without needing a logo. The favicon is a simple SVG lightbulb:

<svg viewBox="0 0 24 24" fill="none" stroke="#D97757" stroke-width="2">
  <path d="M9 18h6"/>
  <path d="M10 22h4"/>
  <path d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 
           6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14"/>
</svg>

Google Analytics Integration

Analytics setup was straightforward — adding the gtag snippet to the base layout:

<head>
  <!-- Google tag (gtag.js) -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', 'G-XXXXXXXX');
  </script>
  
  <!-- Rest of head content -->
</head>

Since all pages use BaseLayout.astro, analytics automatically track every page.

Content Architecture

Blog posts use Astro’s content collections with a well-defined schema:

// src/content/config.ts
const blogCollection = defineCollection({
  type: "content",
  schema: z.object({
    title: z.string(),
    description: z.string(),
    publishedAt: z.date(),
    author: z.string(),
    category: z.enum(["tutorials", "guides", "announcements", ...]),
    tags: z.array(z.string()),
    coverImage: z.object({
      src: z.string(),
      alt: z.string()
    }).optional(),
    featured: z.boolean().default(false),
    draft: z.boolean().default(false),
  }),
});

This gives us type-safe frontmatter validation and IDE autocomplete.

What Claude Did Well

Looking back at this project, here’s where Claude excelled:

  1. Multi-file refactoring — When I asked to update the logo across all files, Claude found and updated Header, Footer, and the homepage in one go.

  2. CSS layout problem-solving — The blog layout went through several iterations. Claude understood spatial relationships and could fix alignment issues from a screenshot description.

  3. Boilerplate generation — Component structure, form handling, webhook integration — Claude handled the repetitive parts quickly.

  4. Context retention — Throughout the session, Claude remembered our design system (terracotta accent, Playfair headings, etc.) and applied it consistently.

What Required Human Judgment

Some things still needed my input:

  • Design taste — Choosing the color palette, typography, overall aesthetic
  • Architecture decisions — What to build vs. what to outsource (n8n for email handling)
  • Content strategy — What to write about, how to structure the blog
  • Quality review — Checking the browser, catching visual bugs

AI accelerates execution, but strategy and taste remain human domains.

Deployment & Performance

The site deploys to Vercel via GitHub integration. Every push triggers a build:

npm run build  # Astro builds static HTML
# Output: dist/ folder with optimized assets

Astro’s partial hydration means minimal JavaScript. The site loads fast and works without JS enabled.

Lessons Learned

  1. Start with a clear vision — AI works best when you know what you want. Vague requests produce vague results.

  2. Iterate in small steps — Instead of asking for a complete page, build and verify component by component.

  3. Provide context — Screenshots, reference sites, and specific examples help Claude understand your intent.

  4. Review everything — AI can introduce subtle bugs or make assumptions. Always verify in the browser.

  5. Trust but verify — Claude’s code is usually correct, but edge cases and styling details often need adjustment.

The Numbers

Here’s what I shipped in a single day:

  • 6 pages (Home, Blog, Categories, About, individual posts)
  • 15+ components (Header, Footer, ArticleCard, TOC, SubscribeForm, etc.)
  • Dark mode with persistent theme toggle
  • Newsletter signup with webhook integration
  • Google Analytics for traffic monitoring
  • Full responsive design (mobile, tablet, desktop)

Conclusion

Building claudefan.dev with Claude wasn’t about replacing my skills — it was about amplifying them. I made the design decisions, defined the architecture, and maintained quality standards. Claude handled the implementation details, boilerplate, and tedious refactoring.

The result? A complete, polished website shipped in a fraction of the time it would have taken solo.

If you’re a developer on the fence about AI-assisted development, my advice is simple: try it on a real project. Not a toy demo, but something you actually want to build and ship. That’s when you’ll truly understand the potential.

The future of development isn’t AI replacing developers. It’s developers who use AI outpacing those who don’t.


Have questions about this stack or how I used Claude? Reach out on X @smhnkmrtweet or check out the About page.

#claude #astro #ai-development #web-development #case-study