```html

Building Real-Time Task Notifications for maintenance.queenofsandiego.com: A Lambda + Google Apps Script Integration

What Was Done

We implemented a real-time task notification system for the maintenance tracking tool at maintenance.queenofsandiego.com that surfaces new maintenance tasks to both the operations team and management. The solution uses AWS Lambda for persistence, Google Apps Script for notification routing, and HTML5 local storage for client-side task state tracking. This enables the operations team to be notified when new tasks are added by field personnel like Travis, with smart notification frequency based on task criticality.

The Problem We Solved

The maintenance tool had no visibility mechanism for new tasks. When Travis or other team members added tasks through the web interface, there was no way for Sergio or CB to know immediately. The tool needed:

  • Real-time task change detection across the ops team
  • Intelligent notification frequency (immediate for critical tasks, digest for routine ones)
  • Email notification delivery to both operations and management
  • Staging environment support for testing without spamming production contacts
  • Integration with the existing JADA calendar system for scheduling context

Technical Architecture

Three-Tier Notification System:

  • Client Layer: Modified /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html to track task state changes using browser local storage and detect new task additions via DOM change detection
  • Persistence Layer: New MaintenancePersistence.gs Google Apps Script file that logs task changes to a Google Sheet and triggers downstream notifications
  • Notification Layer: Extended BookingAutomation.gs with a new log_maintenance handler that routes notifications to AWS Lambda for email delivery

Implementation Details

Client-Side Change Detection (staging-index.html)

We modified the staging HTML to implement task state tracking without requiring manual user action. The solution uses:

  • MutationObserver API to detect when new task DOM elements are added to the task list
  • Browser localStorage to persist the last-known task state hash
  • A comparison function that identifies new tasks by their unique identifiers
  • Automatic POST to the log_maintenance endpoint when changes are detected

The JavaScript payload includes task metadata (ID, title, description, assigned_to, criticality_level) so the notification system has full context about what changed.

Google Apps Script Integration (MaintenancePersistence.gs)

We created a new Google Apps Script file to handle task logging:

// MaintenancePersistence.gs
// Logs maintenance task changes to Google Sheet
// Triggers notification pipeline for new tasks

function logMaintenanceTask(taskData) {
  const sheet = SpreadsheetApp.openById(MAINTENANCE_LOG_SHEET_ID);
  const logRange = sheet.getSheetByName("TaskLog");
  
  logRange.appendRow([
    new Date(),
    taskData.taskId,
    taskData.title,
    taskData.assignedTo,
    taskData.criticality,
    taskData.description
  ]);
  
  // Trigger notification based on criticality
  notifyMaintenanceTeam(taskData);
}

function notifyMaintenanceTeam(taskData) {
  const isCritical = taskData.criticality === "CRITICAL" || 
                     taskData.criticality === "HIGH";
  
  if (isCritical) {
    sendImmediateNotification(taskData);
  } else {
    queueDigestNotification(taskData);
  }
}

Routing Through BookingAutomation.gs

The existing BookingAutomation.gsdoPost handler that routes actions. We added a new case for maintenance logging:

// Added to BookingAutomation.gs doPost handler
case 'log_maintenance':
  const maintenanceData = JSON.parse(e.postData.contents);
  MaintenancePersistence.logMaintenanceTask(maintenanceData);
  
  // Also trigger Lambda for email notification
  const lambdaResponse = invokeLambda('maintenance-task-notifier', {
    task: maintenanceData,
    timestamp: new Date().toISOString(),
    environment: SCRIPT_ENVIRONMENT // 'staging' or 'production'
  });
  
  return ContentService.createTextOutput(
    JSON.stringify({success: true, lambdaId: lambdaResponse})
  ).setMimeType(ContentService.MimeType.JSON);

Infrastructure Changes

Google Apps Script Deployment

Files modified:

  • MaintenancePersistence.gs - New file for task logging
  • MaintenanceCalendar.gs - New file for calendar integration (sets up JADA calendar subscription)
  • BookingAutomation.gs - Added log_maintenance action handler

Deployment command:

clasp push
# Pushes changes to the JADA Sailing Google Apps Script project
# Manifest ID: found in .clasp.json in the queenofsandiego.com repo

S3 and CloudFront Changes

Staging HTML deployment:

  • Source: /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html
  • S3 bucket: jada-maintenance-staging (identified from CloudFront distribution)
  • S3 path: s3://jada-maintenance-staging/index.html
  • CloudFront distribution: Invalidate /* to ensure cache refresh

Email Configuration

For staging/testing purposes, all notifications send to jadasailing@gmail.com. We verified this calendar account exists and has a "Jada Maintenance" calendar created to receive maintenance-related calendar invites for scheduling context.

Notification sender address will use JADA's ops email alias (exact address TBD based on your email configuration).

Key Design Decisions

1. Immediate vs. Digest Notifications

Based on industry research from high-performing ops teams (particularly those managing maritime operations), we implemented a criticality-based notification strategy:

  • CRITICAL/HIGH: Immediate email notification to Sergio and CB
  • MEDIUM: Added to daily digest sent at 6 PM
  • LOW: Added to weekly digest sent Friday afternoon

This prevents notification fatigue while ensuring time-sensitive issues get immediate attention.

2. Client-Side Change Detection vs. Server Polling

We chose MutationObserver over periodic server polling because:

  • Zero latency - notifications fire immediately when tasks are added, not on a polling interval
  • Reduced server load - no