Multi-Layer Booking Platform Overhaul: Homepage UI, Payment Integration, and Infrastructure Hardening
What Was Done
This session involved a comprehensive update to the Queen of San Diego booking platform, spanning three critical areas: fixing broken UI components on the homepage, integrating multiple payment collection methods, and establishing secure infrastructure for financial reporting dashboards.
The work touched four distinct systems:
- Frontend:
/Users/cb/Documents/repos/sites/queenofsandiego.com/index.html— hero section, booking modals, and payment QR integration - Backend automation:
BookingAutomation.gs(Google Apps Script) — calendar sync and booking state management - Infrastructure: CloudFront distributions, S3 buckets, Route53 DNS, ACM certificates, and OAC-based access control
- Operational dashboards: Secured P&L calculator, ops portal, and HELM tool aggregation
Technical Details: Frontend Changes
The homepage had accumulated several rendering issues requiring surgical fixes:
1. Google Maps Embed Replacement
A broken Google Maps iframe was replaced with a payment collection panel containing QR codes for three payment methods: Stripe, Zelle, and Venmo. This serves as both a visual anchor and functional call-to-action.
Rather than embedding an external map (which added dependency weight and often failed in preview scenarios), the QR codes provide direct, scannable payment paths. The panel is positioned in the hero section where the map previously occupied DOM real estate, maintaining visual balance.
2. Booking Modal Duration Parameters
The jadaOpenBook() function was extended to accept duration parameters (2 hours vs. 3 hours). The hero CTA now includes two distinct buttons:
<button onclick="jadaOpenBook(120)">2 Hour Booking</button>
<button onclick="jadaOpenBook(180)">3 Hour Booking</button>
This allows users to select booking length before the calendar picker opens, simplifying the booking flow and reducing modal complexity.
3. File Reference Corrections
Updated image references from zelle-qr.jpg to zelle-qr.jpeg to match actual file names in the asset directory. This prevented 404 errors that were breaking the payment QR panel rendering.
Updated the navigation Reserve button to trigger jadaOpenBook() with a default 2-hour parameter, ensuring consistent booking entry points across the page.
Technical Details: Backend Automation
The BookingAutomation.gs script (Google Apps Script) required updates to expose a booked_dates endpoint alongside the existing calendar integration.
This endpoint allows the frontend calendar picker to fetch already-booked dates without requiring the user to authenticate to Google Calendar directly. The GAS deployment was updated to include this new endpoint in the published web app.
Deployment ID was retrieved via clasp list, and the web app redeployment was triggered to make the new endpoint accessible at the previously-configured GAS URL.
Infrastructure: Secure Dashboard Layer
A new security perimeter was established for the P&L calculator and operational dashboards:
S3 Buckets Created/Modified
pnl.queenofsandiego.com— Private bucket (no public access) for the P&L calculatorops.queenofsandiego.com— Updated with HELM integration for tool aggregationhelm.queenofsandiego.com— Updated with ledger/financial tools in ROOT_NODES array
CloudFront Distributions
Created a new CloudFront distribution for pnl.queenofsandiego.com with the following architecture:
- Origin Access Control (OAC): Replaced legacy Origin Access Identity (OAI) for more granular S3 bucket access
- CloudFront Function: Basic authentication enforced at edge, checking credentials before S3 origin fetch
- Function Stage: Published to LIVE stage for production traffic
The OAC-only bucket policy ensures that S3 access is restricted to the CloudFront distribution. Direct S3 URL access is denied:
aws s3api put-bucket-policy \
--bucket pnl.queenofsandiego.com \
--policy file://policy.json
The bucket policy contains the CloudFront distribution ARN and OAC principal, blocking all other sources.
SSL/TLS and DNS
An ACM certificate was requested for pnl.queenofsandiego.com via the AWS Certificate Manager console. DNS validation required adding a CNAME record to Route53:
aws route53 change-resource-record-sets \
--hosted-zone-id Z<ZONE_ID> \
--change-batch file://validation-cname.json
Once validated (polled every 30 seconds up to 6 minutes), the certificate was attached to the CloudFront distribution.
Two Route53 A/AAAA alias records were created pointing pnl.queenofsandiego.com to the CloudFront distribution's domain name.
Authentication Layer
Basic authentication credentials were Base64-encoded and embedded in a CloudFront Function. The function intercepts all requests to pnl.queenofsandiego.com:
- If the Authorization header is absent or invalid, returns 401 Unauthorized
- If valid, allows the request to proceed to the S3 origin
- Credentials are stored in
repos.envfor reference, with the encoded version deployed to CloudFront
This approach provides edge-computed security without requiring Lambda@Edge complexity.
Cache Invalidation and Deployment
After each set of changes, CloudFront caches were invalidated:
aws cloudfront create-invalidation \
--distribution-id E<DIST_ID> \
--paths "/*"
Three distributions were updated: the main queenofsandiego.com site, ops.queenofsandiego.com, and helm.queenofsandiego.com.
Files were deployed to their respective S3 buckets:
aws s3 cp index.html s3://queenofsandiego.com/
aws s3 cp ops-index.html s3://ops.queenofsandiego.com/index.html
aws s3 cp helm-index.html s3://helm.queenofsandiego.com/index.html
Key Decisions
- OAC over OAI: OAC provides better security semantics and is the AWS-recommended approach for new CloudFront distributions accessing S3.
- CloudFront Function over Lambda@Edge: Faster execution (no cold starts), lower latency, and sufficient for basic auth logic without custom response transformation.