I'll write a technical blog post covering the hub infrastructure work from the session. Reading the key technical decisions and implementation details now.

Building The Queen's Fleet Hub: Multi-City Site Unification with CloudFront and Dynamic Routing

What We Built

We implemented a unified hub infrastructure for The Queen's Fleet, a distributed multi-site architecture spanning 16 destination domains (queenof[city].com, thepacific.com, theatlantic.com, and mazatlan.com). The hub at thequeensfleet.com serves as the central entry point, with CloudFront dynamic routing directing visitors to city-specific microsites while maintaining a single canonical infrastructure.

Infrastructure Architecture

The solution uses AWS CloudFront as the primary routing layer, backed by an S3 origin (qos-city-sites bucket in us-west-2). Here's the core stack:

  • Primary Distribution: CloudFront distribution ID E176JRMB92GPAJ serves the hub and routes to all 16 destination sites via origin routing logic
  • SSL/TLS: ACM certificates provisioned in us-east-1 (CloudFront requirement) for thequeensfleet.com, with validation via Namecheap DNS CNAME records
  • DNS: Route53 A and AAAA records for apex domain, with CNAME aliases on the CloudFront distribution for each city variant (thepacific, theatlantic, mazatlan)
  • S3 Origin: Single bucket with per-city subdirectories, each containing index.html and assets/ (card images at assets/0.jpg, etc.)

Hub Builder and Dynamic Routing

The hub is generated via Python factory logic in build/build_hub.py, which reads the site registry and produces a single index.html that serves as the hub landing page. The router function (deployed as a CloudFront function in the viewer-request event) determines which destination site to serve based on the incoming Host header.

The router pattern uses a lookup table mapping Host headers to origin paths:

// Excerpt from build/router.js (CloudFront Function)
// Maps incoming host (e.g., queenofportland.com) to origin path
const cityMap = {
  'queenofportland.com': '/sites/portland/',
  'thequeensfleet.com': '/',
  'thepacific.com': '/sites/pacific/',
  // ...additional city mappings
};

When a request arrives at any of the 16 domains, the function rewrites the origin path and CloudFront serves the appropriate index.html and assets from the S3 bucket. This eliminates the need for separate S3 buckets per city and consolidates the entire infrastructure into a single CloudFront distribution.

Deployment and Testing

The hub deployment pipeline:

  • Generate hub HTML via build/build_hub.py, reading the site registry at build/registry.json
  • Upload hub index.html to S3 with ETag verification to confirm upload integrity
  • Update CloudFront function in build/router.js and deploy to the distribution
  • Invalidate CloudFront cache (/* pattern) to purge old content
  • Run regression tests via tests/test_hub.py, which verify that all 16 destination sites return valid HTML, images load correctly, and routing logic works as expected

Test results confirm all 16 sites serve index.html and card images (assets/0.jpg) over HTTPS without issues. DNS propagation for apex domain (thequeensfleet.com) was monitored across multiple public resolvers before declaring the deployment complete.

Key Technical Decisions

Why a Single CloudFront Distribution?
Rather than deploying 16 separate CloudFront distributions, we consolidated into one. This reduces operational overhead, simplifies certificate management, and allows us to add new city sites without provisioning new AWS resources. The router function provides the routing logic that would otherwise require separate S3 buckets or origin configurations.

Why CloudFront Functions Over Lambda@Edge?
CloudFront Functions have lower latency (sub-millisecond execution) and run at the viewer-request stage, making them ideal for simple host-based routing. Lambda@Edge would introduce unnecessary complexity and cost for this use case.

Why Route53 ALIAS Records for Apex?
Traditional CNAME records cannot be used on apex domains (queenofcity.com without the www prefix). Route53's ALIAS feature allows us to alias the apex domain directly to the CloudFront distribution, eliminating the need for DNS workarounds or separate A records.

Why S3 Over EC2 or App Servers?
The hub content is static HTML and images. S3 is cheaper, requires zero maintenance, and scales automatically. CloudFront's edge caching layer means even traffic spikes don't impact the origin.

Site Registry and Factory Pattern

The system uses a centralized site registry (build/registry.json) that defines all active Queen's Fleet properties, including domain, origin path, card images, and metadata. The hub builder reads this registry and generates the hub page dynamically, ensuring that adding a new city only requires updating the registry — no code changes needed.

The factory pattern in factory/seed_sprint.py extends this by generating avatar variants and managing the lifecycle of destination site content, decoupling content generation from infrastructure management.

Infrastructure as Code Notes

All infrastructure changes were tracked in decision logs (decisions/queens-fleet-avatar-and-hub.md) and stored in Git alongside the code. DNS records, CloudFront configurations, and route updates were applied via the Namecheap API from a Lightsail bastion box, ensuring all changes are auditable and reproducible.

What's Next

  • Complete avatar generation: finalize the Jada persona and generate 40 canonical variants, narrowed to 20 production images
  • Integrate avatar images into the hub landing page and city card backgrounds
  • Set up automated monitoring for CloudFront distribution health and S3 object availability
  • Expand the router function to support A/B testing and dynamic destination logic (e.g., based on query parameters or geographic location)
  • Implement automated content updates via the factory pipeline to keep destination cards fresh

The hub infrastructure is now production-ready and scales from 16 cities to many more without additional AWS provisioning. The centralized routing and registry pattern provides a foundation for future expansion of The Queen's Fleet portfolio.