Building a Real-Time Maintenance Task Notification System for maintenance.queenofsandiego.com
What Was Done
We implemented a multi-layered notification system to surface newly added maintenance tasks to both the web UI and critical team members via email. The system distinguishes between routine and urgent tasks, using task criticality to determine notification frequency and delivery method. This addresses the challenge of Travis adding tasks via SMS without them being immediately visible in the maintenance tool interface.
Architecture Overview
The solution spans three primary layers:
- Persistence Layer: New
MaintenancePersistence.gsin Google Apps Script handles task state management and change detection - Notification Layer: Lambda function processes task changes and sends notifications based on criticality
- UI Layer: Staging HTML at
/tools/maintenance/staging-index.htmlnow displays a task notification banner - Calendar Integration: New
MaintenanceCalendar.gssyncs critical tasks to the "Jada Maintenance" Google Calendar
Core Infrastructure Changes
Google Apps Script Files
Two new GAS files were created in the queenofsandiego.com Apps Script project:
MaintenancePersistence.gs– Manages task state, detects new entries, and tracks last notification timestampsMaintenanceCalendar.gs– Interfaces with Google Calendar API to create/update "Jada Maintenance" calendar events for critical tasks
The BookingAutomation.gs doPost handler was extended with two new action routes:
if (action === "log_maintenance") {
// Route to MaintenancePersistence.logNewTask()
}
if (action === "notify_task_changes") {
// Route to MaintenancePersistence.checkAndNotify()
}
This maintains the existing request routing pattern while adding dedicated handlers for maintenance operations.
S3 Deployment
The staging maintenance HTML was deployed to the existing S3 bucket serving maintenance.queenofsandiego.com. Key changes include:
- Modified HTML stored at the CloudFront origin path for staging-index.html
- New JavaScript section parses task criticality and renders notification banners
- Banner styling differentiates between priority levels: critical (red), high (orange), routine (blue)
The CloudFront distribution was invalidated post-deployment to ensure cache refresh.
Technical Implementation Details
Task State Management
MaintenancePersistence.gs implements a simple but effective state pattern:
- Stores task metadata in a Google Sheet tied to the Apps Script project
- Tracks
task_id,added_timestamp,criticality(1-5 scale),last_notified, andnotified_count - On each check cycle, compares incoming tasks against stored state to identify new entries
- Implements exponential backoff for routine tasks; immediate notification for critical tasks
The function signature for new task logging:
function logNewTask(taskData) {
// taskData: { title, description, criticality, assignee }
// Returns: { success: boolean, taskId: string }
}
Notification Logic
Task criticality drives notification strategy:
- Criticality 4-5 (Critical): Immediate email to both jadasailing@gmail.com and ops team; added to calendar within 5 minutes
- Criticality 2-3 (High): Email notification after 30 minutes; digest collection for end-of-day summary
- Criticality 1 (Routine): Daily digest only; no individual notifications
This tiered approach prevents notification fatigue while ensuring urgent issues surface immediately.
Calendar Integration Pattern
MaintenanceCalendar.gs creates recurring calendar events in the "Jada Maintenance" calendar. Design rationale:
- Why Google Calendar? Existing team workflow; integrates with JADA's calendar-based operations planning. This is where charter schedules live, so maintenance tasks belong in the same system of record.
- Recurring events: Multi-day tasks use recurring patterns. For example, a paint job lasting 3 days creates a 3-day recurring event rather than three separate entries.
- Only critical tasks: Filtering to criticality 4-5 prevents calendar spam while keeping urgent work visible during daily planning.
Testing and Staging Strategy
The challenge: maintenance.queenofsandiego.com currently lacks environment separation. Our approach:
- Staging HTML: Deployed to a separate path in the same S3 bucket; served via CloudFront with a staging-specific origin header
- GAS Functions: Accept an optional
environmentparameter (defaults to "production"). Staging requests includeenvironment=staging - Email Delivery: Staging notifications go to
jadasailing@gmail.com - Calendar Target: Staging events write to a separate "Jada Maintenance - Staging" calendar for testing without polluting the live calendar
This provides functional isolation without requiring separate infrastructure, keeping deployment complexity low.
Key Decisions and Rationale
Criticality-Based Notification Frequency
Rather than notifying on every new task, we implement intelligent batching for routine items. Industry research (citing practices from high-performing operations teams like those at incident response platforms) shows that frequent low-urgency notifications reduce effective signal-to-noise ratio and lead to alert fatigue. By reserving individual notifications for truly critical tasks and batching routine items into daily digests, we maintain team responsiveness while preserving focus.
Google Apps Script as the Persistence Layer
Why not a dedicated database? The queenofsandiego.com project already uses Google Sheets for various operational logs. Leveraging the same pattern:
- No additional infrastructure or authentication to manage
- Team members can view task history directly in Sheets if needed
- Reduces operational surface area
- Cost: zero (within existing Google Workspace quotas)
Email as Primary Notification Channel (for now)
We chose email over SMS or Slack for initial implementation because:
- Works across all team roles without additional tooling onboarding
- Creates an audit trail of notifications sent
- Can be templated with rich formatting and context
- Integrates seamlessly with the GAS ecosystem
SMS or Slack integration can be added later as a second-layer notification for critical tasks if team feedback warrants it.
Deployment Commands
# Deploy staging HTML to S3
aws s