Building HELM: An Interactive Operations Graph for Real-Time System Visibility

Over the past development session, we built HELM — a single-page, self-contained HTML5 application that visualizes the entire JADA booking and operations workflow as an interactive force-directed graph. HELM runs on helm.queenofsandiego.com and serves as a drill-down dashboard for engineers, ops staff, and stakeholders to understand data flow, money flow, booking paths, and real-time system health across multiple platforms and internal services.

What We Built

HELM is a complete visualization of:

  • Traffic sources: email campaigns, organic web search, referral partner codes, and direct traffic
  • Revenue platforms: Viator, Boatsetter, GetMyBoat, and internal booking channels (with greyed-out nodes for planned platforms)
  • Operational systems: crew dispatch, scheduling, email automation, payment processing, and client communication
  • System dashboards: each internal tool (expense tracker, crew dispatch, booking engine) appears as a node with drill-down capability
  • Real-time health: nodes glow green/red based on live probes; a system health bar aggregates status across all services

The entire application is a single HTML file (/Users/cb/Documents/repos/sites/helm/index.html) with embedded CSS and JavaScript, using the vis-network library for force-directed physics simulation and interactive graph rendering.

Technical Architecture

Graph Structure & Data Model

We defined two core data structures:

  • NODE_DATA: an object mapping node IDs to metadata (category, label, description, and associated GAS function signatures for drill-down)
  • EDGE_DATA: an array of [source, target, label] tuples representing data or money flow between systems

Nodes are organized into categories: SOURCE (traffic), PLATFORM (booking channels), PAYMENT, OPS (internal systems), and DASHBOARD. Each category has a distinct color; inactive platforms are greyed out.

Example node definition:


gas_crewdispatch: {
  category: 'OPS',
  label: 'Crew Dispatch',
  description: 'Real-time crew scheduling and assignment',
  functions: ['dispatchCrew', 'assignPerson', 'updateCrewHealth']
}

Real-Time Health Diagnostics

A polling loop (interval: 30 seconds) calls live health-check GAS endpoints for each system node. Response codes determine node color:

  • Green: HTTP 200, system healthy
  • Yellow: HTTP 200 but warnings in response
  • Red: HTTP 500+ or timeout, system down

The System Health Bar at the top of the page aggregates these statuses: percentage green × node count, with a color gradient from red to amber to green.

Drill-Down Detail Panel

Clicking a node opens a side panel showing:

  • Node description
  • Current health status and last check timestamp
  • Linked GAS function signatures (extracted from the crew dispatch, expense tracker, and booking engine Google Apps Script projects)
  • Quick links to relevant dashboards or logs

This lets engineers understand what a system does and which functions power it without leaving the visualization.

Infrastructure & Deployment

S3 & CloudFront Setup

We created a new S3 bucket to host the static HTML:


Bucket name: helm.queenofsandiego.com
Region: us-west-2
Versioning: enabled
Block public access: enabled (all)

The bucket policy grants CloudFront an Origin Access Control (OAC) to fetch objects without public read permissions:


Principal: CloudFront Distribution ID (via OAC)
Effect: Allow
Action: s3:GetObject
Resource: arn:aws:s3:::helm.queenofsandiego.com/*

We created a CloudFront distribution (OAC-authenticated, no public bucket policy) with:

  • Origin: helm.queenofsandiego.com S3 bucket
  • Default root object: index.html
  • Cache behavior: TTL 300 seconds (5 min), with cache invalidation on deploy
  • Viewer protocol policy: HTTPS only
  • Compression: enabled (gzip)

DNS & SSL

Route53 ALIAS record created:


Name: helm.queenofsandiego.com
Type: A (IPv4)
Alias target: CloudFront distribution domain name
Evaluate target health: false

SSL certificate already existed in ACM for *.queenofsandiego.com, so no new cert was needed.

Key Technical Decisions

Single-File HTML vs. Modular Build

We chose a single-file approach because:

  • Deployment simplicity: one S3 upload, one cache invalidation
  • No external dependencies: only vis-network from CDN (fallback to local embed if needed)
  • Offline capability: could be downloaded and opened locally for offline review
  • Fast iteration: dev edits and redeploy in seconds via S3 CLI + CloudFront invalidation

Force-Directed Physics Over Hierarchical Layout

We used vis-network's force-directed simulation instead of a DAG or hierarchical layout because:

  • Money and data flow are bidirectional and complex; a rigid hierarchy wouldn't reflect reality
  • Force-directed layouts naturally cluster related nodes (ops systems together, platforms together)
  • Interactive dragging and pan/zoom keep exploration intuitive and fun
  • Physics simulation is CPU-efficient for ~40–50 nodes on modern hardware

Embedded GAS Function Signatures Over Live Introspection

Rather than calling Google Apps Script API to fetch function definitions at runtime, we extracted function signatures once and embedded them in the HTML:

  • No runtime dependency on GAS API availability
  • Faster drill-down response (instant UI render)
  • Handoff: a developer's task to re-extract signatures when GAS code changes (documented in /