Skip to content

404Dealer/PatchBay

Repository files navigation

Patchbay CRM (Developer Preview)

A tiny, fast, SMS‑first CRM built with Next.js + Supabase. Tenant‑aware, Twilio‑enabled, and still early — APIs and UI are subject to change and not yet production‑ready.

This repo is an opinionated, open‑source reference app for an SMS‑centric CRM: capture leads from anywhere, message them in a single thread, and automate quotes/alerts with a Supabase‑native outbox worker. It’s designed to be easy to fork, easy to run locally, and easy to adapt to your own multi‑tenant use cases.

If you’re here from an open‑source downloader or template browser: this is not a generic starter. It ships a real data model, Twilio dispatcher, and guardrails for multi‑tenant SaaS apps.


✨ Why Patchbay?

  • Massive simplicity: leads → messages → notifications, without a bunch of extra CRM bloat.
  • Supabase‑native: RLS security, Realtime updates, SQL‑first data model, and Edge Functions/cron for background work.
  • Bring Your Own Provider: Twilio adapter for real SMS, plus a fake provider so you can click around with no credentials.
  • Tenant‑aware from day one: all business tables are tenant_id‑scoped and locked down by RLS.
  • Contrib‑friendly: small surface area, typed domain, and Playwright smoke tests so you can refactor with confidence.

If you just want to kick the tires, you can run everything locally and use the fake SMS provider — no Twilio account required.


🧱 Stack at a Glance

Layer Purpose Notes
Next.js App Router Dashboard, leads workspace, admin tooling Tailwind + shadcn/ui for layout/components
Supabase (Postgres + Auth + Realtime) Auth, multitenant data, RLS, realtime updates supabase/ folder contains migrations, seeds, SQL helpers
Supabase Edge Function dispatch-notifications Pulls from public.notifications, calls Twilio, logs to public.messages Scheduler via pg_cron + Supabase CLI
Twilio (optional) Sends SMS notifications to leads/owners Tenant-specific credentials via messaging_credentials or shared fallback env vars
Vitest + Playwright Unit + E2E tests guarding guards and protected routes npm run test:unit, npm run test:e2e

Additional details:

  • App: Next.js 16 (App Router), TypeScript, Tailwind, shadcn/ui
  • Tooling: npm, Supabase CLI, Playwright, Vitest

Repo highlights:

  • app/ – Next.js routes, protected layouts, auth flow, and the leads workspace UI
  • components/ – UI and feature components (leads feed, dispatcher panel, Twilio debugger, etc.)
  • lib/ – utilities, auth guards, Supabase helpers
  • supabase/migrations/ – authoritative schema, policies, helpers, and worker/cron SQL
  • supabase/functions/dispatch-notifications/ – Edge Function worker that pulls from public.notifications and sends via Twilio
  • supabase/sql/ – cron installer + post‑deploy sanity checks
  • docs/ – data model and Twilio plan

🧬 Data Model (simplified)

The exact schema lives in supabase/migrations/, but conceptually this app revolves around:

  • Leads – people you’re talking to (with flexible JSONB properties per tenant)
  • Messages – inbound/outbound SMS rows tied to a lead
  • Notifications – internal queue of events the dispatcher will pick up (e.g. “lead created”, “quote request received”)
  • Notification rules – per‑tenant preferences for who gets alerted and how
  • Messaging credentials – optional per‑tenant Twilio credentials (otherwise the app can fall back to shared env vars)

All core tables are tenant_id‑scoped and protected by RLS so each customer only sees their own data.

For a deeper walkthrough of the SMS dispatcher and queues, see docs/twilio-lead-sms-plan.md.


🗺️ Architecture

At a high level:

  • Next.js app renders the dashboard, leads workspace, and admin tools. Server actions talk directly to Supabase using the service role key on the server only.
  • Supabase Postgres stores tenants, users, leads, messages, notification rules, and Twilio credentials. RLS enforces tenant isolation everywhere.
  • Supabase Edge Function dispatch-notifications acts as a worker: it leases rows from public.notifications, calls Twilio (or the fake provider), writes to public.messages, and updates the notification state.
  • pg_cron (installed via supabase/sql/install-dispatch-cron.sql) schedules the worker to run on a fixed cadence.
  • Twilio (optional) is the real SMS provider. You can also run with the fake provider to simulate sends in development.

🚀 Quick Start

You’ll need:

  • Node.js 20+
  • Supabase project (URL, anon/publishable key, service role key)
  • Optional: Twilio Account SID + Auth Token + Messaging Service SID (or a single From number)

1) Install dependencies

npm install

2) Environment

Copy .env.local.example.env.local and keep these values in sync with Vercel + Supabase secrets.

Key What it Controls Next.js / Vercel Supabase secret Notes
NEXT_PUBLIC_SUPABASE_URL Supabase project URL Also used by scripts
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY Browser auth key
SUPABASE_SERVICE_ROLE_KEY Server actions + dispatcher Required by scripts + Edge Function
TWILIO_ACCOUNT_SID / TWILIO_AUTH_TOKEN Shared Twilio credentials (optional) Tenants can override via messaging_credentials
TWILIO_FROM_NUMBER / TWILIO_MESSAGING_SERVICE_SID Default sender identity Either an E.164 number or Messaging Service SID
DISPATCH_ALERT_WEBHOOK_URL Slack/Teams webhook for failures Optional but recommended for monitoring
NOTIFICATION_BATCH_SIZE, NOTIFICATION_LEASE_SECONDS, NOTIFICATION_MAX_ATTEMPTS, NOTIFICATION_MAX_BACKOFF_MINUTES Dispatcher tuning knobs Defaults: 25 / 45s / 5 attempts / 60m
PLAYWRIGHT_BASE_URL Overrides smoke‑test target Defaults to http://127.0.0.1:4000
SEED_TEST_ADMIN_PASSWORD Overrides the default password for the deterministic test admin Optional; defaults to TestAdmin!123

