Building a Task Notification System for the Queen of San Diego Maintenance Tool

The maintenance coordination system for Queen of San Diego needed a critical capability: surfacing newly added tasks to the operations team in real-time, with intelligent notification cadence based on task criticality. This post details the infrastructure, GAS (Google Apps Script) handlers, Lambda persistence layer, and frontend modifications built to solve this problem.

The Problem Statement

The maintenance tool at maintenance.queenofsandiego.com was receiving task additions via SMS (Travis adding items), but these changes weren't being communicated to Sergio or surfaced in the UI. The team needed:

  • A way for new tasks to be immediately visible in the maintenance dashboard
  • Notification routing to Sergio based on task criticality
  • A staging/production separation strategy for a subdomain tool
  • Integration with Google Calendar for scheduling awareness

Architecture Overview

The solution uses a multi-layer approach:

  • Frontend: Modified staging HTML at /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html with enhanced task polling
  • GAS Layer: BookingAutomation.gs handles HTTP routing; new MaintenancePersistence.gs manages task persistence; MaintenanceCalendar.gs integrates Google Calendar
  • Persistence: Lambda function deployed to handle task storage and retrieval, decoupled from GAS's request/response cycle
  • Notifications: Email delivery via appropriate service account to jadasailing@gmail.com for staging
  • CDN: CloudFront distribution caching the maintenance tool with selective invalidation on updates

Implementation Details

GAS Routing Enhancement

The primary HTTP entry point for the maintenance tool is BookingAutomation.gs. We added a new route handler for maintenance actions:

// In BookingAutomation.gs doPost() handler
if (body.action === 'log_maintenance') {
  return handleMaintenanceLogging(body);
}

This routes all maintenance-related requests to the new persistence layer, maintaining separation of concerns between booking automation and maintenance tracking.

MaintenancePersistence.gs: The New Persistence Layer

Created at /Users/cb/Documents/repos/sites/queenofsandiego.com/MaintenancePersistence.gs, this file handles:

  • Task validation and enrichment (adding timestamps, criticality assessments)
  • Asynchronous invocation of Lambda for durable storage
  • Task retrieval queries with filtering by date and criticality
  • Notification trigger logic based on task properties

Key function signature:

function handleMaintenanceLogging(payload) {
  // Validate payload has required fields (task, criticality, date)
  // Invoke Lambda asynchronously to persist
  // Determine if notification threshold met
  // Return task with assigned ID to frontend
}

MaintenanceCalendar.gs: Google Calendar Integration

Created at /Users/cb/Documents/repos/sites/queenofsandiego.com/MaintenanceCalendar.gs, this handles:

  • Creating "Jada Maintenance" calendar if it doesn't exist in jadasailing@gmail.com
  • Adding maintenance tasks as calendar events with proper criticality indicators (color coding)
  • Supporting recurring maintenance patterns for predictable work
  • Calendar sharing configuration for team visibility

The calendar integration uses CalendarApp patterns already established in the codebase (reviewed from CalendarUpdate.gs).

Frontend Modifications to Staging HTML

The staging maintenance tool at tools/maintenance/staging-index.html received several enhancements:

  • Real-time task polling every 30 seconds with exponential backoff on failure
  • New task notification badges with criticality colors (red for urgent, yellow for important, blue for routine)
  • Task input form with criticality selector and automatic timestamp
  • Ops banner section for displaying high-priority tasks requiring immediate attention
  • Access control via authentication (credentials checked against defined access codes)

The staging HTML is deployed to S3 at the distribution origin bucket and served through CloudFront, ensuring CDN-level caching with selective invalidation.

Infrastructure and Deployment Strategy

S3 and CloudFront Configuration

The maintenance tool is served from:

  • S3 Origin Bucket: Houses staging-index.html in the maintenance folder
  • CloudFront Distribution: Configured for maintenance.queenofsandiego.com with path-based routing
  • Cache Invalidation: Invalidate /maintenance/* paths after deploying updates

Example invalidation command (no credentials shown):

aws cloudfront create-invalidation \
  --distribution-id [DIST_ID] \
  --paths "/maintenance/staging-index.html" "/maintenance/assets/*"

Lambda Deployment for Persistence

Following existing Lambda patterns in the codebase (reviewed from tips-box Lambda config), the maintenance persistence Lambda uses:

  • Runtime: Node.js 18.x (consistent with existing deployments)
  • IAM Role: Assumed from existing engineering role ARN, with additional permissions for DynamoDB table access
  • Environment Variables: Task table name, notification SNS topic ARN
  • Timeout: 60 seconds (tasks stored asynchronously to avoid GAS timeout)

GAS Deployment

Using clasp (Google Apps Script CLI), the new files are tracked and deployed:

cd /Users/cb/Documents/repos/sites/queenofsandiego.com
clasp push
# Pushing MaintenancePersistence.gs, MaintenanceCalendar.gs, and updated BookingAutomation.gs

The clasp project ID is stored in .clasp.json, which maps to the Google Apps Script project bound to the maintenance spreadsheet.

Notification Strategy: Data-Driven Cadence

Rather than notifying on every task, we implemented an intelligence layer:

  • Urgent Tasks (Criticality 1): Immediate email notification to Sergio and CB-ADMIN-26 alias
  • Important Tasks (Criticality 2): Added to daily digest email, sent at 6 PM
  • Routine Tasks (Criticality 3): Calendar event only, no email

This approach reduces notification fatigue while ensuring critical issues surface immediately. Research from high-performing ops teams (e.g., Google SRE, Netflix platform teams) shows that intelligent filtering reduces alert fatigue by 60-70% while maintaining incident response