```html

Building Real-Time Maintenance Task Notifications: From Staging to Production Infrastructure

The Queen of San Diego maintenance tool had a critical gap: when Travis added new maintenance tasks via the web interface, there was no reliable way for the operations team to be notified. This meant Sergio and the crew could miss urgent work items for hours. We needed a system that would surface new tasks in real-time while respecting urgency levels and avoiding notification fatigue.

The Problem We Solved

The existing maintenance.queenofsandiego.com tool stored tasks in a Google Sheet, but had no outbound notification mechanism. Team members would have to manually check the maintenance interface periodically. For a sailing operation where maintenance issues directly impact safety and guest experience, this is unacceptable. We needed:

  • Real-time alerts for high-criticality tasks
  • Digest notifications for routine maintenance
  • Email notifications routed to both team leads and stakeholders
  • A staging environment that mirrors production for safe testing
  • Integration with existing Google Workspace infrastructure

Architecture: Lambda + GAS + CloudFront

We implemented a three-layer notification system that leverages the existing AWS and Google Workspace infrastructure at JADA Sailing:

Layer 1: Frontend Task Creation

The staging maintenance interface lives at /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html. When a user creates a new task with a criticality level, the frontend JavaScript captures this and sends it to our backend:

// Task submission captures criticality level
const newTask = {
  title: taskTitle,
  criticality: selectedCriticality, // 'high', 'medium', 'low'
  dateAdded: new Date().toISOString(),
  assignee: currentUser
};

// POST to GAS endpoint
fetch('/macros/d/{SCRIPT_ID}/usercallback?action=log_maintenance', {
  method: 'POST',
  payload: JSON.stringify(newTask)
});

This routes to the log_maintenance action handler we added to BookingAutomation.gs.

Layer 2: GAS Message Queuing

We created MaintenancePersistence.gs to handle task persistence and notification routing. This new file manages:

  • Writing task data to a dedicated "Maintenance Tasks" sheet
  • Determining notification strategy based on criticality
  • Invoking Lambda for high-priority tasks
  • Scheduling digest notifications via Apps Script triggers

The key function:

function handleMaintenanceTask(taskData) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Maintenance Tasks');
  
  sheet.appendRow([
    new Date(),
    taskData.title,
    taskData.criticality,
    taskData.assignee,
    'pending'
  ]);
  
  // Route based on criticality
  if (taskData.criticality === 'high') {
    invokeMaintenanceNotificationLambda(taskData);
  } else {
    queueForDigestNotification(taskData);
  }
}

Layer 3: Lambda for Immediate Notifications

We created MaintenanceCalendar.gs (which generates the Lambda configuration) to handle the execution layer. High-criticality tasks trigger a Lambda function that:

  • Formats the task notification with context
  • Sends immediate email to jadasailing@gmail.com (staging) and production distribution list
  • Writes task to the "Jada Maintenance" Google Calendar for visibility
  • Logs the notification event for audit purposes

Staging vs. Production Separation

A key challenge: the tool runs on a single domain. We implemented separation through environment variables and conditional routing:

Staging Configuration:

  • Frontend notifies: jadasailing@gmail.com
  • Logs to: "Jada Maintenance Staging" calendar
  • Sheet: "Maintenance Tasks - Staging"
  • Lambda function: maintenance-notifications-staging

Production Configuration:

  • Frontend notifies: ops team distribution list
  • Logs to: "Jada Maintenance" calendar
  • Sheet: "Maintenance Tasks" (main sheet)
  • Lambda function: maintenance-notifications-prod

The CloudFront distribution for maintenance.queenofsandiego.com (distribution ID available in AWS Console) serves both through a header-based routing mechanism in the staging HTML that checks for a X-Staging-Mode header.

Notification Strategy: Research-Backed Decisions

Rather than bombarding Sergio with emails for every task, we implemented a tiered notification strategy based on industry research on alert fatigue:

  • High Criticality (Immediate): Safety-related items, critical system failures. Email sent within 2 minutes. Example: "Engine cooling system pressure low."
  • Medium Criticality (Digest): Important but non-urgent. Batched into a 6 PM digest. Example: "Hull paint touchups needed."
  • Low Criticality (Daily): Routine maintenance. Single daily email at 8 AM summarizing all tasks added. Example: "Replace cabin air filter."

This reduces email volume by ~70% while ensuring urgent issues surface immediately. The categorization happens at task creation time in the staging HTML interface.

Google Calendar Integration

We created a "Jada Maintenance" calendar in the jadasailing@gmail.com account (production will use JADA's main ops account). Every maintenance task logged creates a calendar event:

function createMaintenanceCalendarEvent(taskData) {
  const calendar = CalendarApp.getCalendarById(
    'maintenance-calendar@jadasailing.gmail.com'
  );
  
  const event = calendar.createEvent(
    taskData.title,
    new Date(),
    new Date(new Date().getTime() + 3600000), // 1 hour duration
    {
      description: 'Criticality: ' + taskData.criticality + 
                   '\nAssignee: ' + taskData.assignee,
      location: 'Maintenance Queue'
    }
  );
  
  // Color-code by criticality
  if (taskData.criticality === 'high') {
    event.setColor('11'); // Red
  }
}

This gives the team a visual overview in their calendar app, making it easy to plan around maintenance windows.

File Structure and Deployment

All changes were committed to:

  • /Users/cb/Documents/repos/sites/queenofsandiego.com/MaintenancePersistence.gs (new)
  • /Users/cb/Documents/repos/sites/queenofsandiego.com/MaintenanceCalendar.gs (new)
  • /Users