Building an Automated Technical Blog System Across Four Maritime Event Sites
This session focused on architecting and implementing an automated technical documentation system that captures development work in real-time across four distinct domains: queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com. The goal was to create granular, detailed technical posts that appear immediately after work completes, accessible via each site's Ship's Papers navigation menu.
System Architecture Overview
The implementation consists of three core components:
- Tech Blog Generator (
/Users/cb/Documents/repos/tools/tech_blog_generator.py) — Parses Claude session transcripts in JSONL format and converts tool usage patterns into detailed technical posts - Infrastructure Initialization (
/Users/cb/Documents/repos/tools/tech_blog_init.py) — Provisions S3 buckets, CloudFront distributions, and DNS records for each tech blog domain - Claude Hooks Integration (
/Users/cb/.claude/hooks/tech_blog_stop.sh) — Registered as a stop hook that triggers post generation and deployment whenever a Claude session ends
Infrastructure Provisioning Strategy
Rather than manually creating resources for each site, the system leverages existing wildcard SSL certificates:
- queenofsandiego.com and sailjada.com already had ACM wildcard certificates (
*.queenofsandiego.comand*.sailjada.com), allowing immediate tech subdomain deployment - dangerouscentaur.com reuses the existing wildcard CloudFront distribution (Distribution ID:
E2Q4UU71SRNTMB) backed by thedc-sitesS3 bucket, with tech blog content isolated in a/techpath prefix - burialsatseasandiego.com required new ACM certificate provisioning and Route53 DNS validation, leveraging the GoDaddy API integration already established for domain management
Each tech blog is deployed to its own S3 bucket following the pattern tech-[domain]-posts, with CloudFront distributions configured for immediate cache invalidation on new posts.
Session Transcript Processing Pipeline
The tech blog generator processes Claude session data through the following stages:
- JSONL Parsing — Reads the session transcript file format (stored in
~/.claude/sessions/) which contains tool invocations and file modifications as newline-delimited JSON objects - File Change Extraction — Identifies all Write and Edit operations, capturing exact file paths and modification types
- Tool Use Mapping — Correlates command executions with their corresponding file changes to understand the workflow sequence
- Credential Filtering — Strips sensitive data (API keys, passwords, personal information) before post generation using regex patterns for common credential formats
- HTML Generation — Produces semantically structured HTML posts with technical depth, including code blocks, file paths, and architecture decisions
Navigation Integration via Ship's Papers
Each site's Ship's Papers menu (the navigation dropdown present in index.html for all four domains) was updated to include a "Tech Blog" link:
- queenofsandiego.com →
https://tech.queenofsandiego.com/ - sailjada.com →
https://tech.sailjada.com/ - dangerouscentaur.com →
https://tech.dangerouscentaur.com/ - burialsatseasandiego.com →
https://tech.burialsatseasandiego.com/
This integration ensures that stakeholders like Sergio can immediately access detailed technical documentation for any feature, bug fix, or infrastructure change without leaving the main site navigation.
CloudFront Deployment and DNS Configuration
The infrastructure init script performs the following DNS and content delivery operations:
For Route53-managed domains (queenofsandiego.com, sailjada.com, burialsatseasandiego.com):
- Retrieves hosted zone IDs from Route53
- Creates A records with alias targets pointing to CloudFront distribution domain names
- Sets alias hosted zone IDs to the CloudFront-managed zone (Z2FDTNDATAQYW2)
For Namecheap-managed domains (dangerouscentaur.com):
- Generates CNAME records pointing to the existing CloudFront distribution
- Applies records via direct Namecheap API calls or manual CNAME configuration
For ACM certificate validation:
- New certificates are requested with DNS validation enabled
- Validation records are automatically added to Route53 (for Route53 domains) or via GoDaddy API (for GoDaddy-managed domains like burialsatseasandiego.com)
- Validation typically completes within minutes, allowing CloudFront distribution activation
Stop Hook Integration with Claude Code
The stop hook was registered in ~/.claude/settings.json under the hooks configuration. When a session ends:
- The hook script (
tech_blog_stop.sh) executes automatically - It reads the session transcript from the Claude Code session directory
- Invokes the tech blog generator against that transcript
- Determines which of the four sites were affected based on file paths modified
- Uploads the generated post(s) to the appropriate S3 bucket(s)
- Invalidates CloudFront cache paths to ensure immediate visibility
- Logs all actions to
~/.claude/logs/tech_blog_generation.logfor audit trails
Key Technical Decisions
Why JSONL session transcripts instead of manual logging? Claude Code's native session format captures the exact sequence of tool invocations and file changes without requiring additional instrumentation. This is the source of truth already present in every session.
Why separate S3 buckets per tech blog? Isolation allows independent access control, CloudFront cache policies, and future scalability. Posts for queenofsandiego.com don't share storage with dangerouscentaur.com, reducing blast radius for any misconfiguration.
Why leverage existing wildcard certificates? Certificates for *.queenofsandiego.com and *.sailjada.com were already in ACM, eliminating certificate provisioning delays and DNS validation wait times for those domains.
Why filter credentials at generation time? The hook runs automatically and posts are public-facing. Credential filtering prevents accidental exposure of API keys, GoDaddy credentials, AWS profiles, or other sensitive data that might appear in tool outputs or file contents.
What's Next
The system is now operational. Immediate next steps include:
- Testing the stop hook against a full