Building an Asynchronous Lead Response System with Playwright Automation and SMS Integration
What Was Done
We designed and partially validated a multi-stage lead response pipeline for getmyboat.com that bridges manual message monitoring with automated proposal drafting and human-gated SMS confirmation. The system prioritizes immediate acknowledgment to warm leads while maintaining human oversight on outbound communications—a critical constraint for any customer-facing automation that touches real people.
The work involved three distinct layers:
- Monitoring layer: Playwright-based browser automation to detect new messages on getmyboat.com and trigger acknowledgment workflows
- Drafting layer: Template-driven proposal generation using historical outbound proposals as context
- Confirmation layer: Human-gated SMS dispatch via native macOS tooling with quiet-hours enforcement
Technical Details: Architecture and Component Design
Playwright Message Monitor
The monitoring component uses Playwright to maintain an authenticated browser session against getmyboat.com. Rather than building a custom scraper, Playwright was chosen because:
- It handles modern JavaScript-heavy interfaces without requiring API reverse-engineering
- Credential management via stored Google/Email login reduces maintenance surface
- Headless execution integrates cleanly into CI/cron environments
The verification command confirmed Playwright is installed system-wide and available in the operational PATH:
which playwright && npm list -g @playwright/test
Next steps involve authoring ~/jada-ops/monitor-getmyboat.js, a Node.js script that:
- Launches a headless browser context with stored credentials from
creds.txt(labels verified; values masked during audit) - Polls the messages inbox at configurable intervals (proposed: 5–10 minute cadence for warm-lead responsiveness)
- Detects unread messages and extracts sender identity, subject, and timestamp
- Triggers downstream workflows without blocking on proposal generation
Because this runs on a developer Mac rather than in a persistent Lambda or EC2 instance, the monitoring session is attended—human restart is required after terminal closure. This is a deliberate trade-off: it prevents unattended auto-sends that could fire overnight without human review, reducing production risk.
Proposal Drafting Engine
Historical proposals for Dylan, Noelle, and Molly live in ~/jada-ops/proposals/ and serve as both templates and context. The drafting layer will:
- Read all historical proposals from disk (format: markdown or plaintext, to be determined after review)
- Extract common structure: charter details, pricing rationale, terms, call-to-action
- Use lead metadata (sender name, vessel type from message, date requested) to synthesize a new proposal
- Output draft to a human-readable file (
~/jada-ops/drafts/proposal-[lead-name]-[timestamp].txt) for review before sending
No LLM or external API dependency is proposed at this stage. The drafting is deterministic template expansion, which keeps latency predictable and audit trail clear. If AI-assisted synthesis becomes valuable later, it's a pluggable layer.
SMS Confirmation Gate
The confirmation system enforces a crucial human-in-the-loop pattern:
- The
send-smstool (verified to exist in the session) wraps native macOS messaging APIs - Before any SMS dispatch, the system prepares the exact message text and presents it for one-tap confirmation
- Quiet-hours enforcement prevents texts to crew (e.g., Travis) between 17:00–08:00 local time
- If a confirmation is time-sensitive but falls in quiet hours, it's queued and flagged for morning dispatch
Implementation involves a simple time-of-day check in the confirmation routine:
function isQuietHours(recipient) {
const now = new Date();
const hour = now.getHours();
// Quiet hours: 17:00 (17) through 07:59 (7)
const inQuietWindow = hour >= 17 || hour < 8;
return inQuietWindow ? { queued: true, sendTime: "08:00" } : { sendNow: true };
}
Infrastructure and Data Sources
The system reads from four distributed sources, reflecting JADA's decentralized architecture:
- EC2 ~/repos: Code, site assets, and narrative context (jada-heritage-research.md)
- iCloud jada-ops/ and JADA/: Proposals, Sheraton COI documents, operational scripts
- DynamoDB: Charters, crew roster, revenue records (queried for context during proposal drafting)
- shipcaptaincrew Lambda: Stripe integration, subdomain routing, magic-link patterns
For the immediate workflow, only iCloud and local Mac storage are touched. DynamoDB integration (crew roles, pricing lookups) is deferred pending confirmation that it adds value to proposal drafting.
Key Decisions and Rationale
Attended vs. Unattended Automation
The design defaults to attended operation: the engineer (you) returns each morning, the system prepares a draft confirmation text, and you one-tap send it. This prevents the hard-to-reverse problem of auto-sending SMS to real people overnight without human glance. For a single confirmation that can wait until morning, this adds negligible latency and eliminates production risk.
Local Polling Over Webhooks
Getmyboat.com likely doesn't expose incoming-message webhooks. Rather than request API access or build a scraper, Playwright polling is simpler and more resilient—it works against the public interface without undocumented dependencies.
Template-Driven Proposals Over Generative Models
Historical proposals contain domain knowledge (pricing rationale, terms, tone) that reflect real deals. Extracting that structure and applying it to new leads is deterministic, auditable, and doesn't require API keys or external dependencies. If generative synthesis becomes necessary later, it's a clear upgrade path.
What's Next
The immediate next steps are:
- Playwright script authoring: Write
~/jada-ops/monitor-getmyboat.jswith credential loading, message polling, and draft-trigger logic - Proposal template extraction: Read existing proposals, identify common fields, and author a deterministic synthesis function
- Confirmation text caching: Pre-fetch Travis's charter details (date, role, call time) so morning confirmation is instant
- GMB notification redirect: Update Google My Business settings to route notifications to jadasailing@gmail.com and verify email delivery
- Quiet-hours testing: Validate that time-based gating works correctly across timezone changes
Once the attended workflow is proven with one real lead, unattended scheduling (via cron or a persistent daemon) becomes a low-risk upgrade. But for tomorrow, human confirmation at 08:00+ is the right starting point.