Automating Boat Cleaning Dispatch and Calendar Integration: Building a Multi-Platform Scheduling System
During this development session, we tackled a critical operational gap: replacing a cancelled third-party cleaning service with an in-house dispatch system integrated directly into our existing calendar infrastructure. This post documents the technical architecture, implementation decisions, and integration patterns used to solve this problem at scale.
The Problem: FancyHands Cancellation and Operational Continuity
When our third-party service provider (FancyHands) was cancelled, we needed an immediate replacement for managing boat cleaning appointments. Rather than scrambling to find another vendor, we built an internal dispatch system that:
- Pulls boat cleaning requests from multiple booking platforms (GetMyBoat, Boatsetter)
- Routes tasks to our cleaning crew via email and SMS
- Synchronizes with Google Calendar to prevent scheduling conflicts
- Tracks completion status across all platforms
The solution had to integrate seamlessly with existing infrastructure without disrupting current operations.
Technical Architecture: Multi-Layer Integration
Layer 1: Boat Platform Credential Management
We centralized API credentials for GetMyBoat and Boatsetter in our environment configuration. The dispatch system reads these from repos.env at runtime, following our standard credential management pattern. This allows rotating credentials without code changes.
The primary dispatch script lives at:
/Users/cb/Documents/repos/tools/dispatch_boat_cleaner.py
This Python script handles the core logic:
- Authentication with boat booking platforms
- Parsing incoming booking data
- Formatting dispatch information for crew communication
- Error handling and retry logic for failed notifications
Layer 2: Calendar Synchronization via Google Apps Script
The boat cleaning schedule must synchronize with our primary calendar system (Google Calendar) to prevent double-booking venues and crew. This integration runs through our existing Apps Script replacement project at:
/Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/CalendarSync.gs
This GAS file was modified during this session to include boat cleaning event types. The script:
- Receives calendar events via HTTP POST from our dispatch system
- Validates event data (date/time, crew availability, venue conflicts)
- Creates Google Calendar entries in a dedicated
Boat Cleaningcalendar - Sends confirmation emails to crew and customers
- Tracks polling intervals to avoid API rate limits
The CalendarSync.gs GAS project is deployed via clasp. We maintain a .clasp.json mapping file that identifies the project ID, allowing CI/CD pipelines to push updates automatically.
Layer 3: AWS Lambda Calendar API
Our dashboard and backend systems access calendar data through a Lambda function exposed via API Gateway. This function serves as the single source of truth for all calendar operations across the organization.
Key API actions supported by the Lambda function:
add-calendar-event— Creates new calendar entries with full validationlist-calendar-events— Retrieves events within a date rangeupdate-calendar-event— Modifies existing entriesdelete-calendar-event— Removes cancelled bookings
The Lambda function connects to Google Calendar API using service account credentials stored in AWS Secrets Manager. All API calls include authentication tokens validated against a dashboard token stored in repos.env.
Implementation: Email-Driven Dispatch Workflow
The dispatch system uses email as its primary notification mechanism, following our existing patterns for crew communication. When a cleaning request arrives:
- Booking Platform Polling: The dispatch script queries GetMyBoat and Boatsetter APIs at configured intervals for new bookings
- Data Transformation: Booking data is normalized into a standard internal format (customer name, boat details, cleaning scope, preferred time)
- Calendar Verification: The system calls the Lambda calendar API to check crew availability and venue conflicts
- Crew Notification: An HTML email template (stored in
/Users/cb/Documents/repos/tools/templates/) is sent to the assigned crew member via SES - Calendar Entry Creation: Once crew accepts, CalendarSync.gs creates the official calendar entry via the Lambda API
- Platform Confirmation: Status is pushed back to the booking platform to confirm the appointment
This workflow ensures a complete audit trail and prevents race conditions where a venue might be double-booked across multiple platforms.
HTML Email Template Architecture
We created responsive email templates specifically for boat cleaning dispatch:
/Users/cb/Documents/repos/tools/templates/rady_shell_blast1.html
/Users/cb/Documents/repos/tools/templates/rady_shell_blast2.html
Each template includes:
- Boat details (name, location, client contact)
- Cleaning specifications (interior/exterior, duration estimate)
- Crew assignment and contact information
- Calendar invite link (QR code + URL)
- Status confirmation buttons (Accept/Decline/Running Late)
Templates are versioned to support A/B testing different crew communication styles and response rates.
Campaign Scheduler for Recurring Dispatch Batches
For larger events (multi-boat charters, seasonal cleaning campaigns), we implemented a batch scheduler:
/Users/cb/Documents/repos/tools/campaign_scheduler.py
/Users/cb/Documents/repos/tools/campaign_schedule.json
The campaign scheduler:
- Reads JSON configuration files defining cleaning campaigns
- Spreads dispatch notifications across time windows to avoid crew overload
- Rotates crew assignments to ensure fair workload distribution
- Triggers deployment via
deploy_campaign_scheduler.sh
This pattern allows us to coordinate large-scale cleaning operations without manual crew management.
Cross-Platform Integration: quickdumpnow.com Example
The same dispatch architecture is used across our portfolio. At quickdumpnow.com, we adapted the system for waste management services:
/Users/cb/Documents/repos/sites/quickdumpnow.com/tools/qdn_consumer_blast.py
/Users/cb/Documents/repos/sites/quickdumpnow.com/tools/qdn_stats.py
The qdn_consumer_blast.py script handles multi-channel notifications (email, SMS, push notifications). The qdn_stats.py module provides operational analytics:
- Crew response rates
- Average dispatch-to-acceptance time
- Service completion rates per crew member
- Customer satisfaction metrics
This modularity allows different business units to operate independently while sharing the same underlying infrastructure.
Key Decisions and Trade-offs
Why Email