```html

Building an Automated Technical Blog System for Multi-Domain Documentation

What Was Done

Created an automated technical blog generation system that captures development activities across four separate domains and publishes granular, detailed technical posts to dedicated tech subdomains. The system integrates with Claude Code's session management to extract work performed and automatically generates posts with no manual intervention required.

Architecture Overview

The solution consists of three core components:

  • Blog Generator (/Users/cb/Documents/repos/tools/tech_blog_generator.py) — Python utility that parses Claude Code session transcripts (JSONL format) to extract file modifications, commands executed, and decisions made
  • Infrastructure Initializer (/Users/cb/Documents/repos/tools/tech_blog_init.py) — Provisions AWS S3 buckets, CloudFront distributions, and DNS records for each tech blog subdomain
  • Stop Hook (/Users/cb/.claude/hooks/tech_blog_stop.sh) — Bash script executed when a Claude Code session terminates, triggering blog post generation and deployment

Infrastructure Setup

AWS S3 Buckets and CloudFront Distributions

Created dedicated S3 buckets for content delivery:

  • qos-tech-blog for tech.queenofsandiego.com
  • jada-tech-blog for tech.sailjada.com
  • bats-tech-blog for tech.burialsatseasandiego.com
  • Leveraged existing dc-sites bucket with wildcard CloudFront distribution (ID: E2Q4UU71SRNTMB) for tech.dangerouscentaur.com

Each new S3 bucket was configured with:

  • Block public access disabled to allow CloudFront distribution read
  • Static website hosting enabled with index.html as default document
  • Custom origin access policy to restrict direct S3 access

CloudFront distributions created with:

  • Origin pointing to S3 bucket static site endpoint
  • Cache behavior configured with 5-minute TTL for HTML content
  • HTTP-only (HTTPS not required for internal technical documentation)

DNS Configuration

DNS setup varied by registrar:

  • queenofsandiego.com and sailjada.com — Route53 hosted zones updated with CNAME records pointing to CloudFront distribution domain names
  • dangerouscentaur.com — Existing wildcard CNAME at Namecheap DNS already routed to CloudFront wildcard distribution; no changes needed
  • burialsatseasandiego.com — GoDaddy DNS provider; added CNAME record for tech subdomain pointing to CloudFront distribution endpoint

SSL/TLS Certificates

Leveraged existing AWS Certificate Manager wildcard certificates:

  • *.queenofsandiego.com and *.sailjada.com certificates already provisioned and validated
  • burialsatseasandiego.com required new certificate; DNS validation CNAME added to GoDaddy via API (credentials stored in environment, no hardcoding)

Blog Generator Implementation

tech_blog_generator.py reads Claude Code session transcripts in JSONL format. Each session file contains timestamped entries with:

  • Tool use blocks — Executed commands (git, AWS CLI, file operations)
  • File operations — Read/write/edit actions with paths and context
  • Reasoning entries — Agent notes explaining decisions

The generator performs these transformations:

  • Filters files modified to identify which domain(s) were affected
  • Extracts granular technical details: exact file paths, bucket names, distribution IDs, Route53 zone updates
  • Sanitizes content to remove credentials, API keys, tokens, and sensitive personal data (regex patterns match common secret formats)
  • Groups related changes into logical sections (Infrastructure / Code Changes / Configuration / Testing)
  • Generates HTML output with semantic markup using <h2>, <h3>, <ul>, <code> tags
  • Includes timestamp metadata and links to referenced resources

Session Hook Integration

Modified /Users/cb/.claude/settings.json to register the stop hook:

"hooks": {
  "stop": "/Users/cb/.claude/hooks/tech_blog_stop.sh"
}

The tech_blog_stop.sh hook:

  • Executes automatically when Claude Code session terminates
  • Reads the current session transcript from ~/.claude/sessions/
  • Invokes tech_blog_generator.py to generate HTML blog post
  • Determines target domain(s) from modified file paths
  • Uploads generated post to corresponding S3 bucket
  • Updates CloudFront cache via invalidation requests
  • Logs output to ~/.claude/logs/tech_blog_stop.log for debugging

Navigation Integration

Updated the "Ship's Papers" dropdown menu in /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html to include links to all tech blogs:

  • Added menu items for tech.queenofsandiego.com, tech.sailjada.com, tech.dangerouscentaur.com, and tech.burialsatseasandiego.com
  • Repeated navigation structure across remaining sites so consistent access across all properties
  • Links styled to match existing Ship's Papers menu design

Key Technical Decisions

Session Transcript Format: Claude Code stores sessions as line-delimited JSON (JSONL) where each line is a complete event object. This allows efficient streaming parsing without loading entire session into memory.

Sanitization Strategy: Rather than hardcoding secret patterns, the generator uses configurable regex rules stored in a separate config file, allowing easy addition of new patterns without code changes.

Multi-Domain Detection: File paths contain domain information (e.g., /repos/sites/queenofsandiego.com/), enabling automatic routing of posts to correct S3 buckets without manual configuration.

CloudFront Invalidation: Rather than waiting for cache expiration, each post generation triggers invalidation of /* on the target distribution, ensuring immediate visibility.

Infrastructure as Code: