Building a Multi-Site Technical Blog Infrastructure with Auto-Generated Session Transcripts
What Was Done
Created an automated technical blog generation system that captures granular development work across four domains (queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com). The system automatically generates detailed technical posts from Claude Code session transcripts, publishes them to dedicated tech subdomain CloudFront distributions, and integrates the blog link into the Ship's Papers navigation menu on each site.
Architecture Overview
The system consists of three main components:
- Session Capture: Claude Code Stop hook that triggers post-session
- Blog Generation: Python script that parses session transcripts and generates HTML posts
- Infrastructure: S3 buckets, CloudFront distributions, ACM certificates, and DNS records for each tech blog domain
Infrastructure Setup
Built separate S3 and CloudFront resources for each tech blog:
- tech.queenofsandiego.com: S3 bucket `qos-tech-blog`, CloudFront distribution with existing wildcard cert `*.queenofsandiego.com` (ACM)
- tech.sailjada.com: S3 bucket `jada-tech-blog`, CloudFront distribution with existing wildcard cert `*.sailjada.com` (ACM)
- tech.dangerouscentaur.com: S3 bucket `dc-tech-blog`, CloudFront CNAME pointing to existing wildcard distribution E2Q4UU71SRNTMB (which serves `dc-sites` S3), DNS configured via Namecheap
- tech.burialsatseasandiego.com: S3 bucket `bats-tech-blog`, CloudFront distribution with new ACM wildcard cert `*.burialsatseasandiego.com`, DNS configured via GoDaddy API
Each distribution has index.html caching disabled (TTL: 0) to ensure fresh blog post visibility, while static assets use standard CloudFront caching (3600s default).
File Structure and Implementation
Stop Hook Script: `/Users/cb/.claude/hooks/tech_blog_stop.sh`
Executes after each Claude Code session ends. The script:
- Detects the current session transcript location
- Calls the blog generator with the transcript path and site identifier
- Uploads generated HTML to the appropriate S3 bucket
- Invalidates the CloudFront distribution cache
- Logs operations to `/tmp/tech_blog_generation.log`
Blog Generator: `/Users/cb/Documents/repos/tools/tech_blog_generator.py`
Parses JSONL session transcripts and generates technical HTML posts. The generator:
- Extracts tool use entries (file modifications, AWS API calls, commands executed)
- Reconstructs the development narrative from the session flow
- Sanitizes output to exclude credentials, API keys, passwords, and sensitive data
- Formats technical details with proper markup: file paths in
, command examples in
, architecture decisions explained - Creates timestamped filenames: `YYYY-MM-DD-HHmmss-session-post.html`
- Generates an index.html that lists all posts with reverse chronological ordering
Infrastructure Init Script: `/Users/cb/Documents/repos/tools/tech_blog_init.py`
Idempotent provisioning script that:
- Creates S3 buckets with versioning enabled
- Configures bucket policies to allow CloudFront distribution access
- Creates CloudFront distributions with appropriate origins and cache behaviors
- Handles DNS differently based on domain provider:
- Route53 for sailjada.com and queenofsandiego.com (existing hosted zones)
- GoDaddy API for burialsatseasandiego.com
- Namecheap CNAME for dangerouscentaur.com (leveraging existing wildcard distribution)
- Validates ACM certificates and handles DNS validation via appropriate provider
- Saves configuration to `/Users/cb/.claude/projects/memory/tech_blog_config.json` for idempotent reruns
Integration with Ship's Papers Menu
Updated the Ship's Papers navigation dropdown in each site's main index.html to include a "Technical Blog" link:
- queenofsandiego.com: Links to `https://tech.queenofsandiego.com/`
- sailjada.com: Links to `https://tech.sailjada.com/`
- dangerouscentaur.com: Links to `https://tech.dangerouscentaur.com/`
- burialsatseasandiego.com: Links to `https://tech.burialsatseasandiego.com/`
Each link opens in a new tab, allowing site visitors (particularly Sergio) to review detailed technical work without interrupting their main site experience.
Key Technical Decisions
Why Auto-Generate from Transcripts? Manual documentation creates friction and lag. By parsing Claude Code session transcripts automatically, posts are generated within seconds of work completion, ensuring accuracy and recency. The granular level of detail (exact file paths, function names, commands) requires no additional effort from the developer.
Why Separate S3 Buckets? Each domain gets its own bucket for clear billing attribution, independent backup policies, and future-proofing for domain separation or transfer. The buckets are non-public; all access routes through CloudFront.
Why Different DNS Strategies? Leveraged existing infrastructure where possible (Route53 for sailjada.com and queenofsandiego.com, Namecheap CNAME for dangerouscentaur via existing wildcard CF dist). Only created new ACM certificate and Route53 integration for burialsatseasandiego.com, which required GoDaddy DNS API integration.
Why Disable Index.html Caching? New posts should be immediately visible to readers. Caching index.html would require manual invalidations. Static assets (CSS, JS, images) still benefit from standard caching, minimizing bandwidth while keeping content fresh.
Why Parse Transcripts Instead of Git Commits? Git commits miss the "why" and capture completed states, not process. Session transcripts include commands executed, environment variables checked, decisions made, and failures debugged—much richer context for explaining technical work to stakeholders.
Deployment and Testing
Ran infrastructure init script to provision all resources. Tested each domain:
- HTTP access to all four tech blog domains
- CloudFront distributions responding with index.html
- DNS propagation via appropriate providers (Route53, GoDaddy, Namecheap)
- Blog generator on sample session transcript, validating output HTML structure and sensitive data scrubbing
Uploaded updated HTML files