Building a Unified Ops Dashboard: Consolidating Payment Processing, Site Management, and Infrastructure Tooling
Over the past development session, we transformed https://ops.queenofsandiego.com from a basic landing page into a comprehensive operations hub—centralizing payment links, site deployments, and infrastructure management. This post details the technical decisions, architecture patterns, and implementation specifics that enabled this consolidation.
What Was Done
The ops page now serves as a single source of truth for JADA Charters operations:
- Payments section with live Stripe deposit links, Zelle banking details, and payment history tracking
- Public Sites section linking to all customer-facing properties with deployment status
- External Platforms section expanded to include communication and document management tools
- Infrastructure tooling organized by AWS service (S3, CloudFront, DynamoDB, Lambda/GAS)
- Updated deployment workflow with corrected Google Sheets references
Technical Details: File Structure and Deployment
The ops page lives in version control at:
/Users/cb/Documents/repos/sites/ops/index.html
This single HTML file is the source of truth. It's deployed to an S3 bucket named ops.queenofsandiego.com and served through a CloudFront distribution, which invalidates on each deployment to ensure cache freshness.
The deployment command structure:
# Deploy to S3 bucket
aws s3 cp /Users/cb/Documents/repos/sites/ops/index.html s3://ops.queenofsandiego.com/index.html
# Invalidate CloudFront cache for the distribution
aws cloudfront create-invalidation --distribution-id [DIST_ID] --paths "/*"
Why this approach: Static HTML deployment via S3+CloudFront eliminates server-side dependencies while providing global edge caching and instant invalidation. The ops page is internal-only tooling, so we prioritize deployment speed and reliability over dynamic features.
Payments Integration: Stripe Product Architecture
We created a Stripe product specifically for JADA charter deposits:
- Product Name: "JADA Charter — $1,560.00"
- Price: $156,000 cents ($1,560.00 USD)
- Payment Link: https://buy.stripe.com/dRmdR29XnfJlfdC6A2fjG0f
This price object was created via the Stripe API (credentials stored in /repos.env) and linked to a payment page for charter deposits. The decision to use Stripe payment links over embedded checkout forms reflects our need for:
- Mobile-friendly, link-shareable payment flows
- Automatic receipt and invoice generation
- Webhook integration with booking confirmations
- No frontend state management for payment processing
Alongside Stripe, we documented Zelle banking details (Sail JADA Charters LLC / 619-986-7344) as an alternative payment method for clients preferring ACH transfers.
Infrastructure Organization: Service-Based Categorization
The ops page reorganizes all tooling by infrastructure provider and purpose:
AWS Services
- S3 Buckets: Links to
queenofsandiego.combucket for site content,jada-images-prodfor photo assets - CloudFront: Distribution ID references for cache invalidation after deployments
- DynamoDB:
jada-crew-dispatchtable for crew scheduling and real-time status updates
Compute & Automation
- Google Apps Script (GAS): Two separate script projects:
- Booking engine (processes charter requests)
- Rady Shell project (separate business unit automation)
- Google Sheets: Port submission sheet (corrected sheet ID:
1jUxYXS24VS-D9tO37ckNqMNclvOBqQuh)
External Platforms
- DocuSign: Waiver and contract signing
- ImprovMX: Email aliasing (e.g., bookings@queenofsandiego.com forwarding)
- Google Business Profile: Local SEO and booking integration
- Instagram @sailjada: Social media and marketing content
Key Decisions and Rationale
1. Correcting the Port Sheet Reference
During this work, we discovered the Port Sheet link was pointing to an outdated Google Sheets ID. The correct sheet for Sheraton port submissions is 1jUxYXS24VS-D9tO37ckNqMNclvOBqQuh. This was documented in ACTIVE.md but not reflected on the ops page, creating a single point of failure if someone used the old link.
Why this matters: Stale infrastructure references compound over time—operators use outdated sheets, data diverges, and manual reconciliation becomes necessary. By centralizing and validating all links, the ops page now serves as a living audit trail.
2. Separating GAS Projects by Business Unit
We distinguish between the main booking engine GAS project and the Rady Shell automation project. These have separate script IDs and run independently, reducing blast radius if one project encounters errors.
3. HTML-Based Dashboard Over Database-Backed Alternative
Rather than building a dynamic dashboard backed by a database, we chose static HTML. This decision reflects:
- Minimal latency for operations staff (no database queries, pure edge caching)
- Version control for all changes (ops page changes are auditable in Git)
- Reduced attack surface (no backend API, no database credentials on the server)
- Easy link management—operators can update links during incident response without code deployment
Email Communication Pattern: SES + SMTP
During this session, we also sent transactional emails via Amazon SES SMTP from bookings@queenofsandiego.com. The pattern used:
# SMTP connection details (credentials in .env)
Host: email-smtp.[region].amazonaws.com
Port: 587
From: bookings@queenofsandiego.com
Emails were formatted as polished HTML with embedded images from S3 JADA image buckets, providing professional confirmation and branding for charter deposits. SES was chosen over simpler solutions because:
- High deliverability for time-sensitive booking confirmations
- Built-in bounce and complaint tracking
- Integration with SNS for webhook notifications
What's Next
The ops page is