Building a Granular Technical Blog System Across Four Sailing & Charter Sites
What Was Done
We implemented an automated technical blog generation system that captures development work at four domain properties and publishes granular, detailed posts to dedicated tech subdomains. This required building infrastructure-as-code tooling, CloudFront distributions, S3 buckets, DNS integration, and a Claude Code hook system that automatically generates blog posts from session transcripts.
The system now publishes to:
tech.queenofsandiego.com(via*.queenofsandiego.comwildcard cert)tech.sailjada.com(via*.sailjada.comwildcard cert)tech.dangerouscentaur.com(via Namecheap CNAME)tech.burialsatseasandiego.com(via GoDaddy DNS)
Technical Architecture
Blog Generator Pipeline
The system works through three Python tools:
tech_blog_generator.py— Parses Claude Code session transcripts (JSONL format) and extracts granular technical details from tool use entries, generating an HTML blog post with exact file paths, command examples, infrastructure changes, and reasoningtech_blog_init.py— Idempotent infrastructure provisioning that creates S3 buckets, CloudFront distributions, ACM certificates, DNS records, and indexes blog poststech_blog_stop.sh— Claude Code hook (bash) that fires on session end, runs the generator, uploads to S3, and invalidates CloudFront
The generator parses session transcripts in JSONL format stored at /Users/cb/.claude/projects/-Users-cb-Documents-repos/sessions/. Each line is a JSON object representing a turn in the conversation. Tool use entries contain structured data about files modified, commands executed, and reasoning—exactly what we need for granular documentation.
Infrastructure Per Domain
For domains using AWS-hosted DNS (queenofsandiego.com, sailjada.com):
- S3 Bucket:
tech-queenofsandiego-com(public, website hosting mode) - CloudFront Distribution: Caching behavior with origin at S3 bucket, using wildcard ACM cert for
*.queenofsandiego.com - Route53 DNS: CNAME alias record
tech.queenofsandiego.com→ CloudFront distribution domain name
For dangerouscentaur.com (no existing AWS setup):
- S3 Bucket:
dc-sites(reuses existing wildcard CloudFront E2Q4UU71SRNTMB) - Namecheap DNS: CNAME
tech.dangerouscentaur.com→ CloudFront distribution domain
For burialsatseasandiego.com (GoDaddy DNS):
- S3 Bucket:
tech-burialsatseasandiego-com - CloudFront Distribution: New distribution with ACM cert (DNS-validated via GoDaddy)
- GoDaddy DNS: CNAME
tech.burialsatseasandiego.com→ CloudFront domain
Key Implementation Details
Session Transcript Parsing
Claude Code sessions are stored as JSONL transcripts. Each session file contains metadata (domain, tags, timestamp) and structured message/tool entries. The generator extracts:
- Files modified/created with paths and write operations
- Commands run (shell history)
- Reasoning/agent notes explaining decisions
- Tool use chains showing cause-and-effect workflows
This allows posts to say "We edited /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html because the Ship's Papers nav dropdown needed restructuring" rather than "We made website updates."
CloudFront Distribution Configuration
Each CloudFront distribution uses:
- Origin: S3 bucket in website hosting mode (not REST API)
- Cache Behavior: 1-hour TTL for HTML (to catch updates quickly), longer for static assets
- Viewer Protocol Policy: Redirect HTTP → HTTPS
- Allowed Methods: GET, HEAD (read-only)
- Default Root Object:
index.html
CloudFront invalidations are triggered post-upload via the --paths "/*" option to ensure new posts are visible immediately (no 1-hour wait).
DNS Validation for ACM Certificates
The burialsatseasandiego.com setup required ACM DNS validation because the domain is at GoDaddy (not Route53). The infrastructure script:
- Requests ACM cert for
tech.burialsatseasandiego.com - Extracts DNS CNAME validation record from pending cert
- Outputs instructions for manual GoDaddy DNS entry (we add via GoDaddy API with stored credentials)
- Polls until cert is validated
- Creates CloudFront distribution pointing to the validated cert
This ensures the blog is HTTPS-enabled without requiring DNS zone transfer.
Claude Code Integration
The stop hook is registered in /Users/cb/.claude/settings.json:
"hooks": {
"on_session_stop": "/Users/cb/.claude/hooks/tech_blog_stop.sh"
}
When a session ends, the hook:
- Reads the session transcript from the session file
- Runs
tech_blog_generator.pyto produce HTML - Uploads to the appropriate S3 bucket (detected from session metadata/repo path)
- Invalidates CloudFront cache
- Logs output to
~/.claude/logs/tech_blog_stop.logfor debugging
The hook is executable and wrapped in error handling to prevent session termination failures from blocking work.
Navigation Integration
Each site's Ship's Papers menu now includes a "Tech Blog" link pointing to the appropriate tech.* subdomain. For queenofsandiego.com, this required editing the navigation dropdown in index.html to add:
<li><a href="https://tech.queenofsandiego.com">Tech Blog</a><