Building an Automated Multi-Site Technical Blog System with Session-Based Post Generation
What Was Done
Implemented a fully automated technical blog infrastructure across four domains (tech.queenofsandiego.com, tech.sailjada.com, tech.dangerouscentaur.com, and tech.burialsatseasandiego.com) that captures development session activity and generates granular technical posts immediately upon session completion. The system uses Claude Code's hook mechanism to intercept session transcripts, parse them for file modifications and commands executed, and publish detailed posts to S3-backed CloudFront distributions without manual intervention.
Technical Architecture
Core Components
tech_blog_generator.py— Main post generation engine that parses Claude Code session transcripts in JSONL format, extracts file modifications (reads, writes, edits), command executions, and agent reasoning, then renders them into structured HTML blog posts with syntax highlighting and navigation.tech_blog_init.py— Infrastructure provisioning script that creates S3 buckets, CloudFront distributions, ACM certificates, and DNS records for each tech blog domain. Validates existing wildcard certificates before creating new resources.tech_blog_stop.sh— Claude Code hook executed at session end that invokes the Python generator, uploads posts to appropriate S3 buckets, and invalidates CloudFront caches for instant publication.
Infrastructure Setup
Each tech blog uses an identical pattern:
- S3 bucket:
tech-{domain}(e.g.,tech-queenofsandiego-com) configured for static web hosting with public read access on HTML files only. - CloudFront distribution: Points to S3 bucket origin with brotli/gzip compression enabled, 1-hour default TTL, and HTTP→HTTPS redirect.
- ACM certificate: Leverages existing wildcard certs (
*.queenofsandiego.com,*.sailjada.com) or creates new ones; uses DNS validation via Route53 or GoDaddy depending on domain registrar. - DNS: Route53 alias records for queenofsandiego.com and sailjada.com; CNAME records at Namecheap for dangerouscentaur.com and GoDaddy for burialsatseasandiego.com.
Session Transcript Parsing
The generator reads session files from ~/.claude/projects/{workspace}/sessions/ in JSONL format. Each line contains either:
- file_write/file_edit events: Path, action type (Write/Edit), and timestamp
- tool_use blocks: Command name, input parameters, and execution results
- text blocks: Agent reasoning explaining decisions and architecture choices
The parser extracts:
Files modified: Path normalization, grouping by directory
Commands run: Exact command names and arguments (redacting sensitive parameters)
Agent notes: Direct extraction from reasoning blocks for "Why" context
Timestamps: Session start/end with duration calculation
Key Implementation Details
Credential Redaction
The system implements strict filtering:
- Any tool_use with parameters containing
password,token,key,secret,credentialfields is scrubbed before publishing. - Environment variable references are preserved; actual values are never extracted.
- GoDaddy API credentials, AWS keys, and DNS passwords are logged to
~/.claude/hooks/logs/separately for audit but never included in public posts.
Domain-Specific Routing
Posts are routed based on file paths modified:
- Modifications to
queenofsandiego.com/→ Published totech.queenofsandiego.com - Modifications to
sailjada.com/→ Published totech.sailjada.com - Modifications to both or infrastructure code → Published to all four sites with domain-specific sections
S3 Upload & CloudFront Invalidation
Post-generation workflow:
aws s3 cp post-YYYYMMDD-HHMMSS.html s3://tech-{domain}-com/posts/
aws cloudfront create-invalidation --distribution-id {ID} --paths "/*"
Invalidations are queued and processed within 60 seconds, ensuring posts appear live before session context windows close.
Navigation Integration
Updated queenofsandiego.com/index.html ship's papers menu to include "Tech Blog" link pointing to tech.queenofsandiego.com. Similar navigation updates applied to other primary sites. Blog index pages auto-generate tables of contents from S3 object listings, sorted by post date descending.
Why This Approach
Granularity Over Summaries
Rather than end-of-month high-level reports, the system captures every file edit, every command, and every decision rationale. This allows Sergio to drill down into specific changes (e.g., "What changed in the booking flow?") without losing implementation context.
Session-Based Triggers
Using Claude Code's native hook mechanism means no external polling, cron jobs, or manual triggers. The moment a development session ends, the hook fires automatically. This eliminates the "did someone document this?" problem.
Infrastructure as Code**Reproducibility
The tech_blog_init.py script is idempotent—running it multiple times is safe and enables disaster recovery. All resource names, bucket policies, and CloudFront configurations follow predictable naming conventions, making audits and modifications straightforward.
Infrastructure Resource Summary
| Domain | S3 Bucket | CloudFront Dist ID | DNS Provider |
|---|---|---|---|
| tech.queenofsandiego.com | tech-queenofsandiego-com |
Created via init script | Route53 |
| tech.sailjada.com | tech-sailjada-com |
Created via init script | Route53 |