Local development

Prerequisites

  • Node 20 (.nvmrc)

  • pnpm

  • A Supabase project — PostgreSQL and Auth

  • Redis, for the in-flight call counter

Setup

git clone <repository-url>
cd dialer-v2
nvm use
pnpm install

Create .env (git-ignored) with at minimum:

DATABASE_URL=
DIRECT_URL=
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
REDIS_URL=redis://localhost:6379

Then add integrations for whatever you are working on — see Environment variables.

pnpm prisma generate
pnpm prisma migrate deploy   # or `pnpm prisma migrate dev` against a scratch database
pnpm dev

Signing in

Signup requires a @payability.com address (or a subdomain) — isAllowedPayabilityEmail() in middleware and a Supabase auth hook both enforce it. A different domain is signed out immediately with ?error=forbidden_domain.

POST /api/auth/register creates the Profile, Subscription and owner SubscriptionUser in one step, so a fresh signup lands in a working workspace.

What works without every integration

Missing Consequence

NEXT_RETELLAI_API_KEY

Browsing works; dialing fails at the Retell step and the target is marked failed with retell_error

RESEND_API_KEY

Email campaigns can be configured but not sent

AI_GATEWAY_API_KEY

Call analysis, variation generation, prompt suggestions and test runs all fail

CRM_QUEUE_URL / AWS credentials

CRM publishes silently no-op; watch the logs

BigQuery credentials

Sequence data gates fail; other sequence channels still work

REDIS_URL

Broadcast throttling misbehaves — fix this before running a campaign locally

INTERNAL_API_SECRET

Broadcasts return 401; call them manually with the header instead

The dashboard, contacts, registries, campaign and sequence configuration, and reporting (against whatever data exists) all work with just the database and Supabase.

Triggering work manually

Nothing schedules itself locally — there is no pg_cron. Invoke the loops by hand:

# one dial tick
curl -X POST http://localhost:3000/api/campaigns/<campaignId>/broadcast \
  -H "Authorization: Bearer $INTERNAL_API_SECRET" \
  -H "Content-Type: application/json" -d '{}'

# one email tick
curl -X POST http://localhost:3000/api/email-campaigns/<campaignId>/broadcast \
  -H "Authorization: Bearer $INTERNAL_API_SECRET" \
  -H "Content-Type: application/json" -d '{}'

The daily resets and the phone-number optimizer are Inngest cron functions (phoneNumberDailyResetCron, sendingDomainDailyResetCron, phoneNumberOptimizerCron). Run them with Invoke in the Inngest dev server UI (see below).

Inngest locally

Workflows need the Inngest dev server:

npx inngest-cli@latest dev -u http://localhost:3000/api/inngest

Its UI (usually http://localhost:8288) shows runs, step results and lets you replay. Without it, events are sent and never consumed — which looks exactly like a broken workflow, so check the dev server first.

Replaying a webhook

Real payloads are already in the database:

select "eventType", "rawPayload"
from "WebhookEvent"
where source = 'Retell' and "eventType" = 'call_analyzed'
order by "receivedAt" desc
limit 1;

curl it back at the endpoint. The WebhookEvent upsert is idempotent on (source, eventId), so the row is not duplicated, but the handler runs again — which is the point.

Data safety

.env typically points at a shared Supabase project. Assume writes are real:

  • Set CampaignTarget.isTestTarget = true on anything you plan to dial, which excludes it from CRM hand-off.

  • Prefer draft campaigns; only running campaigns broadcast.

  • pnpm prisma migrate reset destroys data — never run it against a shared database.

  • Test email sends go to real inboxes and count against real daily caps.

The in-app docs site

The Fumadocs site at /docs is built from the .mdx files directly under docs/ (source.config.ts, lib/source.ts, app/docs/). It is public — no session required — and hot-reloads in development.

This Antora component lives under docs/modules/ and is not part of that site. To preview it, point an Antora playbook at the repository with start_path: docs; see About this documentation.

Common setup problems

Symptom Fix

@prisma/client did not initialize

pnpm prisma generate

Type errors on Prisma models after a schema edit

pnpm prisma generate — the client is generated into prisma/generated

Stale build after dependency changes

rm -rf .next && pnpm install && pnpm build

Redirected to /login in a loop

Missing or wrong Supabase anon config, or a non-Payability email

Events sent but no workflow runs

The Inngest dev server is not running