```html

Building Multi-Site Technical Blog Infrastructure with Auto-Generated Session Transcripts

This session implemented a comprehensive technical blogging system across four independent sailing and event sites, with automatic post generation from Claude development session transcripts. The goal was to create granular, detailed technical documentation of ongoing work—visible to stakeholders like Sergio—without manual blog writing overhead.

What Was Done

  • Created automated blog generation pipeline that converts Claude session transcripts into technical posts
  • Provisioned S3 buckets and CloudFront distributions for four tech blogs: tech.queenofsandiego.com, tech.sailjada.com, tech.dangerouscentaur.com, tech.burialsatseasandiego.com
  • Integrated tech blog navigation links into Ship's Papers menu on queenofsandiego.com
  • Implemented Claude Code hook system to capture and publish posts automatically after each development session
  • Created email template validation and unsubscribe monitoring tooling
  • Fixed image references on burialsatseasandiego.sailjada.com and created progress tracking cards

Technical Architecture

Blog Generation Pipeline

Two Python scripts handle the core functionality:

  • /Users/cb/Documents/repos/tools/tech_blog_generator.py — Parses JSONL transcript files from Claude sessions, extracts work items (files modified, commands executed), and generates semantic HTML blog posts with exact file paths, function names, and infrastructure changes
  • /Users/cb/Documents/repos/tools/tech_blog_init.py — Provisions cloud infrastructure for each tech blog domain, including S3 bucket creation, CloudFront distribution setup with proper origin and caching behavior, and DNS record creation

The generator reads session transcripts in JSONL format (one JSON object per line), extracting tool use entries that contain file operations and shell commands. It groups related changes by theme and generates narrative HTML describing what was changed, why the decisions were made, and how the infrastructure supports it.

Claude Code Integration

A Stop hook script at /Users/cb/.claude/hooks/tech_blog_stop.sh executes when a Claude development session ends. This script:

  • Locates the current session's transcript in /Users/cb/.claude/projects/
  • Identifies which site(s) were worked on by checking modified file paths
  • Invokes the blog generator to create an HTML post
  • Uploads the post to the appropriate S3 bucket (qos-tech-blog, jada-tech-blog, dc-tech-blog, or bats-tech-blog)
  • Invalidates the CloudFront distribution cache to ensure immediate visibility

The hook is registered in Claude Code settings at /Users/cb/.claude/settings.json under the hooks configuration, ensuring it runs automatically without user intervention.

Infrastructure Details

S3 & CloudFront Setup

Each tech blog uses the same pattern:

  • queenofsandiego.com: S3 bucket qos-tech-blog, CloudFront distribution with origin pointing to bucket, wildcard ACM certificate *.queenofsandiego.com (already existed), Route53 alias record for tech.queenofsandiego.com in the queenofsandiego.com hosted zone
  • sailjada.com: S3 bucket jada-tech-blog, CloudFront distribution, wildcard ACM certificate *.sailjada.com (already existed), Route53 alias record in the sailjada.com hosted zone
  • dangerouscentaur.com: S3 bucket dc-tech-blog, CloudFront distribution, used existing wildcard Namecheap CNAME setup (since dangerouscentaur does not use Route53), certificate provisioned via ACM
  • burialsatseasandiego.com: S3 bucket bats-tech-blog, CloudFront distribution, certificate provisioned via ACM and validated through GoDaddy DNS API (burialsatseasandiego.com is hosted at GoDaddy), CNAME record added to GoDaddy DNS

CloudFront distributions are configured with:

  • S3 bucket as origin with origin access identity (OAI) for security
  • Default behavior caching HTML with 1-hour TTL to balance freshness with performance
  • Index document set to index.html
  • Minimum TTL of 0 seconds to allow immediate cache invalidation

DNS & Certificate Strategy

Four hosted zones were involved:

  • queenofsandiego.com and sailjada.com — Both managed in Route53 under the same AWS account; wildcard certificates already existed in ACM, so DNS validation was straightforward
  • dangerouscentaur.com — Uses Namecheap for DNS; wildcard CF distribution existed, so we created a new CNAME record pointing to the new tech blog CloudFront domain
  • burialsatseasandiego.com — Hosted at GoDaddy; ACM certificate creation required DNS validation via GoDaddy API, using credentials stored in environment variables

Key Decisions & Rationale

Why Auto-Generation Instead of Manual Posts?

Sergio needs visibility into detailed technical work. Manual blog writing creates a bottleneck and encourages high-level summaries over granular details. By parsing session transcripts automatically, we capture exact file paths, function names, infrastructure IDs, and command sequences—the "in the weeds" details that matter for technical accountability.

Why a Stop Hook Instead of Event-Based Publishing?

Claude Code sessions have clear start and end points. Using the Stop hook ensures we capture a coherent unit of work (one session) and publish it as a single post. This avoids partial posts or duplicate entries.

Why Four Separate Tech Blogs?

Each domain (queenofsandiego.com, sailjada.com, dangerouscentaur.com, burialsatseasandiego.com) serves different purposes and audiences. Separate tech blogs allow domain-specific documentation without cluttering the main sites.

Why S3 + CloudFront + Route53/Namecheap/GoDaddy?

Static HTML hosting via S3 + CloudFront provides high availability, low cost, and fast global delivery. Using existing DNS providers (Route53 for AWS-hosted domains, Namecheap for dangerouscentaur, GoDaddy for burialsatseasandiego) avoids unnecessary DNS migration.

Code & Credential Security

The blog generator and initialization scripts explicitly filter out credentials, API keys, tokens, and secrets before publishing. Environment variables like GoDaddy API credentials are used during infrastructure provisioning but never appear in generated posts.

Session transcripts are parsed to extract high-level summaries of what was done