```html

Building a Centralized Operations Dashboard: Multi-Domain Infrastructure Consolidation for Event Management

Over the past development session, we consolidated scattered operational tools, payment systems, and deployment infrastructure into a single, accessible ops dashboard. This post details the technical architecture, deployment strategy, and infrastructure decisions behind https://ops.queenofsandiego.com/.

Problem Statement

The operations workflow was fragmented across multiple platforms:

  • Payment processing split between Stripe dashboards and manual tracking
  • Event site deployments required manual S3/CloudFront commands without centralized visibility
  • Booking system logic existed in three separate locations (Apps Script, event HTML, backend)
  • Infrastructure metadata scattered across handoff documents, JSON configs, and markdown files

This created friction during time-sensitive booking operations and made it difficult to manage multiple event properties simultaneously.

Technical Architecture: The Ops Dashboard

File Structure and Deployment

The ops dashboard is a static HTML site deployed to:

  • S3 Bucket: queenofsandiego.com (shared bucket for all subdomains)
  • Path: /ops/index.html
  • CloudFront Distribution: queenofsandiego.com (primary distribution handling all subdomain routing)
  • DNS: Route53 alias record pointing CloudFront distribution to ops.queenofsandiego.com

The static approach was intentional: we prioritized instant load times and zero backend dependencies for a tool used during live booking operations. All data is either:

  • Hardcoded links to external services (Stripe, Zelle, DocuSign)
  • Quick-access buttons to frequently-used resources
  • Embedded iframes or redirects to live dashboards

Content Organization

The dashboard is organized into functional sections, each addressing a specific operational need:

ops/index.html Structure:
├── Payments (Primary CTA)
│   ├── $500 Deposit (Stripe Payment Link)
│   ├── $125 Birthday Sail Link
│   ├── Zelle Details
│   └── Payment History
├── Public Sites (Event Properties)
│   ├── sailjada.com
│   ├── queenofsandiego.com
│   ├── burialsatseasandiego.com
│   └── Events Hub (rady-shell-events index)
├── External Platforms
│   ├── Stripe Dashboard
│   ├── Google Business Profile
│   ├── Instagram @sailjada
│   └── ImprovMX Email Aliases
├── Dev & Deployment
│   ├── S3 Bucket Deployments
│   ├── CloudFront Invalidations
│   ├── Rady Shell Google Apps Script
│   └── DynamoDB (jada-crew-dispatch)
└── Documentation
    └── Port Sheet & Handoff Files

Key Infrastructure Decisions

Payment Link Strategy

We created two Stripe payment links rather than embedding a single checkout form:

  • Deposit Link ($1,560): https://buy.stripe.com/dRmdR29XnfJlfdC6A2fjG0f — for JADA charter deposits
  • Birthday Sail Link ($125): Separate price object for the recurring birthday event

Why two links? Stripe payment links are shareable, trackable URLs that include their own product/price metadata. This allows operators to send links directly to customers without accessing the Stripe dashboard, and enables tracking customer conversion paths independent of the dashboard sessions.

Both links point to products created via the Stripe API with clearly-scoped names (JADA Charter — $1,560.00 and Birthday Sail at Sunset Cliffs — $125.00) for easy recognition in payment records.

Event Site Deployment Pattern

Multiple event sites share the same deployment architecture but have distinct infrastructure:

Event Site Deployment Pattern:

Birthday Event (/queenofsandiego.com/rady-shell-events/sites/birthday/)
├── S3 Bucket: queenofsandiego.com
├── Path: /rady-shell-events/sites/birthday/index.html
├── CloudFront Distribution: birthday event's dedicated distribution
└── Invalidation: /rady-shell-events/sites/birthday/*

Birthday Afternoon (/queenofsandiego.com/rady-shell-events/sites/birthday-afternoon/)
├── S3 Bucket: queenofsandiego.com
├── Path: /rady-shell-events/sites/birthday-afternoon/index.html
├── CloudFront Distribution: separate distribution
└── Invalidation: /rady-shell-events/sites/birthday-afternoon/*

Gipsy Kings Concert (similar structure)
├── Hero image assets: /rady-shell-events/sites/gipsykings/images/
├── S3 Deploy: index.html + 3 new band photography assets
└── CloudFront Invalidation: /rady-shell-events/sites/gipsykings/*

Why separate CloudFront distributions per event? This allows independent cache invalidation and TTL policies. Concert events might need aggressive cache-busting (1-hour TTL) while evergreen birthday pages can use longer caches (24-hour TTL). Separate distributions also enable granular access logging and traffic analysis per event type.

Booking Flow Standardization

During this session, we standardized the two-step booking modal across all event pages. The modal progression is:

  1. Step 1: Capture date/time/guest count
  2. Step 2: Contact info + waivers (DocuSign redirect)
  3. Post-submission: Redirect to Stripe payment link

This required updates to:

  • /rady-shell-events/sites/birthday/index.html (4 edits to remove legacy flow)
  • /rady-shell-events/sites/birthday-afternoon/index.html (4 edits)
  • /rady-shell-events/sites/gipsykings/index.html (7 edits + new hero image assets)

Each file had legacy booking code paths removed and replaced with a single `handleBookingSubmit()` function that validates against the current Google Apps Script backend (Rady Shell GAS project, separate from the main booking engine).

Content Delivery & Caching Strategy

All event sites are deployed through the shared CloudFront distribution fronting queenofsandiego.com. Cache behaviors are configured as:

  • /rady-shell-events/sites/* — 1 hour TTL (event details change frequently)
  • /assets/* — 30 days TTL (images, stylesheets versioned in filename)
  • index.html — Cache-Control: no-cache (always validates with CloudFront edge, but uses ETag for