Building a Multi-Site Technical Blog Generator with Auto-Publishing via Claude Code Hooks
What Was Done
Created an automated technical blog generation system that captures development session transcripts and publishes granular technical posts to four independent tech blogs:
tech.queenofsandiego.comtech.sailjada.comtech.dangerouscentaur.comtech.burialsatseasandiego.com
The system automatically captures everything worked on during development sessions and publishes detailed technical posts immediately upon session completion, with integration into the Ship's Papers navigation menu on the main sites.
Technical Architecture
Three-Layer System
Layer 1: Session Capture via Stop Hook
Created /Users/cb/.claude/hooks/tech_blog_stop.sh that executes when any Claude Code session ends. This hook:
- Extracts the session JSONL transcript from Claude's session storage
- Identifies which site project the session belongs to (qos, jada, dc, bats)
- Passes the transcript to the blog generator
- Handles errors gracefully with detailed logging to
/tmp/tech_blog_logs/
Layer 2: Blog Generation via Python
Wrote /Users/cb/Documents/repos/tools/tech_blog_generator.py which:
- Parses Claude session transcripts in JSONL format
- Extracts tool use events (file writes, edits, commands run)
- Filters out sensitive data (credentials, API keys, secrets)
- Generates detailed HTML posts with exact file paths, function names, and infrastructure details
- Creates posts in 600-1200 word range with proper structure (What Was Done / Technical Details / Infrastructure / Key Decisions)
- Timestamps each post and maintains metadata
Layer 3: Infrastructure Deployment
Created /Users/cb/Documents/repos/tools/tech_blog_init.py to provision cloud infrastructure for each blog:
- S3 Buckets: Named
tech-{site}-blog(e.g.,tech-qos-blog) for static HTML content - CloudFront Distributions: Configured with appropriate SSL certs and origin access control
- DNS Integration: Route53 for qos and jada; Namecheap for dangerouscentaur; GoDaddy for burialsatseasandiego
- CNAME Records: Points tech.[domain].com to CloudFront distribution
Certificate Strategy
Leveraged existing AWS Certificate Manager wildcard certificates:
*.queenofsandiego.comwildcard cert fortech.queenofsandiego.com*.sailjada.comwildcard cert fortech.sailjada.com- Requested new cert for
tech.dangerouscentaur.comvia ACM (validated via Namecheap CNAME) - Requested new cert for
tech.burialsatseasandiego.comvia ACM (validated via GoDaddy DNS)
Infrastructure Details
CloudFront Configurations
Each distribution was configured with:
- S3 origin with Origin Access Control (OAC) for security
- Gzip compression enabled for HTML/CSS/JS
- Cache behavior: 3600 second TTL for index.html, 31536000 for versioned assets
- Security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy)
- HTTP/2 and HTTP/3 (QUIC) support enabled
DNS Integration
Route53 Managed Zones (queenofsandiego.com, sailjada.com):
CNAME record: tech → d[distribution-id].cloudfront.net
Namecheap (dangerouscentaur.com):
Created CNAME alias in Namecheap dashboard pointing to CloudFront distribution. Validated ACM certificate by adding GoDaddy-provided CNAME validation record.
GoDaddy (burialsatseasandiego.com):
Added ACM DNS validation CNAME record directly via GoDaddy API integration, then created tech subdomain CNAME pointing to CloudFront.
S3 Bucket Configuration
Each tech blog bucket includes:
- Index document:
index.html(auto-generated blog index) - Error document:
404.html - Public read ACL disabled (all access via CloudFront)
- Versioning enabled for rollback capability
- Server-side encryption (SSE-S3) enabled
Integration with Ship's Papers
Updated the Ship's Papers navigation menu in /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html to include a "Tech Blog" dropdown link pointing to /tech/. The navigation structure uses semantic HTML with proper ARIA attributes for accessibility.
Session Capture Mechanism
Claude Code sessions automatically write transcripts to ~/.claude/sessions/ in JSONL format. The Stop hook:
- Reads
$CLAUDE_SESSION_FILEenvironment variable (set by Claude Code) - Parses the JSONL file, filtering for
tool_useentries - Extracts file modifications, commands run, and reasoning
- Invokes
tech_blog_generator.pywith the transcript data - Generator produces HTML post and uploads to appropriate S3 bucket
- Invalidates CloudFront cache to serve latest content
Sensitive Data Filtering
The generator specifically redacts:
- AWS access keys, secret keys, session tokens
- API keys and OAuth tokens
- Database passwords and connection strings
- Email addresses and personal identifiers (unless part of public-facing content)
- File paths containing
.aws/,.claude/credentials directories - Environment variables containing
SECRET,KEY,TOKEN,PASSWORD
The redaction preserves technical value