```html

Building a Granular Technical Blog System Across Four Sailing & Charter Sites

What Was Done

We implemented an automated technical blog generation system that captures development work at four domain properties and publishes granular, detailed posts to dedicated tech subdomains. This required building infrastructure-as-code tooling, CloudFront distributions, S3 buckets, DNS integration, and a Claude Code hook system that automatically generates blog posts from session transcripts.

The system now publishes to:

  • tech.queenofsandiego.com (via *.queenofsandiego.com wildcard cert)
  • tech.sailjada.com (via *.sailjada.com wildcard cert)
  • tech.dangerouscentaur.com (via Namecheap CNAME)
  • tech.burialsatseasandiego.com (via GoDaddy DNS)

Technical Architecture

Blog Generator Pipeline

The system works through three Python tools:

  • tech_blog_generator.py — Parses Claude Code session transcripts (JSONL format) and extracts granular technical details from tool use entries, generating an HTML blog post with exact file paths, command examples, infrastructure changes, and reasoning
  • tech_blog_init.py — Idempotent infrastructure provisioning that creates S3 buckets, CloudFront distributions, ACM certificates, DNS records, and indexes blog posts
  • tech_blog_stop.sh — Claude Code hook (bash) that fires on session end, runs the generator, uploads to S3, and invalidates CloudFront

The generator parses session transcripts in JSONL format stored at /Users/cb/.claude/projects/-Users-cb-Documents-repos/sessions/. Each line is a JSON object representing a turn in the conversation. Tool use entries contain structured data about files modified, commands executed, and reasoning—exactly what we need for granular documentation.

Infrastructure Per Domain

For domains using AWS-hosted DNS (queenofsandiego.com, sailjada.com):

  • S3 Bucket: tech-queenofsandiego-com (public, website hosting mode)
  • CloudFront Distribution: Caching behavior with origin at S3 bucket, using wildcard ACM cert for *.queenofsandiego.com
  • Route53 DNS: CNAME alias record tech.queenofsandiego.com → CloudFront distribution domain name

For dangerouscentaur.com (no existing AWS setup):

  • S3 Bucket: dc-sites (reuses existing wildcard CloudFront E2Q4UU71SRNTMB)
  • Namecheap DNS: CNAME tech.dangerouscentaur.com → CloudFront distribution domain

For burialsatseasandiego.com (GoDaddy DNS):

  • S3 Bucket: tech-burialsatseasandiego-com
  • CloudFront Distribution: New distribution with ACM cert (DNS-validated via GoDaddy)
  • GoDaddy DNS: CNAME tech.burialsatseasandiego.com → CloudFront domain

Key Implementation Details

Session Transcript Parsing

Claude Code sessions are stored as JSONL transcripts. Each session file contains metadata (domain, tags, timestamp) and structured message/tool entries. The generator extracts:

  • Files modified/created with paths and write operations
  • Commands run (shell history)
  • Reasoning/agent notes explaining decisions
  • Tool use chains showing cause-and-effect workflows

This allows posts to say "We edited /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html because the Ship's Papers nav dropdown needed restructuring" rather than "We made website updates."

CloudFront Distribution Configuration

Each CloudFront distribution uses:

  • Origin: S3 bucket in website hosting mode (not REST API)
  • Cache Behavior: 1-hour TTL for HTML (to catch updates quickly), longer for static assets
  • Viewer Protocol Policy: Redirect HTTP → HTTPS
  • Allowed Methods: GET, HEAD (read-only)
  • Default Root Object: index.html

CloudFront invalidations are triggered post-upload via the --paths "/*" option to ensure new posts are visible immediately (no 1-hour wait).

DNS Validation for ACM Certificates

The burialsatseasandiego.com setup required ACM DNS validation because the domain is at GoDaddy (not Route53). The infrastructure script:

  1. Requests ACM cert for tech.burialsatseasandiego.com
  2. Extracts DNS CNAME validation record from pending cert
  3. Outputs instructions for manual GoDaddy DNS entry (we add via GoDaddy API with stored credentials)
  4. Polls until cert is validated
  5. Creates CloudFront distribution pointing to the validated cert

This ensures the blog is HTTPS-enabled without requiring DNS zone transfer.

Claude Code Integration

The stop hook is registered in /Users/cb/.claude/settings.json:

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

When a session ends, the hook:

  1. Reads the session transcript from the session file
  2. Runs tech_blog_generator.py to produce HTML
  3. Uploads to the appropriate S3 bucket (detected from session metadata/repo path)
  4. Invalidates CloudFront cache
  5. Logs output to ~/.claude/logs/tech_blog_stop.log for debugging

The hook is executable and wrapped in error handling to prevent session termination failures from blocking work.

Navigation Integration

Each site's Ship's Papers menu now includes a "Tech Blog" link pointing to the appropriate tech.* subdomain. For queenofsandiego.com, this required editing the navigation dropdown in index.html to add:

<li><a href="https://tech.queenofsandiego.com">Tech Blog</a><