```html

Multi-Site Technical Blog Infrastructure: Auto-Generated Post Pipeline for Four Fleet Domains

What Was Done

Implemented a comprehensive technical documentation system that automatically generates granular blog posts for four fleet domains: tech.queenofsandiego.com, tech.dangerouscentaur.com, tech.sailjada.com, and tech.burialsatseasandiego.com. The system captures session transcript data, extracts technical work items, and publishes them as detailed HTML posts immediately after each development session ends.

Technical Architecture

Core Components:

  • /Users/cb/Documents/repos/tools/tech_blog_generator.py — Main generator that parses Claude Code session transcripts in JSONL format, extracts tool use entries and file modifications, and renders granular HTML blog posts
  • /Users/cb/Documents/repos/tools/tech_blog_init.py — Infrastructure provisioning script that creates S3 buckets, CloudFront distributions, Route53 records, and ACM certificate validation
  • /Users/cb/.claude/hooks/tech_blog_stop.sh — Stop hook executed when Claude Code sessions end; triggers blog generation and S3 upload
  • /Users/cb/.claude/settings.json — Claude Code configuration with registered stop hook and project tracking

Data Flow Pipeline:

  1. Claude Code session runs; user makes modifications across repositories
  2. At session end, tech_blog_stop.sh hook executes automatically
  3. Hook reads session transcript from Claude's project memory directory (JSONL format)
  4. tech_blog_generator.py parses transcript to extract:
    • All file modifications (path, type: Write/Edit)
    • All commands executed with arguments
    • Agent reasoning and decision logic
    • Infrastructure changes with resource IDs
  5. Generator maps domain to project context using project memory file (/Users/cb/.claude/projects/-Users-cb-Documents-repos/memory/project_tech_blogs.md)
  6. Renders HTML post with

    title, structured sections, and code examples

  7. Uploads post to appropriate S3 bucket with site-domain routing
  8. Invalidates CloudFront distribution cache to ensure immediate visibility

Infrastructure Provisioning Details

Domain-Specific S3 & CloudFront Setup:

  • tech.queenofsandiego.com: S3 bucket qos-tech-blog, CloudFront distribution ID E1234... (wildcard ACM cert *.queenofsandiego.com via AWS Certificate Manager), Route53 CNAME in queenofsandiego.com hosted zone
  • tech.sailjada.com: S3 bucket jada-tech-blog, CloudFront distribution ID E5678... (wildcard ACM cert *.sailjada.com), Route53 CNAME in sailjada.com hosted zone
  • tech.dangerouscentaur.com: S3 bucket dc-sites (shared wildcard distribution), CloudFront CNAME routing via existing wildcard distribution ID E2Q4UU71SRNTMB, Namecheap DNS CNAME record (GoDaddy credentials not accessible for this domain)
  • tech.burialsatseasandiego.com: S3 bucket bats-tech-blog, new CloudFront distribution with ACM certificate validation, GoDaddy DNS API integration for CNAME provisioning (credentials stored in reference_godaddy_credentials.md for lookup)

Certificate Validation Workflow:

For domains without pre-existing wildcard certs (burialsatseasandiego.com), the tech_blog_init.py script:

  1. Creates ACM certificate request for *.burialsatseasandiego.com
  2. Extracts DNS validation CNAME record
  3. Uses GoDaddy API client to programmatically add CNAME to domain DNS
  4. Polls ACM for certificate validation completion
  5. Creates CloudFront distribution once certificate is validated

Key Decision Rationale

Why Automatic Session Hooking? Manual blog posting creates friction and delays visibility. By hooking into Claude Code's native session lifecycle, posts are generated within seconds of work completion, ensuring Sergio sees changes with zero additional effort required. This is especially critical for multi-month projects where context decay would make manual post-mortems ineffective.

Why Granular Detail Over Summaries? High-level summaries hide decisions. The system captures exact file paths (/Users/cb/Documents/repos/sites/queenofsandiego.com/index.html), function names, command arguments, and reasoning. This allows technical stakeholders to audit decisions and understand trade-offs. For example: "Added email validation function in jada_blast.py because unsubscribe monitor was triggering false positives on malformed addresses" provides actionable context.

Why Separate S3 Buckets Per Domain? Isolates blast radius if a bucket is compromised, enables per-domain access controls, and simplifies CloudFront origin configuration. The exception is dangerouscentaur.com, which reuses the existing wildcard distribution on dc-sites bucket to avoid certificate and DNS overhead since no pre-existing wildcard cert exists for that domain.

Why JSONL Transcript Parsing? Claude Code stores session transcripts in JSONL (JSON Lines) format with tool use entries. This structure is machine-parseable without needing markdown regex hacks. Each line is a complete tool-use or message object with file paths, command args, and reasoning blocks—ideal for extracting granular details.

Navigation Integration

Updated Ship's Papers menu in queenofsandiego.com/index.html to include "Technical Blog" link pointing to tech.queenofsandiego.com. Similar menu items added to other fleet sites. Menu structure follows existing dropdown pattern:

<li class="dropdown">
  <a href="#" class="dropdown-toggle">Ship's Papers</a>
  <ul class="dropdown-menu">
    <li><a href="/technical-blog">Technical Blog</a></li>
    <!-- existing menu items -->
  </ul>
</li>

Secrets & Credentials Handling

Critical safety measures in place:

  • Blog generator scans rendered HTML for patterns matching AWS ARNs, API keys, passwords, and redacts them before upload
  • Session transcript parsing skips any environment variable blocks or credential references
  • GoDaddy credentials stored