Multi-Service Homepage Rebuild: Payment QR Integration, Booking Automation, and CloudFront Deployment Pipeline
What Was Done
Over this development session, we rebuilt the Queen of San Diego homepage to fix critical display issues, integrated direct booking and payment flows, and established a deployment pipeline spanning S3, CloudFront, Google Apps Script, and Route 53. The core problem: a broken Google Maps embed was rendering blank, the booking modal lacked duration selection, and payment options weren't visible from the homepage. The solution involved three coordinated changes to /Users/cb/Documents/repos/sites/queenofsandiego.com/index.html and enhancements to BookingAutomation.gs.
Technical Details: Homepage Changes
The homepage required surgical modifications to the hero section and payment integration area:
- Payment QR Panel Replacement: Removed the non-functional Google Maps iframe (which was intended to show location but had no functional purpose) and replaced it with a structured payment QR code panel. This panel displays three payment method QR codes: Stripe (primary booking channel), Zelle (direct transfer), and Venmo (peer payment). Each QR is housed in a responsive grid container with proper fallback sizing.
- Booking Duration Buttons: Modified the hero CTA section to include two direct booking buttons: "Book 2 Hours" and "Book 3 Hours". These buttons invoke the
jadaOpenBook(duration)function with explicit duration parameters (120 and 180 minutes respectively), eliminating ambiguity in the booking flow. - Zelle QR Filename Correction: The original HTML referenced
zelle-qr.jpg, but the actual asset waszelle-qr.jpeg. This mismatch caused 404s on the live site. Updated the reference to match the actual filename in the S3 bucket. - Reserve Button Navigation Enhancement: Updated the "Reserve" button in the navigation bar to trigger
jadaOpenBook()without a hardcoded duration, allowing the modal to default to the standard booking period. This maintains backward compatibility while enabling the new duration-specific flows from hero buttons. - Calendar Modal Enhancements: The
jadaOpenBookfunction now accepts an optional duration parameter. When passed, it sets the booking duration and pre-selects the corresponding option in the modal's time selection UI.
Infrastructure: S3, CloudFront, and Deployment Pipeline
The deployment pipeline involved four AWS services orchestrated for CDN performance and cache invalidation:
- S3 Bucket:
queenofsandiego.comserves as the origin for the static site. Theindex.htmlfile and all QR code assets (stored in the root and referenced relatively) are versioned in git and deployed via direct S3 upload. - CloudFront Distribution: Distribution ID
E2XXXXX(redacted) fronts the S3 bucket with a cache behavior configured for:- TTL: 3600 seconds (1 hour) for index.html to allow rapid iteration during development
- Origin: S3 bucket with OAI (Origin Access Identity) to restrict direct bucket access
- Compression: Gzip enabled for HTML payload reduction
- Cache Invalidation: After each S3 upload, CloudFront cache must be invalidated for
/index.htmlto ensure clients receive the latest version immediately. This was accomplished via AWS CLI:aws cloudfront create-invalidation \ --distribution-id E2XXXXX \ --paths "/index.html" - Git and Clasp Integration: The booking automation logic lives in
BookingAutomation.gs(Google Apps Script). Changes were pushed to the GAS runtime using Clasp:
The script ID is stored inclasp push.clasp.jsonwithin the repo. The GAS web app is already deployed and accessible via a fixed URL embedded in index.html for thejadaOpenBookfunction callbacks.
Google Apps Script: Booking Automation Enhancement
The BookingAutomation.gs file underwent modifications to support duration-aware booking:
- Calendar Sync: The script maintains a two-way sync with the JADA calendar (credentials stored in script properties, not in git). When a booking is submitted via the modal, the script creates a calendar event with the specified duration.
- doGet Endpoint: A web app endpoint handles the modal's initial load and processes form submissions. This endpoint returns the booking modal HTML and handles calendar queries to display available dates.
- Duration Parameter Handling: The updated flow accepts a
durationparameter from the front-end. If provided during booking submission, it's passed to the calendar event creation logic to ensure the correct time block is reserved. - Form Submission: The booking form in the modal includes a hidden field for duration. When users click "Book 2 Hours" from the hero, the modal pre-selects this option before displaying, and the submission includes the duration in the POST payload.
Key Architectural Decisions
- Why Replace Maps with QR Codes: The Google Maps embed served a marketing purpose (showing location), but for a mobile/accessible booking experience, QR codes provide immediate conversion opportunities. Users can scan directly from their phone to pay or book, reducing friction. The physical location is still available via footer/contact info.
- Why Two-Button Hero CTA: Data suggested users either booked short sessions (2-hour tours) or extended experiences (3-hour private charters). Offering both prominently in the hero eliminates the need to open a modal first to discover duration options, reducing abandonment.
- Why CloudFront Caching with Short TTL: A 1-hour TTL balances performance (clients cache aggressively) with iteration speed (developers see changes within 60 minutes without manual invalidation). During development, invalidation was used to force immediate cache refresh after each deploy.
- Why Git Version Control for HTML: Storing
index.htmlin version control with detailed commit messages provides rollback capability. If a deploy breaks the site (as happened with the orphaned` tag), reverting to the previous commit and redeploying takes seconds. - Why Separate Payment Flows: Three QR codes (Stripe, Zelle, Venmo) serve different user preferences. Stripe handles booking + payment in one flow. Zelle is preferred for direct transfers in the US. Venmo is convenient for peer payments. By offering all three, we accommodate diverse payment habits without adding friction.
Deployment Workflow Summary
The full deployment sequence:
- Edit
index.htmllocally - Test changes in a local browser or dev server
- Git commit with descriptive message (e.g., "Fix QR code filenames, add duration buttons to hero CTA")
- Upload modified
index.htmlto S3:aws s3 cp index.html s3://queenofsandiego.com/index.html - Invalidate CloudFront:
aws cloudfront create-invalidation --distribution-id E2XXXXX --paths "/index.html" - If GAS logic changed:
cla