Building a Task Notification System for the JADA Maintenance Tool: Real-Time Alerts with CloudFront, Lambda, and GAS
What We Built
The JADA maintenance tracking tool (maintenance.queenofsandiego.com) needed a way to surface newly added tasks and notify the operations team in real-time. This project implemented a full notification pipeline: a Lambda function for persistence, a Google Apps Script handler to trigger emails, staging HTML modifications for task visibility, and calendar integration to track maintenance cycles.
The Problem: Silent Task Creation
When Travis adds maintenance tasks via SMS or the tool interface, there's no notification mechanism for the operations team. Sergio needs visibility into new tasks—either individual alerts for critical items or end-of-day digests for routine work. The challenge was building this without disrupting the existing booking automation system, and doing it safely in a staging environment first.
Infrastructure Architecture
Core Components
- CloudFront Distribution: maintenance.queenofsandiego.com (staging HTML cached at /tools/maintenance/staging-index.html in S3)
- S3 Bucket: maintenance-tool bucket containing the staging index.html
- Google Apps Script: queenofsandiego.com Apps Script project with BookingAutomation.gs and new MaintenancePersistence.gs
- Lambda Function: Handles async task logging and triggers GAS webhook for notifications
- Google Calendar: "Jada Maintenance" calendar under jadasailing@gmail.com for tracking maintenance cycles
Technical Implementation Details
1. Persistence Layer (MaintenancePersistence.gs)
Created a new Google Apps Script file to handle maintenance task logging:
File: /Users/cb/Documents/repos/sites/queenofsandiego.com/MaintenancePersistence.gs
Purpose:
- Log task data to Google Sheets for historical tracking
- Trigger notification workflow on new task creation
- Differentiate between critical and routine tasks
- Enable reporting and audit trails
The persistence layer writes to a Google Sheet that serves as the source of truth, enabling:
- Timestamp-based task sequencing
- User attribution (who created the task)
- Task criticality classification
- Integration with Google Calendar events
2. Notification Handler Integration (BookingAutomation.gs)
Extended the existing BookingAutomation.gs doPost handler to route maintenance requests:
Route: /log_maintenance
Method: POST
Payload: {taskName, criticality, description, assignee}
Logic:
1. Parse request from maintenance tool
2. Call MaintenancePersistence.logTask()
3. Determine notification strategy based on criticality
4. Trigger appropriate alert (immediate for critical, digest for routine)
5. Return success/error JSON to client
This kept the routing in a single GAS handler pattern, avoiding multiple entry points and simplifying debugging.
3. Staging HTML Modifications
Updated /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html to:
- Add a "New Tasks" banner at the top (ops visibility)
- Hook task creation form submission to POST /log_maintenance
- Include criticality selector (Low/Medium/High/Critical)
- Display last-synced timestamp from persistence layer
- Add console logging for troubleshooting (staging only)
Key JavaScript addition:
document.getElementById('taskForm').addEventListener('submit', async (e) => {
e.preventDefault();
const payload = {
taskName: document.getElementById('taskName').value,
criticality: document.getElementById('criticality').value,
description: document.getElementById('description').value,
assignee: document.getElementById('assignee').value
};
const response = await fetch('/log_maintenance', {
method: 'POST',
body: JSON.stringify(payload)
});
const result = await response.json();
console.log('Task logged:', result);
});
4. Calendar Integration (MaintenanceCalendar.gs)
New script file for syncing maintenance tasks to the "Jada Maintenance" Google Calendar:
Responsibilities:
- Create calendar events for new maintenance tasks
- Set event duration based on task type
- Add color coding: Red (Critical), Orange (High), Yellow (Medium), Green (Low)
- Include task description and assignee in event details
- Set up recurring maintenance cycles as needed
This provides Sergio with an alternative view of maintenance work in Google Calendar, integrated with the booking system.
Notification Strategy Decision: Criticality-Based Alerting
After reviewing industry best practices from high-performing operations teams (Basecamp's scoping methodology, PagerDuty's alert fatigue research, and incident.io's runbook patterns), we implemented:
- Critical Tasks: Immediate email notification to jadasailing@gmail.com
- High Priority Tasks: Email within 1 hour (batched if multiple)
- Medium/Low Tasks: Daily digest email at 6 PM
Why this approach: Immediate alerts for every task cause notification fatigue. Criticality-based pacing aligns with how maritime operations actually triage work—electrical safety issues demand immediate response, but routine maintenance can wait for a daily review. This matches patterns used by technical teams at companies like Shopify and Stripe.
Staging vs. Production Separation
The maintenance tool presents a unique challenge: both staging and production share the same URL during testing. We implemented:
- Email Destination Override: Staging sends all notifications to jadasailing@gmail.com for review
- HTML Path Separation: Staging uses /tools/maintenance/staging-index.html; production uses live CloudFront distribution
- GAS Script Versioning: Version numbers in payload headers track which version generated the request
- CloudFront Cache Invalidation: After each staging deployment, run:
aws cloudfront create-invalidation \
--distribution-id [STAGING_DIST_ID] \
--paths "/tools/maintenance/*"
Deployment Commands
The full deployment sequence:
# 1. Deploy modified staging HTML to S3
aws s3 cp staging-index.html s3://[maintenance-bucket]/tools/maintenance/staging-index.html
# 2. Push GAS changes (MaintenancePersistence.gs, MaintenanceCalendar.gs, BookingAutomation routes)
clasp push
# 3. Invalidate CloudFront cache
aws cloudfront create-invalidation \
--distribution-id [STAGING_DIST_ID] \
--paths "/tools/maintenance/staging-index.html"
# 4. Verify: Check jadasailing@gmail.com for test task notification
Key Decisions and Rationale
- Google Sheets for Persistence: No new infrastructure needed; integrates with existing Google Workspace account; queryable for reporting
- GAS for Routing: