Switchyard

Roadmap

Phase 1 (lead intake) ships live. Phases 2 and 3 followed without Phase-1 schema rewrites — additive tables, additive jobs, no concessions. Phase 4 is the remaining piece.

Phase 1

Lead intake → ClickUp tasks

Shipped

Multi-tenant parsers, enrichment, OAuth, signed webhooks, Filament admin, OpenAPI docs.

Inquiries from many sources (brand contact forms, Upwork notification emails, Fiverr DMs, generic webhooks, manual paste-in) get normalized, enriched with a taxonomy + portfolio-example suggestions + a 0-100 lead score, and land as ClickUp tasks. ClickUp webhook callbacks mirror status changes back into the local inbox.

leadslead_sourceslead_eventsclickup_connectionsclickup_configs
Phase 2

Client status board

Shipped

Public /status/[token] page renders milestones from a tracked ClickUp folder; no client login needed.

A client_projects row sits 1:1 with a ClickUp folder. public_status_tokens are sty_-prefixed signed share links (with optional expiry + revoke). Incoming ClickUp webhook events update both the lead mirror (Phase 1) and the milestonemirror (Phase 2) independently. Operators issue share links straight from Filament; clients see "In review", "In design", "Shipping" with status colors pulled from ClickUp.

client_projectspublic_status_tokensclient_milestones/status/[token]MilestoneSyncer
Preview the (404) status page →
Phase 3

Proposal → project scaffolder

Shipped

Auto-fires on lead-status=won when a service-tagged template has auto_scaffold on.

When a lead transitions to won, the MirrorClickUpStatusJob looks up a matching project_templates row (slug-matched on service_tag, falls back to a no-tag default) and dispatches ScaffoldProjectJob. That calls ClickUp createFolder createList createTaskin order, materializing a full project structure with the template's lists + tasks (string-or-object task specs supported with due_offset_days). Every run records a step-by-step scaffold_runs audit log; failed runs retry from Filament. The new folder also lands as a Phase 2 client_projects row so a public share link is one click away.

project_templatesscaffold_runsScaffoldProjectJobon(lead.status=won)
Phase 4

Time → invoice automation

Sketched

Mirror ClickUp time entries via the time-tracking API into time_entries. On a per-tenant schedule (weekly / biweekly), generate Stripe invoices grouped by client + period. Drafts land in invoices with a review action before send.

time_entriesinvoicesstripescheduler
Why the same seams hold up. Every phase reuses ClickUpApiClient (retry + 429 backoff + rate-limited + idempotent on lead_id), WorkspaceScope (tenant isolation by global scope), and the lead_events audit log (which generalizes to a workspace-wide event bus for Phase 3's won-state trigger). Adding a phase means new tables + new jobs, not a refactor — and Phases 2 and 3 shipped without a single Phase-1 schema change.