Building Automated Technical Documentation: Multi-Site Blog Infrastructure with Session Capture
What Was Done
Implemented a comprehensive automated technical blog system across four domains (queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com) that captures development session activity and publishes granular technical posts in real-time. This system integrates with Claude Code's session management to extract work artifacts and infrastructure changes, then publishes sanitized technical documentation to dedicated tech subdomains.
Technical Architecture
Core Components
- tech_blog_generator.py — Main Python module that parses Claude Code JSONL session transcripts, extracts file modifications and command executions, filters sensitive data (credentials, API keys, tokens), and generates HTML blog posts with proper metadata.
- tech_blog_init.py — Infrastructure provisioning script that creates S3 buckets (one per domain), CloudFront distributions for static delivery, Route53 DNS records with health checks, and ACM certificate management with DNS validation.
- tech_blog_stop.sh — Claude Code Stop hook that executes automatically at session end, triggers the blog generator, and uploads new posts to the appropriate tech subdomain.
- Claude Code Settings Integration — Registered stop hook in
~/.claude/settings.jsonpointing to the executable stop script, ensuring every development session generates documentation.
Infrastructure Topology
Each technical blog runs on identical infrastructure:
- S3 Buckets:
qos-tech-blog,jada-tech-blog,dc-sites-tech-blog,bats-tech-blog— Static HTML storage with versioning and lifecycle policies. - CloudFront Distributions — Origin set to respective S3 buckets with custom domain CNAMEs (e.g.,
tech.queenofsandiego.com), HTTP/2 enabled, gzip compression, cache behaviors for index.html (minimal TTL) and assets (24hr TTL). - Route53 / DNS — For sailjada.com and queenofsandiego.com domains (Route53 hosted zones), A records point to CloudFront distribution aliases. For dangerouscentaur.com (existing wildcard CF dist on Namecheap) and burialsatseasandiego.com (GoDaddy DNS), CNAME records added for tech subdomains.
- ACM Certificates — Leveraged existing wildcard certs (
*.queenofsandiego.com,*.sailjada.com) for the CloudFront distributions; created new cert fortech.dangerouscentaur.comand validated via GoDaddy DNS for burialsatseasandiego.com.
Session Capture Mechanism
JSONL Transcript Parsing
Claude Code stores session transcripts as JSON Lines format in ~/.claude/sessions/. Each line contains message metadata including:
{"type": "tool_use", "name": "bash", "input": {"command": "..."}, ...}
{"type": "tool_result", "output": "..."}
The blog generator extracts:
- File write/edit operations from filesystem commands and tool outputs
- Bash commands executed (except those matching credential patterns)
- AWS CLI operations (showing resource names, not credentials)
- Configuration changes with before/after snippets
Data Sanitization
Critical security step — the generator uses regex patterns to detect and redact:
- AWS credentials, API keys, and tokens
- Password strings in environment variables or configs
- GoDaddy/Namecheap API credentials
- Email addresses and phone numbers
- Database connection strings
- SSH keys and personal identifiers
Redacted sections appear as [REDACTED: credential type] in the published post.
Integration Points
Ship's Papers Navigation
Updated HTML navigation menus across all four sites to include "Technical Blog" links in the Ship's Papers section. This makes development activity visible to stakeholders (like Sergio) without exposing infrastructure details.
CloudFront Invalidation
The stop hook includes cache invalidation for /* on the tech blog CloudFront distribution, ensuring new posts appear immediately without waiting for TTL expiration.
Timestamped Posts
Each generated post includes:
- Session start/end timestamps
- Ordered list of file modifications with line counts changed
- Chronological command execution list
- Infrastructure resource changes with before/after state
- Decision rationale for architectural changes
Key Technical Decisions
Stop Hook vs. Scheduled Job
Using Claude Code's Stop hook (execution at session end) rather than cron jobs ensures documentation is generated only when actual work occurs, eliminating empty posts and keeping the blog focused on real activity.
Per-Domain vs. Centralized Blog
Created separate tech blogs for each domain rather than a single centralized blog. This allows different stakeholders to view relevant documentation (Sergio sees queenofsandiego.com work; other crew sees their domain's activity) and isolates credential risk—if one domain's S3 is compromised, only that blog is affected.
Static HTML Generation
Rather than a dynamic backend, posts are generated as static HTML and pushed to S3. This provides:
- No server management or authentication needed
- CloudFront edge caching for instant delivery
- Immutable post history (versioned in S3)
- No database or runtime dependencies
Route53 vs. External DNS
For domains already in Route53 (queenofsandiego.com, sailjada.com), A records point directly to CloudFront aliases with health checks. For external DNS (dangerouscentaur at Namecheap, burialsatseasandiego at GoDaddy), CNAME records created, adding a small lookup overhead but avoiding DNS provider lock-in.
Infrastructure Provisioning Details
S3 Bucket Creation:
aws s3api create-bucket \
--bucket qos-tech-blog \
--region us-west-2 \
--create-bucket-configuration LocationConstraint=us-west-2
aws s3api put-bucket-versioning \
--bucket qos-tech-blog \
--versioning-configuration Status=Enabled
aws s3api put-bucket-public-access-block \
--bucket qos-tech-blog \
--public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=false,RestrictPublicBuckets=false"
CloudFront Distribution:
Configured with S3 bucket as origin, origin access identity (OAI) for secure bucket access,