Building HELM: A Real-Time Operations Visualization Dashboard for JADA's Multi-Platform Booking Ecosystem
Last week, we deployed HELM (JADA's interactive operations map) to production at helm.queenofsandiego.com. HELM is a self-contained, force-directed graph visualization that maps the entire customer journey—from email campaigns and web search through to crew dispatch and per-sail operations—with live health diagnostics and drill-down detail panels. This post covers the architecture, deployment strategy, and key technical decisions.
What Problem Does HELM Solve?
JADA operates across multiple revenue channels (Viator, Boatsetter, GetMyBoat, organic web traffic, referral partners), integrates with Google Apps Script backends for crew dispatch and booking management, and manages complex per-sail operations. Until now, there was no single visual reference for how these systems connect, what's live vs. planned, and how money/customers flow through the platform. HELM unifies that view.
Architecture: Why vis-network + Self-Contained HTML?
We chose a self-contained HTML5 file deployed as a static asset rather than a traditional SPA framework for several reasons:
- Zero backend dependency: HELM can load and function without any microservice. Function signatures and node metadata are embedded as JavaScript objects in the HTML, reducing latency and failure modes.
- Force-directed physics (vis-network): The library provides stable node repulsion, edge tension, and interactive pan/zoom out of the box. No need to build custom layout logic.
- Easy deployment: One file to S3, one CloudFront invalidation, done. No build pipeline, no dependency tree bloat.
- Security posture: Static assets can't be exploited via injection or deserialization attacks. The health probe logic is read-only against Google Sheets.
The trade-off is file size (~120KB gzipped) and slightly longer initial parse time, but acceptable for a reference tool used by 3–5 engineers per day.
Core Data Model and Node Types
HELM defines nodes in a NODE_DATA object that captures four layers:
- Acquisition: email_campaigns, web_search, referral_partners, social_media
- Booking Platform: viator, boatsetter, getmyboat, organic_web (with grey nodes for planned platforms like airbnb_experiences)
- Operations & Fulfillment: gas_crewdispatch, gas_booking_manager, gas_health_check, notifications (Twilio, SendGrid)
- Dashboards & Reporting: tableau_bookings, tableau_ops, google_sheets_master
Each node carries metadata: label, category, description, and a reference to a GAS function (if applicable). For example:
{
id: 'gas_crewdispatch',
label: 'Crew Dispatch',
category: 'operations',
description: 'Google Apps Script: crew assignment + SMS/email notifications',
gas_function: 'dispatchCrewForSail',
status: 'live'
}
Edges represent data flow or dependencies. An edge from viator to gas_booking_manager means: "Viator bookings flow into the booking manager for processing."
Health Diagnostics: Live Probes and Color Coding
A unique feature of HELM is real-time health feedback. The system polls a Google Sheet (sourced from the gas_health_check function) every 30 seconds to determine node status. Nodes render as:
- Green: Last health check passed within SLA (typically <5 min)
- Yellow: Last check was 5–15 min ago (degraded)
- Red: Last check >15 min ago or explicit failure flag (down)
- Grey: Planned or not yet live
A system health bar at the top aggregates the percentage of green nodes. This gives engineers an at-a-glance view: "Is the platform healthy right now?"
Infrastructure: S3, CloudFront, Route53
We deployed HELM using AWS infrastructure aligned with JADA's existing setup for queenofsandiego.com:
- S3 Bucket:
helm-queenofsandiego-com(region: us-west-2, versioning enabled for rollback) - Upload:
/index.html(the main file, ~120KB) - CloudFront Distribution: OAC (Origin Access Control) to restrict bucket access to CloudFront only; no public bucket policy needed
- Route53: ALIAS record pointing
helm.queenofsandiego.comto the CloudFront domain name
The CloudFront distribution includes a cache behavior for /index.html with a 1-hour TTL and automatic cache invalidation on each deploy. This balances freshness (health statuses update relatively quickly) with cache efficiency.
Deployment Workflow
We automated the deploy process:
# 1. Validate HTML/JS syntax locally
node --check helm/index.html
# 2. Upload to S3
aws s3 cp helm/index.html s3://helm-queenofsandiego-com/index.html --content-type text/html
# 3. Invalidate CloudFront cache
aws cloudfront create-invalidation --distribution-id E2ABC123XYZ --paths "/*"
# 4. Poll distribution status and smoke test
curl https://helm.queenofsandiego.com
This sequence ensures that new versions are live within ~90 seconds (CloudFront invalidation + edge propagation).
Drill-Down Detail Panel
When a user clicks a node, HELM displays a detail panel with:
- Full node description
- List of GAS functions (extracted via introspection of the Apps Script project files)
- Incoming and outgoing edges (dependencies)
- Last health check timestamp and result
This turns HELM into a lightweight documentation tool, eliminating the need to hunt through spreadsheets or wikis to find which function handles crew dispatch, for example.
Key Technical Decisions Explained
- Dark navy + gold color scheme: Professional, yacht-industry-aligned branding. Reduces eye strain for extended viewing.
- Physics-based layout: Rather than a fixed tree or circular layout, we let nodes repel each other and edges pull them together. This creates an intuitive, organic map that's easier to visually scan.
- Google Sheets for health data: JADA already logs events to Sheets. Polling a designated health sheet avoids spinning up a separate database or API.
- No authentication layer (for now): HELM is internal-only (access gated at DNS/firewall level). If we needed public access, we'd add OAuth2 via AWS Cognito.