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.htmlto track task state changes using browser local storage and detect new task additions via DOM change detection - Persistence Layer: New
MaintenancePersistence.gsGoogle Apps Script file that logs task changes to a Google Sheet and triggers downstream notifications - Notification Layer: Extended
BookingAutomation.gswith a newlog_maintenancehandler 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_maintenanceendpoint 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 loggingMaintenanceCalendar.gs- New file for calendar integration (sets up JADA calendar subscription)BookingAutomation.gs- Addedlog_maintenanceaction 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