Building a Multi-Site Auto-Generated Technical Blog System with Session Capture
What Was Done
Implemented a comprehensive technical blog generation system across four distinct properties (queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com) that automatically captures development work and publishes granular technical posts. The system hooks into Claude Code's session management to extract detailed engineering decisions, infrastructure changes, and code modifications—creating transparency for stakeholders reviewing ongoing work.
Architecture Overview
The system consists of three primary components:
- Tech Blog Infrastructure: S3 buckets + CloudFront distributions + Route53/DNS configuration for each subdomain
- Session Capture Hook: Stop hook that triggers after development sessions end, extracting transcript data
- Blog Generator: Python tool that parses session transcripts and generates formatted HTML posts
- Navigation Integration: Ship's Papers menu system linking to tech blogs
Infrastructure Setup
Domain-Specific CloudFront + S3 Configuration
For each property, we provisioned separate infrastructure:
- queenofsandiego.com: Created
qos-tech-blogS3 bucket with CloudFront distribution, using existing*.queenofsandiego.comwildcard ACM certificate (already available in us-east-1) - sailjada.com: Created
jada-tech-blogS3 bucket with CloudFront distribution, leveraging existing*.sailjada.comwildcard certificate - dangerouscentaur.com: Configured CNAME record at Namecheap pointing
tech.dangerouscentaur.comto the existing wildcard CloudFront distribution (E2Q4UU71SRNTMB) backed bydc-sitesS3 bucket—reusing infrastructure since dangerouscentaur.com uses GoDaddy DNS - burialsatseasandiego.com: Created
bats-tech-blogS3 bucket with CloudFront distribution and provisioned new ACM certificate fortech.burialsatseasandiego.com, then added DNS validation CNAME to GoDaddy nameservers
All CloudFront distributions configured with:
- Origin path pointing to S3 bucket
- Default root object:
index.html - Compression enabled for HTML/CSS/JS
- Cache invalidation on deployment
- HTTPS-only with HTTP→HTTPS redirect
Route53 / DNS Configuration
For sailjada.com and queenofsandiego.com (Route53-hosted), created A records with alias targets pointing to respective CloudFront distributions. For dangerouscentaur.com (Namecheap), added CNAME reusing the existing wildcard distribution. For burialsatseasandiego.com (GoDaddy), provisioned new distribution and added ACM validation record.
Session Capture Mechanism
Stop Hook Implementation
Created /Users/cb/.claude/hooks/tech_blog_stop.sh which executes when a Claude Code session ends. The hook:
- Reads the latest session transcript from
~/.claude/sessions/ - Extracts file modifications, command history, and tool use patterns
- Invokes the blog generator with transcript path and target site identifier
- Handles errors gracefully with logging to
~/.claude/logs/tech_blog_stop.log
Registered the hook in ~/.claude/settings.json under the hooks section with key on_session_end, pointing to the executable script.
Transcript Format Parsing
Claude Code sessions store transcripts in JSONL format at ~/.claude/sessions/[session-id]/transcript.jsonl. Each line contains a JSON object representing either:
- User messages: input text and context
- Assistant responses: generated content and reasoning
- Tool use: function calls with parameters and results (file operations, command execution)
- Session metadata: timestamps, file paths, environment context
The generator parses these entries to extract granular details about what was modified, created, or deleted.
Blog Generator Implementation
Core Logic
The tech_blog_generator.py script performs:
- Transcript parsing: Reads JSONL and filters for relevant entries (file modifications, commands, tool use)
- Content extraction: Pulls exact file paths, function names, configuration changes, and reasoning from tool use entries and assistant responses
- Credential filtering: Regex-based redaction of AWS credentials, API keys, passwords, tokens, and secrets before HTML generation
- HTML templating: Generates semantic HTML with proper heading hierarchy, code blocks, and lists
- S3 upload: Deploys generated post to appropriate tech blog S3 bucket with metadata headers
- CloudFront invalidation: Triggers cache invalidation for the distribution serving that subdomain
Content Filtering
Implemented multi-layer credential detection:
- Regex patterns for AWS access keys, secret keys, and session tokens
- Common password/API key indicators (Bearer tokens, OAuth strings, encoded credentials)
- Environment variable redaction (API keys, passwords assigned to env vars)
- File path sanitization (removing absolute paths to sensitive directories)
Any matched patterns are replaced with [REDACTED] in generated output.
Navigation Integration
Updated /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html to include tech blog links in the Ship's Papers dropdown menu. Each property's main site now displays a "Tech Blog" navigation item linking to its respective tech subdomain. This maintains consistency across all four properties.
Infrastructure Initialization
Created tech_blog_init.py to provision infrastructure idempotently. The script:
- Checks for existing S3 buckets; creates if missing
- Verifies ACM certificates; requests new ones if needed with DNS validation
- Creates CloudFront distributions with proper origin, cache, and compression settings
- Adds DNS records (Route53 A records with alias targets, Namecheap CNAMEs, or GoDaddy records)
- Generates index.html placeholder pages with proper styling
- Saves infrastructure metadata to
~/.claude/projects/.../memory/project_tech_blogs.mdfor reference
The initialization is designed to be re-runnable without side effects—it verifies state before making changes.