02Agentic Product

Pitch Studio

Multi-tenant SaaS that turns a company's sales pitch into an avatar-led presentation viewers can interrupt.

Context
Personal project
Year
2026
Role
Everything — architecture, backend, frontend, design
Live
Visit

3

retrieval tiers, stopping at the first that clears

3

layers of tenant isolation

The problem

A sales pitch is delivered once, live, by the person who knows the answers. Every recording after that is worse: it cannot respond, so the viewer with a question either emails and waits, or leaves.

The naive fix — put a chatbot next to the video — fails for the reason chatbots usually fail in sales contexts. It will answer confidently about things the company never said, and one invented number is worse than no answer at all.

How it works

01

Retrieval that declines rather than guesses

A question is answered from the narrowest context that can actually answer it: the current scene first, then the whole presentation, then the organisation's knowledge base. The search stops at the first tier clearing a grounding threshold. Below that threshold the answer is a refusal, not a paraphrase of the nearest chunk.

02

Tenant isolation in three layers

Every tenant table carries an org id. All access goes through a scoped client that pins the org filter, and importing the raw database client outside the data layer is a lint error rather than a code-review note. Retrieval filters by org before any vector search runs, not after.

03

Model proposals behind human approval

Visual templates are described in a small DSL. The model proposes one and it lands in a queue for a person to approve, edit or reject. The model gets to suggest; it does not get to publish.

04

Ingestion as background work

Document parsing, embedding and avatar rendering are jobs, not request handlers. Uploading a deck returns immediately and the work happens where a slow PDF or a HeyGen render cannot time out a user's request.

Decisions worth defending

  • Postgres with pgvector rather than a dedicated vector store — one database to operate, one transaction boundary, and org filtering that composes with the vector query instead of fighting it.

  • Clerk for auth and organisations, because multi-tenant identity is a genuinely hard problem to get right and it is not the problem this product exists to solve.

  • The lint rule enforcing the scoped client is the actual isolation guarantee. A convention that relies on everyone remembering is not a guarantee.

  • A grounding threshold that produces refusals is a product decision as much as a technical one. It makes the product less impressive in a demo and more trustworthy in a sale.

Outcome

Built solo end to end — schema, jobs, retrieval, studio UI and public viewer. The architecture is the deliverable here: the interesting parts are where the system chooses not to answer.

Built with

Next.jsTypeScriptNeon PostgrespgvectorDrizzle ORMClerkInngestCloudflare R2Voyage embeddingsHeyGenElevenLabs

More work

Start a conversation