Building an Automated Technical Blog System Across Four Sailing Event Sites
Overview
This session implemented a comprehensive automated technical blog generation system across four separate domains: tech.queenofsandiego.com, tech.dangerouscentaur.com, tech.sailjada.com, and tech.burialsatseasandiego.com. The system captures granular development work in real-time, generates posts from Claude Code session transcripts, and publishes them to CloudFront-distributed S3 buckets without exposing credentials.
Problem Statement
The organization needed visibility into technical work being performed across multiple sailing event websites. Previous approaches either lacked granularity or required manual documentation. The solution needed to:
- Automatically capture work from each Claude Code development session
- Generate posts that "get into the weeds" with specific file paths, function names, and infrastructure details
- Publish to separate tech blogs for each domain
- Integrate into existing site navigation (Ship's Papers menu)
- Prevent credential leakage in all outputs
- Work across heterogeneous DNS providers (Route53, GoDaddy, Namecheap)
Infrastructure Architecture
S3 Buckets
Created three new S3 buckets to host the tech blogs:
tech-queenofsandiego-com— for queenofsandiego.com technical poststech-sailjada-com— for sailjada.com technical postsdc-sites(existing wildcard) — for dangerouscentaur.com technical posts via subdomaintech-burialsatseasandiego-com— for burialsatseasandiego.com technical posts
Each bucket is configured with public read access for index.html and posts, static website hosting enabled, and proper CORS headers to support cross-origin requests from the main sites.
CloudFront Distributions
Created CloudFront distributions for tech.queenofsandiego.com, tech.sailjada.com, and tech.burialsatseasandiego.com, each pointing to their respective S3 origins. These distributions:
- Use wildcard ACM certificates already provisioned for *.queenofsandiego.com, *.sailjada.com, and the existing *.dangerouscentaur.com cert
- Cache HTML at 60 seconds, posts at 3600 seconds to balance freshness with performance
- Include cache invalidation support for immediate publish cycles
- Enforce HTTPS with HTTP→HTTPS redirect
DNS Configuration
DNS setup varied by domain registrar:
- queenofsandiego.com & sailjada.com (Route53): Added ALIAS records pointing to CloudFront distribution domains
- dangerouscentaur.com (Namecheap): Added CNAME record for tech subdomain pointing to existing wildcard CloudFront distribution E2Q4UU71SRNTMB
- burialsatseasandiego.com (GoDaddy): Used GoDaddy API credentials to add CNAME records for ACM certificate validation, then added tech subdomain CNAME to CloudFront distribution
Software Components
tech_blog_generator.py
The core generator script reads Claude Code session transcripts in JSONL format, extracts all tool uses (file operations, commands executed), and generates an HTML blog post. Key features:
- Parses session transcript from
~/.claude/sessions/directory - Filters out sensitive patterns using regex (AWS keys, API tokens, passwords)
- Groups work by type: file modifications, infrastructure changes, domain operations
- Generates semantic HTML with proper heading hierarchy
- Includes timestamps and session identifiers
- Creates index.html with archive of all posts
tech_blog_init.py
Initialization script that sets up infrastructure for a new tech blog:
- Creates S3 bucket with versioning and public access policy
- Configures static website hosting (index.html as default)
- Provisions CloudFront distribution (except for dangerouscentaur reuse)
- Handles DNS records via Route53 API or external DNS provider APIs
- Manages ACM certificate validation records
- Stores infrastructure config in JSON for later reference
tech_blog_stop.sh
Bash hook script that executes when Claude Code sessions end. Located at ~/.claude/hooks/tech_blog_stop.sh, this script:
- Waits for the session transcript file to be written
- Invokes tech_blog_generator.py on the completed transcript
- Uploads the generated HTML to the appropriate tech blog S3 bucket
- Invalidates CloudFront distribution cache for index.html
- Logs all operations to
~/.claude/logs/tech_blog_publish.log - Handles errors gracefully, noting issues without blocking session completion
Configuration and Integration
Claude Code Settings
Updated ~/.claude/settings.json to register the stop hook:
"hooks": {
"on_session_stop": "/Users/cb/.claude/hooks/tech_blog_stop.sh"
}
Site Navigation
Updated the Ship's Papers menu in /queenofsandiego.com/index.html to include a "Technical Blog" link pointing to tech.queenofsandiego.com. Similar updates applied to other site index.html files. This makes the technical work visible to stakeholders like Sergio through the existing navigation structure.
Environment Variables
The system reads from ~/.repos.env for:
- AWS_PROFILE — for S3 and CloudFront operations
- GODADDY_API_KEY and GODADDY_API_SECRET — for burialsatseasandiego.com DNS management
- Domain-specific configuration for routing blog posts to correct S3 buckets
Key Technical Decisions
Session Transcript as Source of Truth
Rather than requiring manual logging, the system uses Claude Code's native session transcript (stored in JSONL format at ~/.claude/sessions/) as the authoritative record. This captures exactly what happened without human intervention or interpretation.
Granular File-Level Documentation
The generator extracts specific file paths from transcript tool uses, not just high-level summaries. Example: instead of "updated email templates," it captures "Edit: /Users/cb/Documents/repos/sites/queenofsandiego.com/notes/email_birthday_sail_2026.html" with context about the change.
Heterogeneous DNS Provider Support
Rather than consolidating all domains to a single DNS provider, the system accommodates existing arrangements: Route53 for AWS-managed domains