An AI-powered meeting platform where users create custom AI agents with unique instructions, start video calls with those agents as real-time participants, and receive auto-generated transcripts and summaries after each meeting. Built with Next.js 15, React 19, tRPC, Stream Video & Chat SDKs, OpenAI Realtime API, Inngest background jobs, and Drizzle ORM with PostgreSQL.
How the system is structured from frontend to external services.
Server Components for layout and data fetching, Client Components for interactive meeting UI, agent forms, and chat. TanStack React Query manages server state with tRPC integration. Responsive dashboard with collapsible sidebar and light/dark mode via next-themes.
Type-safe RPC layer with tRPC — protected procedures enforce authentication, premium procedures gate resource creation behind Polar subscription checks. Drizzle ORM provides type-safe SQL queries with PostgreSQL. Better Auth handles credentials + Google OAuth with session-based auth.
Six tables: users, sessions, accounts, verifications, agents, and meetings. Meeting status tracked via a PostgreSQL enum (upcoming, active, completed, processing, cancelled). Cascade deletes ensure cleanup when users or agents are removed. Duration computed via EXTRACT(EPOCH) on timestamp columns.
Stream Video handles WebRTC video calls with auto-transcription and 1080p recording. OpenAI Realtime API powers AI agent participation in live calls. Inngest runs background jobs for post-meeting transcript processing and GPT-4o summarization. Stream Chat enables post-meeting Q&A. Polar manages subscription billing with free tier limits.
Core entities and how they relate to each other.
Central user account — supports email/password credentials and Google OAuth via Better Auth
id (text, PK)nameemail (unique)emailVerified (boolean)imagecreatedAtupdatedAtActive user sessions with unique tokens, expiry, and device tracking (IP address, user agent)
id (text, PK)token (unique)expiresAtipAddressuserAgentuserIdcreatedAtupdatedAtOAuth provider links — stores provider IDs, access/refresh/ID tokens, and token expiry for each connected provider
id (text, PK)accountIdproviderIdaccessTokenrefreshTokenidTokenaccessTokenExpiresAtscopepassworduserIdcreatedAtupdatedAtEmail verification tokens with identifier and expiry — used by Better Auth for email confirmation flows
id (text, PK)identifiervalueexpiresAtcreatedAtupdatedAtCustom AI agent created by a user — stores name and system instructions that define the agent's personality during calls
id (nanoid, PK)nameinstructions (text)userIdcreatedAtupdatedAtVideo meeting record — tracks lifecycle status, links to agent, stores transcript URL, recording URL, and AI-generated summary after processing
id (nanoid, PK)namestatus (enum: upcoming|active|completed|processing|cancelled)startedAtendedAttranscriptUrlrecordingUrlsummaryuserIdagentIdStep-by-step walkthrough of the main user and system flows.
AI agents need to join video calls as live participants, listen to user speech, and respond conversationally in real time — not just generate text responses asynchronously.
Integrated OpenAI Realtime API with Stream Video SDK. The agent is upserted as a Stream Video user with a DiceBear avatar, joins the call, and uses the OpenAI Realtime API for bidirectional audio streaming. The agent's system instructions (defined by the user) control its conversational behavior.
Raw transcripts from Stream Video contain speaker_id references, not human-readable names. Processing must happen asynchronously after the call ends without blocking the user.
Inngest handles the entire pipeline as a multi-step background function: fetch JSONL transcript, parse it, query both users and agents tables to resolve speaker IDs to names and avatars, then feed the enriched transcript to GPT-4o for summarization. Each step is independently retryable.
Free tier users should be limited on how many agents and meetings they can create, while premium users get unlimited access. This needs to be enforced at the API level, not just the UI.
Created a custom premiumProcedure in tRPC that checks the user's Polar subscription state. For free users, it counts existing resources (agents or meetings) via Drizzle and blocks creation when limits are exceeded. If the user is a paying subscriber, the check is skipped entirely.
Traditional REST APIs require manual type definitions for request/response shapes, leading to type mismatches between frontend and backend as the app evolves.
tRPC provides full type inference from server procedures to client hooks — input schemas are validated with Zod, and return types flow automatically to TanStack React Query. Drizzle ORM adds type safety at the database layer with schema-derived types, so the entire stack from DB to UI is type-checked.
MeetWise demonstrates expertise in AI-integrated real-time applications, combining OpenAI Realtime API for live agent participation, Stream Video/Chat SDKs for WebRTC conferencing and messaging, and Inngest for reliable background processing. The project showcases a modern full-stack architecture with tRPC for type-safe APIs, Drizzle ORM for type-safe database operations, Better Auth for flexible authentication, and Polar for subscription management — all built on Next.js 15 with React 19.