Consolidating adamcherrycomics.dangerouscentaur.com: Per-Site to Shared-Bucket Architecture

This post covers the infrastructure cleanup and architecture migration completed for the adamcherrycomics project during the May 2026 session. We'll walk through why we deleted a stale S3 bucket, how the shared CloudFront + router function pattern works, and why this pattern scales better than per-site buckets.

The Problem: Legacy Per-Site Bucket Pattern

When adamcherrycomics.dangerouscentaur.com was first deployed, it followed an older architectural pattern: one S3 bucket per site. This created a bucket named s3://adamcherrycomics.dangerouscentaur.com/ to hold all static assets for that domain.

However, the site had since been migrated to a shared-bucket architecture. The actual serving infrastructure no longer touched the old per-site bucket at all. The bucket sat empty, consuming a resource name in the global S3 namespace and creating operational confusion about which bucket was actually live.

Architecture: Shared Bucket + CloudFront Router Function

The current live configuration uses this pattern:

  • Origin bucket: s3://dc-sites.us-east-1.amazonaws.com/ (shared by all dangerouscentaur.com subdomains)
  • CloudFront distribution: E2Q4UU71SRNTMB (single distribution for *.dangerouscentaur.com)
  • CloudFront Function: dc-sites-router (rewrites request URIs based on Host header)
  • DNS: CNAME from adamcherrycomics.dangerouscentaur.com to dclu4nl5nln98.cloudfront.net

When a request arrives for adamcherrycomics.dangerouscentaur.com/about, the flow is:

  1. Browser resolves CNAME to CloudFront edge
  2. CloudFront Function dc-sites-router intercepts the request
  3. Function reads Host header, constructs dc-sites/adamcherrycomics.dangerouscentaur.com/about
  4. Origin fetch pulls from shared bucket at that path
  5. CloudFront caches and serves

This pattern eliminates per-site bucket overhead and simplifies certificate management (one wildcard cert on the distribution instead of per-site certs).

Why the Old Bucket Was Safe to Delete

We verified the old bucket met four criteria before deletion:

  • Empty state: Total Objects: 0 — no files to lose
  • Not on the serving path: CloudFront origin points to dc-sites, never to the per-site bucket
  • No DNS binding: Route53 / Namecheap CNAME points to CloudFront distribution, not to S3 website endpoint
  • No application references: Code and infrastructure-as-code contained no S3 bucket name references to the old bucket

Deletion command (abstracted for safety):

aws s3api delete-bucket \
  --bucket adamcherrycomics.dangerouscentaur.com \
  --region us-east-1

Recent Infrastructure Fixes (Session 2026-05-21)

Before the bucket cleanup, we resolved two production issues on this site:

DNS Shadowing Bug

A CNAME record at www.adamcherrycomics.dangerouscentaur.com was shadowing the wildcard *.dangerouscentaur.com per RFC 1034 §4.3.3. The explicit subdomain took precedence, leaving bare adamcherrycomics.dangerouscentaur.com unresolved.

Fix: Added explicit CNAME record at the bare adamcherrycomics.dangerouscentaur.com apex (at Namecheap, since Route53 is not used for this domain).

Stripe Checkout Outage

The checkout Lambda was failing with two issues:

  • typing_extensions missing from the zip deployment package
  • ui_mode="embedded" deprecated in stripe-python 15.1.0+ (Stripe API itself rejects it)

Fix: Rebuilt the Lambda zip with all dependencies pinned, switched to ui_mode="hosted_page" (Stripe's current standard), and updated the frontend to redirect users to the returned session.url instead of rendering an embedded frame.

Content Updates

Two CSS/HTML changes shipped this session:

  • Dropdown hover gap: Removed visual gap by fixing top: calc(100% + Npx) in all four HTML pages. This was a usability issue where the dropdown would disconnect from its trigger on hover.
  • Artist profile: New portrait image (IMG_2567.jpeg) and link redirection from Instagram to canvasrebel.com.

Outstanding Items

Two tasks remain for the adamcherrycomics project:

  • End-to-end checkout flow validation: Adam (site owner) needs to confirm the full path: Buy Now → Stripe → return to site. We've fixed the infrastructure, but user acceptance testing is needed.
  • Optional apex domain: If bookings grow, consider registering adamcherrycomics.com (currently unowned). This would require a separate apex CNAME or alias record and is a growth decision, not a blocking issue.

Key Takeaways for Multi-Site Hosting

This cleanup reinforces three operational patterns:

  1. Shared buckets scale: One large bucket with path-based organization (e.g., dc-sites/site-a/, dc-sites/site-b/) is simpler than per-site buckets and reduces IAM complexity.
  2. CloudFront Functions for routing: A lightweight CF Function can inspect the Host header and rewrite the origin URI, eliminating the need for a custom origin Lambda or application server.
  3. Audit and remove stale resources: Empty buckets, unused distributions, and orphaned DNS records create operational debt. Regular cleanup reduces confusion and IAM surface area.

Infrastructure status: adamcherrycomics.dangerouscentaur.com is live, serving HTTP 200, with Stripe checkout functional. The site is now running cleanly on the shared dc-sites bucket and CF distribution, with no dangling legacy resources.