```html

Building a Multi-Site Technical Documentation System with Auto-Generated Blog Posts

This session focused on building an automated technical blog infrastructure that captures granular development work across four separate domains: queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com. The goal is to create a transparent record of infrastructure and development activities that can be reviewed in detail by team members like Sergio.

What Was Built

A complete system consisting of three main components:

  • Tech blog generator (/Users/cb/Documents/repos/tools/tech_blog_generator.py) — Python script that parses Claude Code session transcripts and converts them into detailed HTML blog posts
  • Infrastructure initialization tool (/Users/cb/Documents/repos/tools/tech_blog_init.py) — Provisioning script that sets up S3 buckets, CloudFront distributions, and DNS records for each tech blog
  • Claude Code integration hook (/Users/cb/.claude/hooks/tech_blog_stop.sh) — Stop hook that automatically triggers blog generation and publishing when a development session ends

Additionally, updated the ship's papers navigation menu in /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html to surface the tech blog as a discoverable resource.

Infrastructure Architecture

Each tech blog follows an identical three-tier architecture:

Storage Layer (S3)

  • queenofsandiego.com: tech-qos-blog bucket
  • sailjada.com: tech-jada-blog bucket
  • dangerouscentaur.com: Uses existing dc-sites bucket (wildcard setup already in place)
  • burialsatseasandiego.com: tech-bats-blog bucket

Each bucket is configured for static website hosting with index.html as the default document. Public read access is restricted to CloudFront distributions via bucket policies.

Content Delivery (CloudFront)

  • New distributions created for qos, jada, and bats tech blogs, each with their own ACM wildcard certificate
  • dangerouscentaur.com reuses the existing wildcard distribution (E2Q4UU71SRNTMB) pointed at dc-sites
  • All distributions configured with:
    • HTTP/2 enabled for performance
    • HTTPS enforcement with TLS 1.2+
    • CloudFront caching with appropriate Cache-Control headers
    • Origin access identity (OAI) for S3 bucket security

DNS Configuration

  • queenofsandiego.com & sailjada.com: Route53 hosted zones with CNAME records pointing tech.<domain> to respective CloudFront distributions
  • dangerouscentaur.com: Namecheap DNS — CNAME record added pointing tech subdomain to CloudFront distribution
  • burialsatseasandiego.com: GoDaddy DNS — CNAME record added pointing tech subdomain to CloudFront distribution; ACM certificate validation via DNS CNAME added to GoDaddy

Technical Details: Session Capture and Blog Generation

The tech_blog_generator.py script performs the following operations:

  1. Session transcript parsing: Reads JSONL-formatted Claude Code session transcripts from ~/.claude/sessions/
  2. Tool use extraction: Filters for relevant tool calls (file reads, writes, commands executed) while explicitly excluding sensitive operations
  3. Context aggregation: Combines tool use data with user request context and agent reasoning to construct a narrative
  4. Content scrubbing: Removes all credentials, API keys, tokens, and sensitive personal data before HTML generation
  5. HTML generation: Produces semantic HTML with proper heading hierarchy, lists, and code blocks
  6. S3 publishing: Uploads generated post to appropriate tech blog bucket with proper metadata and cache headers

Example invocation (no credentials shown):

python3 /Users/cb/Documents/repos/tools/tech_blog_generator.py \
  --session-id <session_uuid> \
  --domain queenofsandiego.com \
  --publish

Claude Code Integration

The tech_blog_stop.sh hook is registered in /Users/cb/.claude/settings.json under the stop_hooks configuration. When a Claude Code session ends, the hook:

  1. Captures the session ID and transcript location
  2. Determines which site(s) were modified based on Git diff analysis
  3. Invokes the blog generator for each affected site
  4. Logs output to ~/.claude/logs/tech_blog_generation.log

This ensures every significant development session automatically produces a blog post without manual intervention.

Infrastructure Provisioning Script

The tech_blog_init.py script automates the setup process:

python3 /Users/cb/Documents/repos/tools/tech_blog_init.py \
  --domain queenofsandiego.com \
  --dns-provider route53 \
  --create-all

This single command:

  • Creates S3 bucket with proper versioning and access controls
  • Generates or imports ACM wildcard certificate
  • Creates CloudFront distribution with cache behaviors
  • Configures DNS records at the specified provider (Route53, Namecheap, or GoDaddy)
  • Validates certificate ownership where required
  • Outputs infrastructure configuration to ~/.claude/tech_blogs_config.json

Key Technical Decisions

Why CloudFront for all sites? Even though dangerouscentaur.com already had a wildcard distribution, we standardized all four sites on CloudFront. This provides:

  • Geographic distribution and edge caching for fast blog access globally
  • DDoS protection at the edge
  • Consistent HTTPS enforcement across all tech blogs
  • Cost efficiency — CloudFront pricing for infrequently-accessed tech documentation is negligible

Why S3 static hosting? Blog posts are static HTML generated once per session and rarely modified. S3 eliminates the operational overhead of managing application servers while providing 99.99% durability and compatibility with CloudFront caching.

Why separate buckets per domain (except dangerouscentaur)? This provides:

  • Clear separation of concerns and access control boundaries
  • Independent scaling and cost