Next.js tip: any variable prefixed with NEXT_PUBLIC_ is bundled to the client. Never put secrets there.

3) Database & seed

With the Supabase CLI installed and logged in:

supabase start
npm run db:push
npm run seed

Running npm run seed executes supabase/seed.sql and provisions a deterministic admin account.

  • Email: test-admin@ironedge.dev
  • Password: TestAdmin!123 (override via SEED_TEST_ADMIN_PASSWORD)

4) Run the app locally

In one terminal:

npm run dev

In another (optional, if you want the real worker running):

supabase functions serve dispatch-notifications --env-file .env.local

Log in at http://localhost:3000 with the seeded admin.

5) Smoke tests

Playwright smoke tests will spin up the dev server and exercise protected routes and basic workspace flows:

npm run test:e2e

🔁 Common Workflows

Task Command
Push latest schema to local Supabase (auto‑runs sanity check) npm run db:push
Run the RLS/cron sanity report manually npm run db:sanity
Seed demo data (tenant, pipeline, leads) npm run seed
Install/refresh cron job npm run cron:install
Deploy dispatcher + cron in one go npm run dispatch:deploy
Trigger the Edge Function manually ./scripts/dispatch-test.sh or pwsh scripts/dispatch-test.ps1
Run unit tests for guards/helpers npm run test:unit
Run smoke tests npm run test:e2e

The scripts/dispatch-test.* helpers read NEXT_PUBLIC_SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY from your environment and wrap an HTTP call to the worker so you don’t have to remember the curl/PowerShell incantations.


📡 Deployment & Cron

Vercel ↔️ Supabase

  • Vercel hosts the Next.js frontend + server actions. Set every env var from the table above in the Vercel dashboard before deploying.

  • Supabase stores the Twilio secrets used by the Edge Function:

    supabase secrets set \
      TWILIO_ACCOUNT_SID=... \
      TWILIO_AUTH_TOKEN=... \
      TWILIO_FROM_NUMBER=... \
      TWILIO_MESSAGING_SERVICE_SID=... \
      DISPATCH_ALERT_WEBHOOK_URL=...
  • SUPABASE_SERVICE_ROLE_KEY should stay in Supabase/CLI and server environments only. Never expose it client‑side.

Worker + scheduler

npm run dispatch:deploy   # supabase functions deploy dispatch-notifications && cron install

The cron install script (supabase/sql/install-dispatch-cron.sql) uses supabase_functions.http_request so the job lives alongside your database. The relevant SQL:

select
  cron.schedule(
    'dispatch_notifications_worker',
    '* * * * *',
    $$
      select
        supabase_functions.http_request(
          'dispatch-notifications',
          jsonb_build_object(
            'eventType', 'quote_request.received',
            'limit', 50
          ),
          '{}'::jsonb,
          'POST'
        );
    $$
  );

After each deploy, run:

supabase db query supabase/sql/post-deploy-sanity.sql

This checks that RLS is enabled, cron is installed, and the queue depth is healthy.


🧪 Tests & Guardrails

  • Auth/permission guardstests/lib/guards.test.ts exercise centralized guard helpers via Vitest. They ensure anonymous visitors get redirected and non‑admins cannot hit admin pages. Run with npm run test:unit.
  • Playwright flowstests/protected-routes.spec.ts and tests/leads-workspace.spec.ts cover bounce logic and the deterministic leads/admin workflows seeded in supabase/seed.sql. npm run test:e2e starts the dev server on port 4000 automatically.
  • DB sanity SQLsupabase/sql/post-deploy-sanity.sql confirms RLS is enabled on key tables (leads, notifications, notification_rules, messages, phone_numbers) and checks for the cron job + queue depth.
  • Edge monitoringdispatch-notifications posts to DISPATCH_ALERT_WEBHOOK_URL on the first failure and when a notification hits MAX_ATTEMPTS. Point that webhook at a Slack/Teams channel you actually watch.

🛠️ Ops & Monitoring

  • Admin debugger (UI)/protected/admin contains “Dispatcher health & Twilio history” panels showing queue depth, failing job count, last send timestamp, next retry window, and the latest Twilio sends pulled from public.messages.
  • Manual trigger – Use scripts/dispatch-test.ps1 / .sh to fire the Edge Function on demand for debugging.
  • Tenant visibility toggles – Leads/dashboard visibility toggles emit toasts when flipped, and the nav hides routes server‑side per tenant visibility.
  • Docsdocs/twilio-lead-sms-plan.md captures the end‑to‑end SMS architecture, dispatcher behavior, and roadmap.

🤝 Contributing

Contributions are very welcome, especially around:

  • improving the Twilio adapter and error mapping
  • additional E2E flows for lead creation + messaging
  • better admin tooling for queues and cron health
  • docs for multi‑tenant patterns and security

Typical flow:

  1. Fork the repo and create a feature branch.
  2. Make changes with tests where it makes sense.
  3. Run npm run test:unit and npm run test:e2e locally.
  4. Open a PR with a short description of the behavior change.

🗺️ Roadmap (high‑level)

  • Email adapter (e.g. Resend) + templates
  • Web form widget for lead capture (with UTM auto‑capture)
  • Attachments via Supabase Storage
  • Multi‑tenant admin & audit log
  • Scheduled sends and quiet‑hours controls per tenant
  • Optional WhatsApp channel via Twilio or another provider

📄 License

Apache License 2.0 — permissive, patent‑grant, and enterprise‑friendly. See LICENSE and NOTICE for full terms and attribution.

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •