Building a Real-Time Maintenance Task Notification System for maintenance.queenofsandiego.com

The maintenance tool at maintenance.queenofsandiego.com needed a critical feature: the ability to surface newly added tasks and notify stakeholders in real-time. Previously, when Travis or other team members added tasks, there was no systematic way to alert Sergio and the ops team. This article covers the architecture and implementation of a multi-component notification system that ingests task data, persists it, and intelligently notifies users based on task criticality.

The Problem: Invisible Task Updates

The maintenance tool lacked any mechanism to alert users when new tasks were added. Without visibility into task creation, team members would miss critical maintenance items unless they manually refreshed the maintenance page. Additionally, there was no audit trail or persistence layer for task data, making it difficult to track what was added and when.

The requirements were clear:

  • Surface new tasks in a way that doesn't require manual page refresh
  • Notify Sergio and appropriate stakeholders of task additions
  • Make notification frequency data-driven (real-time for critical tasks, digest for routine items)
  • Use staging environment for testing before production deployment
  • Integrate with Google Calendar for task scheduling visibility

Architecture: A Three-Layer Approach

The solution implements three core components: a persistence layer (Lambda + DynamoDB), a GAS notification handler, and frontend UI modifications to the staging maintenance tool.

Component 1: Persistence Layer with AWS Lambda

We created MaintenancePersistence.gs in the Google Apps Script project to handle Lambda invocations. The GAS file acts as a bridge between the frontend maintenance tool and AWS infrastructure:

// /Users/cb/Documents/repos/sites/queenofsandiego.com/MaintenancePersistence.gs
function persistMaintenanceTask(taskData) {
  const lambdaEndpoint = PropertiesService.getScriptProperties()
    .getProperty('MAINTENANCE_LAMBDA_ENDPOINT');
  
  const payload = {
    action: 'log_maintenance',
    task: taskData,
    timestamp: new Date().toISOString(),
    source: 'maintenance_tool'
  };
  
  const options = {
    method: 'post',
    payload: JSON.stringify(payload),
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': PropertiesService.getScriptProperties()
        .getProperty('MAINTENANCE_LAMBDA_API_KEY')
    }
  };
  
  return UrlFetchApp.fetch(lambdaEndpoint, options);
}

This abstraction allows the maintenance tool frontend to POST task data without directly handling AWS credentials. The Lambda function (deployed to AWS) receives the task payload and writes it to a DynamoDB table for long-term storage and audit purposes.

Component 2: GAS Notification Handler

We modified BookingAutomation.gs to add a new route for maintenance task logging:

// In BookingAutomation.gs doPost handler
if (params.action === 'log_maintenance') {
  const taskCriticality = params.criticality || 'routine';
  const notificationStrategy = determineNotificationStrategy(taskCriticality);
  
  // Persist the task
  const persistenceResult = persistMaintenanceTask(params);
  
  // Notify based on strategy
  if (notificationStrategy === 'immediate') {
    sendImmediateNotification(params);
  } else if (notificationStrategy === 'digest') {
    queueForDailyDigest(params);
  }
  
  return ContentService.createTextOutput('Task logged')
    .setMimeType(ContentService.MimeType.JSON);
}

The notification strategy is data-driven. We use the JADA operations team's experience as the baseline: critical tasks (electrical hazards, safety items, structural issues) trigger immediate notifications to Sergio via email, while routine maintenance (cleaning, minor repairs, scheduled checks) gets batched into a daily digest sent at end-of-day.

Component 3: Frontend UI Modifications

The staging HTML at /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html was modified to include a task submission form and real-time notification banner:

// New task form in staging HTML
<div id="ops-banner" class="notification-banner">
  <div id="new-tasks-alert"></div>
</div>

<form id="task-form">
  <input type="text" id="task-title" placeholder="Task description" required>
  <select id="task-criticality">
    <option value="routine">Routine</option>
    <option value="important">Important</option>
    <option value="critical">Critical</option>
  </select>
  <button type="submit">Add Task</button>
</form>

<script>
document.getElementById('task-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  
  const taskData = {
    action: 'log_maintenance',
    title: document.getElementById('task-title').value,
    criticality: document.getElementById('task-criticality').value,
    addedBy: 'maintenance-tool',
    timestamp: new Date().toISOString()
  };
  
  try {
    const response = await fetch('/maintenance/api/tasks', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(taskData)
    });
    
    showSuccessMessage('Task added');
    document.getElementById('task-form').reset();
  } catch (error) {
    showErrorMessage('Failed to add task');
  }
});
</script>

Infrastructure Changes

The solution required several infrastructure modifications:

  • S3 Staging Deployment: The modified staging HTML was deployed to the same S3 bucket backing the maintenance subdomain, with a staging path prefix
  • CloudFront Cache Invalidation: We invalidated the CloudFront cache for the staging maintenance distribution to ensure browsers fetch the updated HTML immediately
  • Google Calendar Integration: Created a new "Jada Maintenance" calendar in the jadasailing@gmail.com account to enable task scheduling and visibility
  • Email Configuration: Testing emails are sent to jadasailing@gmail.com using the Google Workspace SMTP relay

Notification Strategy: Data-Driven Frequency

Research from high-performing operations teams shows that notification fatigue is a major cause of alert desensitization. The strategy we implemented:

  • Critical (Immediate): Electrical hazards, safety issues, structural concerns → instant SMS + email to Sergio
  • Important (4-hour window): Equipment failures, urgent repairs → batched notification every 4 hours if new tasks exist
  • Routine (Daily Digest): Maintenance checks, cleaning, scheduled work → single daily email at 5 PM with all routine tasks from that day

This approach follows the pattern used by incident management platforms like P