All work

    CloserCore

    Telnyx-backed power dialer with an AI receptionist

    TanStack StartTanStack RouterReact 19TypeScriptSupabaseDenoTelnyx WebRTCStripeTailwind 4Vite 7

    Role: Sole engineer — architecture, TanStack Start frontend, Telnyx WebRTC integration, Supabase schema and RLS, Edge Functions, Stripe billing, TCPA compliance logic. · Updated 2026-09-01

    What's actually in it

    24
    Routes
    file-based; 26 route files less two layout routes
    13
    Edge Functions
    Deno — Telnyx call, SMS, transcription, Stripe
    93
    RLS policies
    across 22 tables, 17 migrations, 1,371 SQL lines
    116
    TS/TSX modules
    17,644 lines, excluding generated route tree

    The problem

    Sales teams were paying for a dialer, a phone system, a recording tool, and a compliance spreadsheet, and none of them agreed with each other. The compliance part is the one that actually bites: calling a recipient outside their local 8am–9pm window is a TCPA violation per call, and a dialer that only knows the caller's timezone will happily generate hundreds of them.

    What I built

    • 01Built the whole app on TanStack Start with file-based routing — 24 navigable routes across the dialer, inbox, contacts, recordings, SMS, analytics, coaching, and an 11-route settings surface.
    • 02Wired Telnyx WebRTC into a React context so the softphone is a single long-lived connection shared by every route, rather than a component that tears down when the user navigates to their contact list mid-call.
    • 0313 Supabase Edge Functions on Deno handling the Telnyx side — webhooks, call actions, number search and provisioning, SMS, WebRTC credential minting, and a live transcription stream — plus Stripe checkout, portal and webhook.
    • 04AI on the call record rather than in it: a post-call summary function and a voicemail note function write structured output back to the call row, so the coaching and analytics views read columns instead of re-running a model.
    • 0522 tables behind 93 RLS policies, with workspace membership as the tenancy boundary and an append-only audit log for the compliance trail.
    • 06Closed a real failure mode where an `incoming_calls` row stuck at status `ringing` reopened the full-screen call modal on every page refresh, in three layers: a unique index on `telnyx_call_control_id` so the webhook's upsert is idempotent instead of writing a new row per Telnyx retry, a hangup handler that relabels any still-`ringing` row to `missed`, and a two-minute freshness window on the client so a row the webhook never got to close can't resurrect the modal.

    Building something in this shape? Book a 30-min scope call →

    Engineering decisions

    The quiet-hours module is deliberately duplicated

    TCPA calling windows are enforced in both the browser and the Edge Functions, and the two implementations are separate files — Deno can't import from src/, and the browser can't import from supabase/functions/. Rather than pretend a shared package solved it, the mirror is documented as a mirror. Compliance logic that only runs client-side is decorative; a user with devtools open is not a compliance control.

    Ambiguous area codes resolve to the more eastern timezone

    Area-code-to-timezone mapping is imperfect — some codes span two zones. Every ambiguous code is assigned the more eastern zone on purpose, so a wrong guess blocks a borderline-late call rather than permitting a violation. Unknown codes fall through to allowed, because refusing to dial numbers you can't classify would break the product for a legal risk that isn't there.

    Per-seat billing enforced in code, not in Stripe

    Only the Pro and Scale tiers bill per seat. Rather than modelling that in Stripe's product catalogue, checkout reads the live workspace_members count and passes it as quantity, gated by a PER_USER_TIERS set. Seat count lives in the database that already knows it, and adding a tier is a one-line change instead of a Stripe migration.

    Feature gates as a single tier table

    Eight features — power dialer, coaching, analytics, API keys, HIPAA mode, unlimited recording, multi-workspace, AI receptionist — map to a minimum tier in one FEATURE_MIN_TIER object consumed through an entitlements context. No entitlement checks scattered through components, and the upgrade prompt for any gated feature knows exactly which tier to sell.

    The product

    The dialer. `● Registered` is the @telnyx/webrtc client holding a live SIP registration in the browser — the FROM selector picks which owned number the leg originates from.
    AI receptionist. Takeover rules, ring count, voice and language, knowledge base — and a live preview that runs the greeting against the current config before it ever answers a real call.
    Billing. Start and Team are flat `/mo`; Pro and Scale are `/user/mo` — the per-seat split is enforced in application code against a `PER_USER_TIERS` set, not by Stripe.
    Number inventory. `Sync from Telnyx` reconciles local rows against the carrier; `Repair inbound` rewrites the webhook binding on numbers that drifted.
    Append-only audit log. Every workspace, role, and number change lands here — no update path, no delete path.

    Want something built the way CloserCore was?

    Bring the problem, not a spec. 30-minute call — I'll tell you what it actually takes to build, what I'd cut, and what it costs. No decks, no discovery phase invoice.

    Related builds