Multi-Domain Booking Platform Deployment: Integrating Payment QR Codes, CloudFront Caching, and Basic Auth for Financial Tools
This session involved rebuilding the Queen of San Diego booking platform's homepage, establishing a private financial calculator subdomain with basic authentication, and orchestrating a multi-distribution CloudFront deployment strategy. The work required coordinating HTML modifications, Google Apps Script endpoints, S3 bucket policies, ACM certificate validation, and cache invalidation across three separate CloudFront distributions.
Primary Objective: Fixing Homepage Layout and Payment Integration
The Queen of San Diego homepage at queenofsandiego.com/index.html had a critical rendering issue: an orphaned closing </style> tag at line 3090 with no corresponding opening tag, causing CSS cascade failures. Simultaneously, a broken Google Maps embed was occupying valuable hero real estate.
The fix involved three coordinated changes:
- Remove broken Google Maps iframe and replace with a payment QR code panel displaying Stripe, Zelle, and Venmo payment options
- Add direct booking buttons for 2-hour and 3-hour charter durations in the hero CTA section, eliminating the friction of calendar navigation for common booking types
- Fix asset filename reference from
zelle-qr.jpgtozelle-qr.jpegto match actual file in the repository
The CSS fix involved locating all opening <style> tags to understand the intended structure, then removing the orphaned closing tag. This restored proper cascade behavior and unblocked the visual layout.
Booking Modal Enhancement: Duration-Aware Calendar
The existing jadaOpenBook() function in the GAS deployment needed modification to accept a duration parameter. This function is invoked when users click the Reserve button in the navigation or duration-specific buttons in the hero section.
Original invocation:
jadaOpenBook()
Updated to support duration presets:
jadaOpenBook(120) // 2-hour charter
jadaOpenBook(180) // 3-hour charter
The function signature in BookingAutomation.gs was expanded to pass duration context to the calendar selection flow, reducing decision fatigue for the most common booking scenarios.
Infrastructure: Private Financial Dashboard with Basic Authentication
A new subdomain pnl.queenofsandiego.com was created to serve a private P&L (profit and loss) calculator, inaccessible to the public but available to authorized team members.
S3 Bucket Creation and Configuration
A private S3 bucket was created to store the P&L calculator HTML. Unlike the public queenofsandiego.com S3 bucket, this bucket had:
- All public access blocked via bucket policies
- Access exclusively through CloudFront with Origin Access Control (OAC)
- No direct S3 URL accessibility
The P&L HTML file was uploaded as index.html to the bucket root, following the pattern used for the main site and ops tooling.
TLS Certificate and DNS Configuration
An AWS Certificate Manager (ACM) certificate was requested for pnl.queenofsandiego.com using DNS validation. The validation CNAME record was added to Route 53 in the queenofsandiego.com hosted zone. ACM validation completed within 2-3 minutes of CNAME propagation, confirming Route 53 was the authoritative DNS provider.
CloudFront Function for Basic Authentication
Rather than implementing authentication at the application layer or using Lambda@Edge, a CloudFront Function was created to enforce HTTP Basic Authentication at the edge. The function:
- Intercepts all requests to the distribution
- Extracts the
Authorizationheader - Compares the base64-encoded credentials against known valid values
- Returns 401 Unauthorized for missing or invalid credentials
- Allows authenticated requests through to the origin (S3)
CloudFront Functions are ideal here because they execute at the edge (sub-millisecond latency), cost-effectively scale to handle authentication at global PoPs, and don't require Lambda provisioning overhead. The function was published to the LIVE stage after testing in the development environment.
Origin Access Control Setup
An OAC resource was created for the pnl S3 bucket. CloudFront uses OAC (the successor to Origin Access Identity, or OAI) to securely identify itself when requesting objects from S3. The bucket policy was configured with an explicit deny for all public access, followed by an allow for requests originating from the OAC principal:
Principal: {"Service": "cloudfront.amazonaws.com"}
Condition: {"StringEquals": {"AWS:SourceArn": "arn:aws:cloudfront::ACCOUNT_ID:distribution/DISTRIBUTION_ID"}}
This ensures the S3 bucket is completely inaccessible except through the CloudFront distribution.
CloudFront Distribution Creation
A new CloudFront distribution was created with:
- Origin: pnl S3 bucket with OAC
- Viewer protocol policy: Redirect HTTP to HTTPS
- Cache behavior: Compress enabled, TTL set to 300 seconds (5 minutes) for rapid iteration
- Alternate domain names (CNAME):
pnl.queenofsandiego.com - Certificate: ACM cert created above
- Function associations: CloudFront Function on viewer request
Route 53 A and AAAA records were created in the queenofsandiego.com hosted zone, aliasing to the CloudFront distribution domain. This unified DNS management under a single hosted zone.
Multi-Distribution Cache Management
The deployment involved three CloudFront distributions:
- queenofsandiego.com (main booking site) — invalidated for
/index.html - ops.queenofsandiego.com (internal operations tools) — invalidated for
/index.html - helm.queenofsandiego.com (hierarchical tool navigation) — invalidated for
/index.html - pnl.queenofsandiego.com (financial calculator) — invalidated for
/index.html
Cache invalidations were performed immediately after S3 uploads to ensure edge nodes serving stale content were purged. CloudFront invalidation requests were issued for exact paths rather than wildcard patterns to minimize API costs and maintain precision.
Google Apps Script Deployment Updates
The GAS web app deployment for BookingAutomation.gs was updated to add a new booked_dates endpoint alongside the existing booking functionality. The GAS script ID (retrieved from .clasp.json) was used to identify the correct deployment, and clasp push deployed code changes. The deployment was redeployed as a new version to ensure the web app URL reflected the latest code