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-blogfortech.queenofsandiego.comjada-tech-blogfortech.sailjada.combats-tech-blogfortech.burialsatseasandiego.com- Leveraged existing
dc-sitesbucket with wildcard CloudFront distribution (ID:E2Q4UU71SRNTMB) fortech.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
techsubdomain pointing to CloudFront distribution endpoint
SSL/TLS Certificates
Leveraged existing AWS Certificate Manager wildcard certificates:
*.queenofsandiego.comand*.sailjada.comcertificates 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.pyto 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.logfor 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, andtech.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: