Build a ChatGPT clone
The modules, routes and components behind the example's /assistant and /knowledge pages, from a stored chat to tenant keys and metering.
The Next.js example's /assistant page is a chat app on the
AI chat block and the AI SDK: a chat
list, branching messages, resumable streams with stop, file uploads, a
knowledge search tool and memory. This guide walks through it in the order
you would build it. Run it with pnpm dev:portless and sign in as
member@acme.test (password password123); without AI_GATEWAY_API_KEY
a scripted model answers, so it runs offline.
The modules
sql: {
modules: {
streams: { api: "api" },
"ai-chat": { api: "api" },
"ai-files": { api: "api" },
knowledge: { api: "api" },
memory: { api: "api" },
agents: { api: "api" },
connectors: { api: "api" },
"ai-tasks": { api: "api" },
"ai-providers": { api: "api" },
"ai-cache": { api: "api" },
},
},| Module | Gives the clone | Page |
|---|---|---|
ai-chat | chats, folders, pins, the message tree, runs, sharing and the catalog | AI chat |
streams | resumable answers that survive a reload | Streams |
ai-files | uploads read as the caller, and generated files | AI files |
knowledge | documents chunked and embedded for the search tool | Knowledge |
memory | facts and core memory per user | Memory |
agents | custom assistants with their own instructions and tools | Agents |
connectors | MCP servers with per-user OAuth | Connectors |
ai-tasks | prompts on a schedule | AI tasks |
ai-providers | tenant keys, batches and sandboxes | AI providers |
ai-cache | repeated model calls answered from Postgres | AI cache |
Run better-supabase sql sync, generate a migration with
supabase db schema declarative sync, then better-supabase sql data.
The chat route
createAssistant from better-supabase/ai-sdk/chat is the whole server
side: it stores the user's message, runs the model, streams the answer
through the stream store and saves it when it ends. The example builds one
per process in src/features/assistant/assistant-server.ts and mounts it
on three routes:
| Route | Does |
|---|---|
POST /api/chat | stores the message and streams the answer |
GET /api/chat/[id]/stream | resumes the answer after a reload |
POST /api/chat/[id]/stop | stops the answer |
assistantContext builds the per-request context: the caller's chat block,
their files, the knowledge search tool and their memory, all read through
RLS as the signed-in member.
The client
useAssistant from better-supabase/ai-sdk/react is useChat wired to
those routes. The chat list, the new-chat form and the
stored chat live in src/features/assistant/components. Edit and
regenerate create sibling messages; messages.siblings and
messages.switchBranch move between them.
Files and knowledge
Uploads go to Storage as the caller, and aiFileDownload reads them back for
the model, so a member never reads another member's file. /knowledge
ingests documents into the knowledge block; searchTool gives the model a
tool that searches them with the tenant's embeddings.
Memory
withMemory adds the user's core memory to the instructions, and
memoryTool lets the model save and recall facts. Memory is per user and
per organization.
Tenant keys, metering and caching
The example's run adds the organization's own provider keys with
byokOptions, so a tenant that saved an Anthropic key pays for its own
calls (tenant keys). Register
meterTelemetry in instrumentation.ts to meter
every call on the usage block, and wrap deterministic calls such as titles
or summaries with cacheMiddleware.
Beyond the example
The blocks hold more than the example shows:
- Plans gate models through
ai_model_catalogandusageQuota; an empty quota answers with a 429 andRetry-After. - Agents run as a
ToolLoopAgentwith tool approvals, and MCP connectors keep each user's tokens in Vault. - AI tasks run a prompt on a cron, and batches run thousands at the batch price.
- Sharing by link (
shares.create), temporary chats thatchats.purgeremoves, feedback and moderation events are chat block calls.
Last updated on
eve on Supabase
Run eve agents on Supabase with the Workflow World on Postgres, Supabase sign-in on eve routes, connections over credential providers, memory, sessions in the chat tables and the inbox as a channel.
Build a workflow builder
The modules, routes and components behind the example's /workflows pages, where members draw a graph, publish it and watch each run on the canvas.