Building a Granular Session-Based Technical Blog System Across Four Domain Properties
What Was Done
This session established an automated technical blogging infrastructure that captures detailed, session-level work logs across four domain properties: queenofsandiego.com, sailjada.com, dangerouscentaur.com, and burialsatseasandiego.com. The system automatically generates granular technical posts to tech subdomains immediately after development work completes, making all engineering decisions, infrastructure changes, and code modifications visible to stakeholders like Sergio.
Core Architecture: The Three-Component System
1. Session Capture and Blog Generation
The system relies on Claude Code's Stop hook mechanism, which fires when a development session ends. Two Python scripts handle the transformation:
tech_blog_generator.py— Reads the JSONL session transcript from~/.claude/sessions/, parses tool use entries, and extracts granular technical details (file paths, S3 buckets, CloudFront distribution IDs, Route53 changes)tech_blog_init.py— Initializes infrastructure for each tech blog: creates S3 buckets, CloudFront distributions, Route53 DNS records, and ACM certificates
The generator sanitizes credentials automatically—stripping any passwords, API keys, tokens, or secrets before publishing. It generates HTML posts with semantic structure: title, what-was-done section, technical details, infrastructure specifics, key decisions, and next steps.
2. Infrastructure Layer
Each tech blog runs on identical infrastructure patterns:
- S3 Origins: Four private S3 buckets named
qos-tech-blog,jada-tech-blog,dc-tech-blog, andbats-tech-blogstore all generated HTML posts - CloudFront Distributions: Four separate distributions cache and serve posts globally, improving load times for stakeholder access from multiple locations
- DNS Integration: Route53 hosts DNS for sailjada.com and queenofsandiego.com with CNAME aliases pointing to CloudFront. For dangerouscentaur.com (Namecheap) and burialsatseasandiego.com (GoDaddy), CNAME records are manually added to respective registrars
- ACM Certificates: Wildcard certificates for
*.queenofsandiego.comand*.sailjada.comalready existed; new certificates were provisioned for dangerouscentaur.com and burialsatseasandiego.com.tech subdomains with DNS validation
3. Claude Code Hook Integration
The Stop hook script (tech_blog_stop.sh) executes automatically when a session ends:
#!/bin/bash
# Runs immediately when Claude Code session stops
python3 /Users/cb/Documents/repos/tools/tech_blog_generator.py \
--session-id $CLAUDE_SESSION_ID \
--transcript-path ~/.claude/sessions/current_session.jsonl \
--domain-mapping ~/.claude/projects/repos/memory/project_tech_blogs.md
This script is registered in ~/.claude/settings.json under the hooks.stop configuration, ensuring every completed session generates a blog post without manual intervention.
Technical Implementation Details
Session Transcript Parsing
Claude Code stores session transcripts as JSONL files in ~/.claude/sessions/. Each line is a JSON object representing either a user message or a tool use event. The generator extracts tool use entries like:
{
"type": "tool_use",
"tool_name": "bash",
"input": "aws s3 mb s3://qos-tech-blog --region us-west-2",
"timestamp": "2024-01-15T14:32:05Z"
}
The parser then:
- Groups tool invocations by type (bash commands, file operations, AWS API calls)
- Maps file paths to logical components (e.g.,
/Users/cb/Documents/repos/sites/queenofsandiego.com/index.html→ "Queen of San Diego website navigation") - Extracts resource identifiers (S3 bucket names, CloudFront distribution IDs like
E2Q4UU71SRNTMB, Route53 hosted zone IDs) - Sanitizes all inputs to remove credentials before writing HTML
Multi-Domain Mapping
A configuration file at ~/.claude/projects/-Users-cb-Documents-repos/memory/project_tech_blogs.md maintains metadata for all four properties:
- queenofsandiego.com: Route53 hosted zone,
*.queenofsandiego.comwildcard cert, CloudFront distribution ID - sailjada.com: Route53 hosted zone,
*.sailjada.comwildcard cert, CloudFront distribution ID - dangerouscentaur.com: Namecheap DNS provider, wildcard CloudFront distribution on
dc-sitesS3 bucket - burialsatseasandiego.com: GoDaddy DNS provider, separate ACM certificate for tech subdomain
When the generator runs, it determines which domain the session targeted by examining file paths modified (e.g., files under .../queenofsandiego.com/ route to the QOS tech blog) and routes the generated post to the correct S3 bucket and CloudFront distribution.
Infrastructure as Code Approach
Rather than manual AWS console clicks, the initialization script idempotently creates all resources:
# Example: Create S3 bucket for QOS tech blog
aws s3 mb s3://qos-tech-blog --region 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=true,RestrictPublicBuckets=true"
# Create CloudFront distribution with S3 origin
aws cloudfront create-distribution --distribution-config file://qos-cf-config.json
This ensures reproducibility: if a tech blog needs to be rebuilt, running the init script re-creates identical infrastructure with zero manual steps.
Key Architectural Decisions
- Stop Hook Over Scheduled Jobs: Rather than polling for changes every N minutes, the Stop hook fires immediately when a session ends, ensuring posts are live within seconds. This avoids stale data and polling overhead.
- Separate S3 Buckets Per Domain: While a single bucket could store all posts with prefixes (e.g