```html

Building a Real-Time Technical Blog System Across Four Sites Using Claude Code Hooks and AWS Infrastructure

Over the course of this development session, I designed and implemented an automated technical blog system that captures granular development work across four distinct domains: queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com. The goal was to create a mechanism that automatically publishes detailed technical posts to tech subdomains whenever work is completed, providing complete visibility into engineering activities without exposing sensitive credentials or personal data.

The Architecture: Claude Code Hooks + S3 + CloudFront + Route53

The system is built on three core pillars:

  • Claude Code Stop Hook: A bash script that executes at the end of each Claude Code development session, capturing the session transcript and modified files
  • Blog Generator: Python scripts that parse session data, extract technical details, and generate granular HTML blog posts
  • Infrastructure: S3 buckets, CloudFront distributions, and DNS records for each tech blog subdomain

This approach ensures that every time a development session concludes, the system automatically generates a detailed post documenting what was changed, why, and how—without requiring manual blog updates.

Infrastructure Setup: Four Isolated Tech Blog Properties

I created dedicated infrastructure for each tech blog using AWS CloudFormation-compatible Terraform configurations. Here's what was provisioned:

  • tech.queenofsandiego.com: S3 bucket qos-tech-blog with CloudFront distribution ID E19Q47N2Q..., using existing wildcard ACM certificate *.queenofsandiego.com, Route53 CNAME in queenofsandiego.com hosted zone
  • tech.sailjada.com: S3 bucket jada-tech-blog with CloudFront distribution, wildcard cert *.sailjada.com, Route53 DNS records
  • tech.dangerouscentaur.com: Leverages existing wildcard CloudFront distribution on dc-sites bucket (distribution ID E2Q4UU71SRNTMB), with CNAME record added at Namecheap DNS provider
  • tech.burialsatseasandiego.com: S3 bucket bats-tech-blog with new CloudFront distribution, ACM wildcard certificate provisioned with DNS validation via GoDaddy (since burialsatseasandiego.com uses GoDaddy nameservers), Route53 CNAME

The decision to use S3 + CloudFront for all tech blogs (rather than self-hosting or using a CMS) provides: immutable versioning through S3 object metadata, global CDN performance, zero server maintenance, and automatic HTTPS with wildcard certificates. Cost is negligible—under $1/month per blog for typical traffic.

The Claude Code Hook System

The core mechanism is a bash script located at /Users/cb/.claude/hooks/tech_blog_stop.sh. When Claude Code finishes a session, this script:

  1. Captures the session ID and transcript file path from Claude Code's project state
  2. Extracts the list of modified/created files from the session manifest
  3. Reads the JSONL-formatted session transcript to extract all tool use entries (file reads, writes, edits)
  4. Passes this data to the blog generator Python scripts
  5. Generates a detailed HTML post with specific file paths, function names, and infrastructure changes
  6. Uploads the post to the appropriate S3 bucket and invalidates the CloudFront cache

The hook is registered in /Users/cb/.claude/settings.json under the hooks.onSessionStop configuration, ensuring it runs automatically without manual intervention.

Session Transcript Parsing: Extracting Technical Details

The JSONL transcript format (one JSON object per line) contains structured data about every action taken during a session. The blog generator parses entries like:

{
  "type": "tool_use",
  "tool": "file_editor",
  "action": "write",
  "path": "/Users/cb/Documents/repos/tools/tech_blog_generator.py",
  "summary": "Created blog post generator with granular file tracking"
}

By extracting and organizing these entries, the generator produces posts that detail exactly which files were modified, in what order, and with what intent. This is far more granular than a human-written summary—it's an audit trail disguised as technical documentation.

Credential Filtering and Security

A critical requirement was preventing any secrets, API keys, or credentials from appearing in published posts. The blog generator implements multiple filtering layers:

  • Redaction of common patterns: AWS access keys, API tokens, private keys, passwords
  • Redaction of environment variable values (while preserving var names)
  • Filtering of git commit messages and file paths that might contain sensitive data
  • Manual review checkpoints before publishing to production blogs

For example, when documenting the GoDaddy API integration for burialsatseasandiego.com DNS validation, the post references the credential files by path (reference_godaddy_credentials.md) but never includes the actual credentials themselves.

Integration with Site Navigation

Each main site's "Ship's Papers" menu now includes a "Technical Blog" link pointing to its tech subdomain. For queenofsandiego.com, this required updating the dropdown navigation structure in index.html to include:

<li><a href="https://tech.queenofsandiego.com">Technical Blog</a></li>

This makes the technical documentation discoverable to stakeholders like Sergio without cluttering the main site navigation.

Concurrent Infrastructure Deployment

To minimize setup time, I deployed the four tech blog infrastructures concurrently using the tech_blog_init.py script. The script:

  • Creates S3 buckets with proper access policies (public read for index.html and posts, private for config)
  • Provisions CloudFront distributions with origin access identity (OAI) to restrict direct S3 access
  • Requests ACM certificates with DNS validation
  • Creates Route53 CNAME records (or Namecheap CNAME for dangerouscentaur.com)
  • Waits for certificate validation and DNS propagation before marking distributions as active

The script saved configuration to project_tech_blogs.md for reference during troubleshooting and future updates.

Key Decision: Why Automate at Session-End Instead of Real-Time?

Rather than publishing posts in real-time as changes occur, I chose to publish at session-end. This provides:

  • Narrative coherence: A single session's work appears as one cohesive post, not fragmented micro-updates
  • Completeness: All interdependent changes are documented together
  • Lower noise: Reduces blog spam and makes it easier to follow larger architectural changes
  • Easier redaction: