Building Multi-Site Automated Technical Blog Infrastructure with Session-Based Post Generation
What Was Done
Implemented a complete automated technical blogging system across four separate domains (queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com) that automatically captures development work from Claude Code sessions and publishes granular technical posts without exposing credentials or sensitive data.
Architecture Overview
The system consists of three core components:
- Session Capture Hook: A Stop hook integrated into Claude Code that runs when development sessions end
- Infrastructure Init Script: Provisions S3 buckets, CloudFront distributions, and DNS records for each tech blog domain
- Blog Generator: Parses session transcripts, extracts technical work, and generates HTML posts with automatic credential filtering
Infrastructure Setup
S3 Bucket Architecture
Created dedicated S3 buckets for each tech blog:
qos-tech-blog— Hosts tech.queenofsandiego.comjada-tech-blog— Hosts tech.sailjada.comdc-sites— Existing bucket repurposed with wildcard CloudFront distribution for *.dangerouscentaur.combats-tech-blog— Hosts tech.burialsatseasandiego.com
Each bucket is configured as a static website host with index.html as the default root object. Buckets are blocked from public ACL access; all traffic routes through CloudFront.
CloudFront Distribution Strategy
Four CloudFront distributions provide global edge caching:
- Three new distributions point to
qos-tech-blog,jada-tech-blog, andbats-tech-blogS3 origins - Existing dangerouscentaur distribution already provides wildcard coverage for all *.dangerouscentaur.com subdomains
- All distributions use AWS Certificate Manager wildcard certificates (
*.queenofsandiego.com,*.sailjada.com, and wildcard for dangerouscentaur) - Cache behavior set to 300-second TTL for HTML to balance freshness with performance
DNS Configuration
Different DNS providers required different approaches:
- queenofsandiego.com (Route53): Created
tech.queenofsandiego.comCNAME record pointing to CloudFront distribution domain - sailjada.com (Route53): Created
tech.sailjada.comCNAME record pointing to CloudFront distribution domain - dangerouscentaur.com (Namecheap): Added CNAME for
tech.dangerouscentaur.compointing to existing wildcard distribution - burialsatseasandiego.com (GoDaddy): Added CNAME for
tech.burialsatseasandiego.compointing to CloudFront; also integrated ACM certificate DNS validation records
Session Hook Integration
The Stop hook is located at /Users/cb/.claude/hooks/tech_blog_stop.sh and runs automatically when Claude Code sessions terminate. The hook:
- Exports the current session transcript in JSONL format from Claude Code's internal storage
- Passes the transcript to the blog generator with site context (determining which domain to publish to based on file modifications)
- Filters out any sensitive patterns (API keys, tokens, credentials, personal identifiers)
- Generates a timestamped HTML post and uploads it to the appropriate S3 bucket via AWS CLI
- Invalidates the CloudFront distribution cache to ensure new posts appear immediately
- Logs all operations to
~/.claude/logs/tech_blog_generation.logfor audit trails
Blog Generator Logic
The generator (/Users/cb/Documents/repos/tools/tech_blog_generator.py) parses session transcripts by:
- Identifying modified files: Examines the "Files modified/created" section to determine which site(s) were worked on
- Extracting tool invocations: Parses JSONL records where
type: "tool_use"to capture commands run (with credential filtering) - Building semantic context: Groups related file modifications and commands into logical work units (e.g., "Infrastructure Setup" vs "Content Updates")
- Creating HTML structure: Generates semantic HTML with
<h2>,<h3>, and<code>tags for readability - Sanitizing output: Strips passwords, API keys, tokens, secret ARNs, and personal data using regex patterns and keyword matching
- Timestamping: Uses ISO 8601 timestamps for post publication dates and file organization
Navigation Integration
Updated /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html to add a "Ship's Papers" menu section with a "Technical Blog" link pointing to tech.queenofsandiego.com. This provides user-visible access to development transparency. Similar navigation will be added to other main sites.
Key Technical Decisions
Why Separate S3 Buckets Instead of One Shared Bucket
Separate buckets provide clear ownership boundaries, independent scaling, and easier access control policies. If one site's traffic spikes, it doesn't affect others. Disaster recovery is also isolated—rolling back one blog doesn't require understanding another site's history.
Why CloudFront Over Direct S3 Access
CloudFront provides geographic distribution (faster loads for global users), DDoS protection via AWS Shield Standard, and the ability to add request/response headers without touching S3. HTTPS termination at the edge is also essential for security.
Why Session-Based Rather Than Git-Hook-Based
Claude Code sessions are self-contained and preserve full context (exact prompts, tool outputs, file contents). Git hooks capture only commit messages and diffs. Sessions capture the reasoning and decision-making process, which is valuable for Sergio to understand not just what changed, but why.
Credential Filtering Strategy
The generator uses multiple filtering layers: regex patterns for AWS ARNs, API Gateway keys, and JWT tokens; keyword matching for "password," "secret," "key," and "token"; and redaction of sensitive environment variables. This defense-in-depth approach minimizes the risk of accidental exposure.
Infrastructure Code
The initialization script /Users/cb/Documents/repos/tools/tech_blog_init.py is idempotent and handles:
- S3 bucket creation with versioning and website hosting configuration
- CloudFront distribution creation with appropriate cache behaviors
- DNS