How to build a multi-model AI chat app with Replit
Your chat app, hosting, and Postgres database all live in a single workspace. Just describe what you need to the AI Agent (from API keys and user logins to model selection and spending limits) and it builds the entire system for you.
Replit
$ Build an AI chat app: replies streaming from my own server holding my provider key, conversations and messages in Postgres in this workspace, a model list defined once on the server, Markdown and code rendering, and a logged, capped limit on every call.
- Postgres provisioned in the workspace
- Streaming capped before testing
- Ready for you to review
What a multi-model chat app actually is
A text box, a list of replies, and a bill that grows every time somebody presses send. The first two take an afternoon. The third is what the rest of this page is about.
Building a basic chat box takes an afternoon. The real engineering goes into what happens behind the screen: managing API connections, preserving conversation history, and controlling costs.
At its core, a production-ready app handles four continuous tasks. It receives your input, streams the response in real time, saves conversation threads for later, and routes requests across different AI providers. The visual UI is just the demo everyone sees. Saving context and balancing vendor models is what makes the product truly usable.
What makes chat apps unique is that you pay for every single turn. Because AI models have no built-in memory, every new message re-sends the entire conversation history back to the API. A thread with forty messages costs roughly forty times more than the first turn. Without smart context management, your spending scales compounding with every response.
An AI chat app is essentially two products stitched together: the visual interface users see, and the billing logic that controls your API usage. Commercial SaaS tools charge high monthly seat fees to rent that second half. Building your own interface connects you directly to the API meter, giving you complete control over your margins and dramatically reducing overhead.
The thread is the product, not the text box
A single question and a single answer is a demo, and you can build one in an afternoon. What people come back for is the conversation still being there tomorrow, opening at the right message, carrying what was said before into what gets asked next, and being findable six weeks later when you half remember writing something down. Build the thread first and the text box becomes an input on it.
What you resend is what you pay for
Models have no memory between calls, so a chat app re-sends the conversation on every turn to create the impression of one. That is normal and it is also the entire cost model: the bill for message forty includes messages one to thirty-nine again. Deciding how much of the past to carry, and when to summarise it instead, is the difference between an app you leave running and one you switch off.
True “multi-model” architecture
Showing five AI models in a dropdown menu is easy. Connecting them is the hard part. Every provider uses different API formats, streaming logic, and error handling, so adding a new vendor takes a full week of coding, not just another line in a list. Don’t take model lists at face value. Always check what’s actually built under the hood.
What the meter actually reads
$0.15
The price of a million input tokens on gpt-4o-mini, the model this template falls back to, read on OpenAI’s own API pricing page in August 2026. Output runs $0.60. A ChatGPT Business seat is $25 a month billed monthly, so one seat-month buys roughly 166 million input tokens at that rate, whether the person holding it sends four messages or four hundred. The seat and the meter are not measuring the same thing, and that is the whole reason to own the interface.
developers.openai.com API pricing, read August 2026 · checked August 2026
The parts every chat app is built from
The first one is what everybody demonstrates. The other five are why anybody would still be signing in three months later.
A reply that arrives while it is written
Waiting eight seconds for a paragraph feels broken, and watching the same paragraph appear a word at a time feels fast, even though it took exactly as long. That is the biggest single difference between a chat app people use and one they close, and it is more work than it looks: the provider sends the answer in fragments over one long-running response, so your code has to read them as they arrive, cope with a fragment split down the middle, and put the whole thing on screen and into the database once it is done.
A thread that survives being left and come back to
The conversation belongs to an account, opens where it left off, and shows up in a list you can scan. The small things are what people notice: a title you can read in the sidebar, renaming, deleting, and an order that puts what you touched last at the top. None of it is hard, and all of it is the difference between a demo and something with your history in it.
A decision about how much past you carry
The model is given the conversation again on every turn, so the length of the thread is the price of the next answer. Left alone that grows without limit, which is fine at six messages and expensive at sixty. The choices are a window of recent messages, a running summary of the older ones, or a hard stop with a new thread. Pick one deliberately rather than finding out on a bill.
A picker that matches what is actually behind it
Offering several models means several vendors, and each has its own request format, streaming format and error shape. The honest options are an adapter per vendor, or one service that presents them all the same way. What you should not do is list a model you cannot reach, because the app will quietly answer with a different one and nobody looking at the screen will know.
A ceiling on a paid endpoint, not just a lock on it
Requiring a sign-in decides whose typing spends your money. It does not decide how much. You want a record of every call, a limit per person over a window you choose, and a total that stops the feature rather than emailing you about it. Watch the sign-up path too: an app that lets anybody create an account in one click has made the meter public, which is reasonable to do and unreasonable to do without a cap.
Rendering what a model actually sends back
Models answer in Markdown, so a raw reply is full of asterisks and backticks unless something turns them into headings, lists and code blocks. Code needs a monospace block with a copy button, because copying code out of a chat is most of what technical users do with one. It is a small feature that gets noticed the moment it is missing.
Own the interface or rent a seat on somebody else’s
The four products below meter three different things: a seat, an allowance of points, and a pool of credits. None of them meters the thing you are actually paying a provider for, which is tokens. One of them is a one-time licence that already does most of what this template does, and it is the row to read before you decide to build anything.
Build your own
Your own key means you pay the model’s list price per token and the bill tracks the typing. No seat, no allowance, and no monthly floor before the first message. It also means the product is yours: your name on it, your users signing in, and your decision about what to charge them.
- You pay the provider’s list price per token, with nobody’s margin on top
- Ten people cost no more than one, because there is no seat to buy
- Your own branding, your own sign-in, and your own users, which none of the four allows
- The conversations sit in your database, so searching, exporting and deleting are yours to define
- Which model answers is a setting you control rather than a catalogue somebody curates
- What a person may spend is a rule you write rather than an allowance you buy
Rent a chat product
ChatGPT Business · TypingMind · Poe · JumaWhat renting buys, and what this template genuinely does not have: a wide catalogue of models from several vendors, kept current by somebody else. Poe and Juma put many vendors behind one bill. TypingMind sells a polished client you point at your own keys. All four work the afternoon you pay for them.
- Many vendors’ models behind one bill, with new ones added as they land
- Nothing to run: no database, no functions, no deploy, and nobody to call at midnight
- Somebody else absorbs a provider changing an API or retiring a model
- A seat price or a points allowance is also a spending ceiling, and your own key has none until you write one
- Sign-in, history search and the day-to-day polish of a product with a full-time team behind it
- TypingMind in particular is a one-time licence on your own key, which is most of this template’s argument, already built
First because it is what everybody compares against, and because it prices the thing this section is about. The meter is the person: a seat costs the same in the month somebody sends four messages and the month they send four hundred, which is the arithmetic in the stat above. It is also single-vendor by construction, so the model list is OpenAI’s and the day a rival ships something better is a day you wait. What you get for it is the most polished product in this table by a distance, and for one person at $20 a month it is genuinely hard to argue with.
learn.chatgpt.com · checked August 2026
The most useful row in the table, and the one to be honest about: it is a working commercial product built on exactly the premise this guide argues for. You buy the licence once, plug in your own provider keys, and its own page notes that the price excludes "API costs". Multi-model parallel chats sit in the Premium tier. Its comparison column describes a ChatGPT or Claude subscription as "Single vendor only", which is the same point made from the other side. Read the $99 against the hours in the calculator above before you decide to build. The discount is a promotion rather than a list price, so check both figures when you look.
typingmind.com · checked August 2026
Included for what it does not tell you, which is worth as much as a price. The page served us yearly-billed figures with no tier names attached, so no month-to-month rate is quoted here. Nothing on that view says what a point buys either: different models cost different numbers of points per message, so "660 thousand points" cannot be turned into a number of conversations and any comparison you make with it is a guess. What Poe genuinely sells is breadth, many vendors’ models behind one subscription, which is the half this template does not have.
poe.com · checked August 2026
The row that agrees with us, which is why it is here. It is a team chat workspace across several vendors, and it has priced the seat away: credits are shared at the workspace level, and the page promises "no per-seat pricing ever" and "Unlimited seats on every plan". That is the same instinct as building your own, sold as a subscription, and for a team that wants it working on Monday it is a fair answer. Note the rename: team-gpt.com now redirects to juma.ai, which is a reminder to check a price rather than trust a screenshot.
juma.ai · checked August 2026
Rule of thumb, and it splits on what you want to own. If you want a better chat client for yourself or a small team, do not build this: TypingMind is $99 once on your own keys, and LibreChat is free, self-hosted and genuinely multi-vendor under an MIT licence. Both beat a from-scratch build on effort and on model breadth, and saying otherwise would be selling you something. What none of them gives you is a product with your name on it that your own customers sign in to and pay for. That is the case for building, and it is a real one: the moment other people are the users, a per-seat plan stops being a tool you buy and becomes a cost that grows with your success. Work out which of the two you are, because the answer is not close in either direction.
Why build with Replit
A real app needs somewhere durable to keep what people enter, rules about who’s allowed to see it, and a place to actually run once it’s built. Those are three separate problems, and most solo builds solve them badly, or not at all.
Replit’s Agent handles all three from one chat, in the same workspace the app ends up living in:
Describe
Tell the Agent what to build, in plain language.
Watch
It writes the code, sets up the database, and shows the app running live.
Try it
Use the real app in the preview rather than a mockup.
Publish
Take it live on Replit’s own hosting, or ask for the next change.
The build and the place it ends up running are the same workspace throughout, so there’s no separate hosting account to set up later.
One workspacebuilds, runs, and hosts it
Replit is the one tool here that also deploys what it builds. Publishing takes the same project live on Replit’s own infrastructure, with a working domain, uptime monitoring, and security scanning included.
Managed Postgres with 20GB included free
Ask the Agent to add a database and it creates the schema and wires your app to it. What you get is a real, fully-managed SQL database rather than a mocked one.
Up to 10 Agent sessions in parallel (Pro)
Core allows up to 2 parallel Agent sessions and Pro allows up to 10, so more than one part of the app can be worked on at the same time.
Pay a developer, or do it with AI
Running costs for this app scale directly with how much your users chat. The estimates below cover development only. API usage is billed separately, so you will need to code your own spending caps to protect your budget.
Hire a developer
Custom build, from scratch- Developer
- ~$10k-$41k
- Supabase (backend)
- Free tier · $25/mo (Pro plan)*
- Hosting
- $0 free tier
- Model provider
- Per token - the line that moves with use
- Build time
- ~205 hrs of their work
~$10k-$41k to build, then from $25/mo plus what people type
Our ~205-hour estimate, priced at the rates in the survey linked below: senior US developers at $100-$150+ an hour, and agencies charging 20-40% above the freelancers they bid against, which is where $50/hr and $200/hr come from. Where those hours go is not where a quote usually assumes. The text box and the first reply are a couple of days. Streaming that survives a broken connection, a second vendor, a thread still cheap at message sixty, and a limit nobody can talk their way past are the rest. If a quote says "an AI chatbot", ask which of those four it covers.
Build it with Replit
From scratch, with Replit- Replit
- Free (daily credits) to $25/month (Core) or $100/month (Pro)
- Database (built-in Postgres)
- Free to start · 20GB included
- Hosting (Replit Deployments)
- Billed separately, on top of the plan
- Your time
- ~98 hrs
Free to try the idea, ~$25-$100/month on Core or Pro while you build a real one, then whichever plan (plus any deployment cost) you keep using
Replit’s plan price and its credit grant are the same number, not a subscription plus a separate credit purchase: Core is $25/month for $25 of monthly credits (or $20/month billed annually), Pro is $100/month for $100 of monthly credits (or $95/month annually). Once you publish, Replit bills hosting through its own Deployments separately, on top of whichever plan you’re on. Budget for it as a second line, not folded into the $25 or $100.
* On this template the free-tier line to watch is the pause rather than storage. No files are kept, because attachments go to the model and are never saved, and a conversation is a few kilobytes of text. What does bite is that a free project sleeps after a week of inactivity, and an app people open when they happen to have a question is exactly the sort that goes quiet. Pro, from $25/mo, ends the pause and keeps a daily backup for 7 days.
Prices and rates from supabase.com, developex.com and replit.com, checked August 2026.
Decide before you build
Six decisions to make before writing code. Half of them directly protect your API budget from unexpected user activity.
Should you support one AI provider or multiple?
Decide now whether a second provider is a real requirement or a nice line on a feature list. One vendor is a perfectly good product and half the work. If you do want two, choose between writing a custom adapter for each or routing everything through one service that presents them identically. The vendors section below compares both approaches.
What is your hard spending limit?
Read your provider’s per-token prices before you write a single line of code, then define your limits explicitly: how many API calls or tokens per person, over what time window, and what message a user sees when they reach that limit. Deciding this now means adding a single field on a table. Deciding it after your first surprising bill means rewriting the core function that everything runs through.
How much conversation history will you send back each turn?
The whole conversation history goes back to the model on every message unless you decide otherwise, so this is a cost decision disguised as a quality one. A rolling window of recent messages is cheapest, a running summary keeps more of the context, and having no limit at all is the expensive default you get by not making a choice. Pick one strategy now, because it shapes your database schema.
Who gets access, and how will you protect your API credit card?
A one-click demo account is excellent for showing the app off, but it also gives open access to your API credit card to anybody who finds the page. Decide whether you want open sign-up, email invitations, or a demo account that is capped much harder than a paid user account. Whatever you choose, usage limits must be set per account rather than per person, because accounts are free to create.
How long will you retain user conversation data?
Conversations accumulate quietly and they are the most personal data in this app. Decide upfront whether threads live forever, automatically expire after a set period, or can be permanently deleted on request. Then decide the same rule for file attachments, which in this template are sent to the model and never stored locally, and state this plainly to whoever signs in.
Are you building an internal tool or a commercial SaaS?
Building a tool for yourself and building a product for external customers are two completely different apps. Your own internal tool needs no branding, no billing system, and no legal terms. A product other people sign into needs all three, plus a clear explanation of what happens to the data they type. Decide which one you are making before designing the first screen, because it changes your database schema and authentication flow.
Comparing your build options
Building a basic chat interface is fast. The hard part is everything behind it: handling connection drops during streaming, managing token costs on long threads, and setting spending limits for users. Here are three ways to build the exact same product.
Getting one reply out of a model takes an afternoon. The months go on everything around it: a reply that arrives a word at a time and survives a dropped connection halfway through, a thread that still opens correctly on the fortieth message, a second vendor whose request shape and streaming format agree with the first one in your own code and nowhere else, and a limit on a button that spends real money every time somebody presses it.
A kit gives you a sidebar, a message list and a text box, which is the silhouette of this app and almost none of the work. Nothing in a kit knows how to stream, what to do when the stream stops mid-sentence, that you are billed for the entire conversation again on every turn, which vendor is answering, or that the person typing is signed in and still able to spend more of your money than you meant.
One request at a time to the Agent, with the Postgres, the server and every screen inside the workspace that ends up hosting them. Two things land on your own server here that sit elsewhere on the other tools: telling the database who is asking, and holding the provider key that every reply spends against. On a chat app those two are the same server, which is convenient and worth being deliberate about.
Estimate your exact build timeframe
Customize your feature list below to see how build time changes. If you only need a single AI model or a basic prototype, uncheck unused items to reduce the estimate.
Your estimate
98 hrs
start to finish
Based on the 7 of 7 features you’ve selected, plus ~21h of groundwork. Toggle any on the left to watch the number move, and open the groundwork row to untick what you have already, such as a database that is already running or going live if you are only building a mock-up for now.
A rough estimate, not a quote. Real time depends on how much you customize and how clean your data is.
Let’s set up the tools you need
Replit runs entirely in the browser, and it’s the one tool here that also hosts what you build, so no GitHub account is required first. Before step 01: an account and a plan. A database comes later, the moment your app actually needs one, and GitHub whenever you want a copy of the code outside Replit.
Replit account
Sign up and you land in a workspace with an Agent chat, the code, and a live preview side by side, with nothing to install.
Sign up for ReplitReplit subscription
Starter’s free daily credits are enough to try an idea, not to finish one. Core is $25/month billed monthly, or $20/month billed annually, for $25 of monthly credits and up to 2 parallel Agent sessions. Pro is $100/month monthly, or $95/month annually, for $100 of monthly credits, more collaborators, and access to the strongest available models. The price you pay and the credits you get are the same number on both plans, so you have no separate subscription-plus-credits split to work out.
Compare Replit plansReplit database (Postgres)
Every Replit app includes its own managed Postgres database with 20GB of free storage. Ask the Agent to add one and it creates the schema and connects your app to it, with no separate account to create anywhere else.
Replit’s built-in database, Replit docsGitHub connection
Not needed to start, and not needed as an undo either, because Replit checkpoints the whole workspace as the Agent works. Connect a repository from the Git pane, free on every plan, and a copy of the real code lives outside Replit under your own account. Worth doing once the project is one you would hate to lose.
Using the Git pane, Replit docsThe first two are all you need to start. Everything here stays inside the one browser tab, the app included once you publish it, and the GitHub copy is the one deliberate exception.
Build your chat app, one Agent message at a time
You describe a piece, the Agent writes it, and a checkpoint is taken so a bad change is a click back. Three things shape the order. Sign-in and the access rules come early, and on this tool they need something extra, because with no hosted identity service your own server declares who is asking before any policy can act. The ceiling goes in with the first reply. And the model picker gets its own step at 05, once something answers.
- 01
One message for the app, Postgres, and the ground rules
The Agent can create the app and provision the database beside it in the same breath. Spend the rest of the message on the rules the build leans on.
PromptSet up the projectCreate a new React 18 + Vite + TypeScript app with Tailwind and its own server, and add a Postgres database to this workspace. Keep the database connection string in Secrets, never in anything the browser downloads. Then write a short PROJECT_NOTES.md fixing the vocabulary for a chat app (conversation, message, model, provider, stream, attachment, call log, limit) and recording two standing rules. One: my model provider key stays in Secrets, so every call to a model runs on my own server, which establishes who is asking before it does anything at all. Second: every model call is logged and checked against a limit I configure before it is made, because each one charges my card, the whole conversation is sent again on every turn, and a signed-in user is not a spending cap. Also note that because this workspace has no hosted identity service, my own server is what declares who is asking before any request touches a table. Start the app so I can see it boot.
That last sentence carries more weight here than on the other tools. Nothing is going to hand the database an account on your behalf, and a policy reading a declaration nobody made does not complain. It admits everybody, and on this app what it admits everybody to is a text box that spends your money.
- 02
Schema, sign-in and the boundary, at a checkpoint
One idea rather than three on this app. Take a checkpoint once it is right, because everything after reads this shape.
PromptModel it and draw the boundaryWrite the data model against the workspace Postgres. Conversations with an owner, a title and a last-updated time. Messages belonging to a conversation, with the text, whether a person or the model wrote it, the model that answered, and attachment metadata. A calls table logging every model request: who, which conversation, which model, tokens in and out, whether it succeeded and an estimated cost. Then add email and password sign-in on my own server, with sessions, and have the server set the database session variable that identifies the account on every request before any query runs. Then row-level security on every table, written against that variable: a row is reachable only by the account it traces back to, with explicit WITH CHECK on every insert and update, and the update rule on a message must forbid changing which conversation it belongs to. Then prove it: two accounts, and show me the second cannot read or move the first one’s messages.
Watch for the declaration being set on every request rather than once when the server starts. A connection reused between two people with the identity of the first one is the failure mode here, it is silent, and the proof above is what catches it.
- 03
The first streaming reply, capped in the same message
Your own server holds the key and enforces the limit. Ask for both together so there is never a checkpoint where one exists without the other.
PromptStream one reply, with a ceilingBuild the chat call as a route on my own server, with my provider key in Secrets and nowhere else. It requires a signed-in user and refuses with a 401 otherwise, sends the conversation to the model, and streams the answer back to the browser as it arrives. Do the streaming carefully: read the response in chunks, keep a buffer for a fragment split across two chunks rather than dropping it, and save the finished message when the stream ends, including when the connection drops halfway. Before it contacts the provider at all, write a row to the calls table and check two limits I can configure: calls per account in a rolling window, and a total across the app. Count both in the database rather than in memory, because a deployment can run more than one copy of this server and a limit held in one process is not a limit. Over either, return a clear "you have reached your limit for today" and do not call the provider. Then the chat screen, and prove the limit refuses an eleventh call when I set the limit to ten.
The line about counting in the database rather than in memory is the one to insist on here specifically. An autoscaling deployment starts more copies of your server under load, and a counter held in one of them resets every time another starts, which is exactly when you are least watching.
- 04
The sidebar, the titles, and what you resend
The conversation list people live in, and the decision that stops a long thread getting more expensive every turn. Take a checkpoint after it.
PromptBuild the thread and the sidebarBuild the conversation sidebar: a list ordered by what I touched last, opening one loads its messages in order, plus renaming, deleting and a new-conversation button. Give a conversation a title from the first exchange rather than from the first fifty characters of what I typed, and never overwrite a title I have renamed by hand. Then change what gets sent to the model: rather than the whole thread every turn, send the most recent messages up to a token budget I can configure and a short running summary of anything older, stored on the conversation and updated as messages fall out of the window. Keep the full history in Postgres. While I am testing, show the token count for the next request on screen.
Check the summary is written when messages fall out of the window rather than on every send. A summary regenerated each turn is itself a model call, so the change that was meant to reduce your bill quietly adds to it.
- 05
Make the picker tell the truth
The step this template needs more than most. A dropdown with five names in it is one screen, and whether five vendors sit behind it is a different question.
PromptMake the picker honestDefine the list of models in one place on my server, with the vendor, the id and the per-token prices for each, and have the picker read that list rather than a separate one in the frontend. The server must refuse a model that is not in it with a clear message rather than silently substituting a default. Record on every message which model actually answered it and show that under the reply. Then, if I want a second vendor, add exactly one: a separate adapter for its request shape and its streaming format, behind the same route and the same ceiling, with its own key in Secrets. Tell me plainly which models are actually reachable and which are only names, and do not add a name I cannot reach.
Because everything sits on your own server here, the model list, the prices and the ceiling can genuinely live in one file. Ask for that explicitly, because three copies of the same list in three places is how a picker and a function drift apart in the first place.
- 06Destination
Markdown, attachments, and one real conversation on the published copy
The rendering, the composer’s extras, your own name on it, and then a rehearsal on the published address rather than the workspace preview.
PromptFinish it, then rehearseFinish the app. Render replies as Markdown with headings, lists and code in a monospace block with a copy button. Add attachments to the composer, and tell me which trade you have taken: sending the file to the model without keeping it, which needs no storage, or putting it in this workspace’s object storage and serving it through my server. Add dictation using the browser’s own speech recognition, with a sensible message in browsers that do not offer it rather than a dead button. Put my own name, colours and copy on the header and the sign-in page. Then publish it, and walk me through one real conversation on the published address: sign in as a second account, hold a conversation long enough to matter, confirm that account cannot see the first one’s threads, and compare what my calls table reports against my provider’s own usage page.
Check who the published app is visible to before you invite anybody. Publishing is what sets that, and on this application the setting decides who can spend against your provider key.
Protecting your app: authentication, security, and API costs
AI chat apps require protecting three things: sensitive user conversations, database privacy, and your API budget. Here are the core security rules to follow before launching.
Logins your server owns
There is no hosted identity service in this workspace, so sign-up, sign-in, sessions and password resets are code on your own server rather than a product you switch on. Use a well-known library rather than writing password hashing yourself, and treat the session cookie as the thing that decides everything else in this list.
The model route requires a signed-in user
The single most important line in this build. Your server holds the provider key, so a route that answers without checking who is asking is not a data leak, it is an invoice: somebody finds it, loops it, and you pay for every call. Check the session first, before anything else in the handler, and check it again on the day you add a second route that calls a model.
Combine user login with hard spending limits
Authenticating users is only half the battle, and this part is up to you to implement. Requiring a login decides who is allowed to spend your money, but not how much they can spend. To protect your budget, you need a system that logs every API call, enforces usage quotas per account over a set timeframe, and hard-stops the feature when limits are reached instead of just sending you a warning email afterward. An unmetered paid endpoint is a critical financial vulnerability: treat it like a major security issue.
Count the limit in the database, never in memory
The version of that rule specific to this tool, and the one people get wrong. An autoscaling deployment runs more than one copy of your server under load, so a counter held in a variable is per copy and resets whenever a new one starts. That is precisely the moment your app is busiest. Count in Postgres, where every copy sees the same number.
Where the checking actually happens
Your server declares who is asking by setting a session variable on the connection before each query, and the row-level policies read it. Two things follow. The declaration has to be set on every request rather than once at startup, because connections are reused between people. And a policy reading a variable nobody set does not complain, it just admits everybody.
Keep your database ownership model simple
In this app architecture, every conversation belongs to a single user account, and every message belongs to a single conversation thread. This means every database access rule reduces to one simple check: "does this specific record trace back to the user making the request?" There are no complex user roles or shared workspaces here. This makes it the simplest security model possible and leaves no hidden edge cases where authorization bugs can hide.
Validate data constraints on record updates
This is a critical database rule to learn, and chat applications demonstrate it clearly. Every update rule in your database needs to answer two questions. The obvious first question is whether a user is allowed to edit a row at all. The often-forgotten second question is what that row is permitted to turn into. In a chat app, this prevents a vulnerability where a message could be edited to move it into a conversation thread owned by another user. Security rules must check both the existing column data on the way in and the updated data on the way out.
Restrict database read policies to prevent leaks
The development history of this template serves as a great lesson, which you can see in its database migration logs. It initially launched with a Row-Level Security (RLS) policy that accidentally allowed any logged-in user to read every row in the profiles table, including user email addresses. A later migration removed that rule and added a stricter one alongside another permissive policy, and a third migration finally removed that second policy too. It took two extra attempts to get a single read rule right on the simplest table in the app. Whenever you write a read rule that grants access to "anyone", check carefully which specific columns you are exposing.
Store API keys securely and disclose data usage
Your AI provider API key must live strictly in your server-side environment secrets and nowhere else. If you place an API key in client-side app code, anyone can extract it and spend your money. Beyond security, consider privacy: everything a user types is sent directly to an external AI provider. In a chat app, that text often includes sensitive personal notes, unreleased ideas, or client information that users wouldn’t share publicly. Decide what data is allowed to leave your app, state this clearly to users when they sign up, and read your AI provider’s privacy terms regarding how prompt data is handled.
Backups, and how far back you can go
Check what your plan actually retains for this workspace’s Postgres before you rely on it, and take your own dump on a schedule if the answer is thinner than you assumed. Worth doing here for a reason specific to chat: people treat a thread as a notebook, and the value of it to them is the history rather than the last answer.
One rule outranks the rest here: the model provider key belongs in Secrets only: never in anything the browser downloads, and never in a repository. A key that gets out is burned, and this is the one somebody will actually spend: replace it the same day and check your usage page for what was done with it.
What speeds the build, and what slows it
Speeds the build
- One small, specific request per message, checked in the live preview before the next one
- Letting the Agent provision the database from the chat instead of wiring one up by hand
- Running two Agent sessions in parallel on unrelated parts of the app, once your plan allows it
- Rolling back to a checkpoint the moment a change goes wrong, instead of unpicking it by hand
- Reviewing what Publishing changed, meaning the domain, who can reach the app, and the machine it runs on, before the first release
Slows the build
- Asking for the whole app in one message instead of one piece at a time
- Building screens for data that isn’t in the database yet
- Running unrelated Agent sessions against the same files at the same time
- Letting several risky changes stack up before checking whether any of them actually broke something
- Publishing without checking who the app is visible to first
Connecting GitHub (Optional)
Every change in Replit is saved automatically without any technical setup. Checkpoints are the day-to-day undo. You only need to link GitHub if you want a private copy under your own control or plan to hand the codebase over to external developers.
Every milestone is already saved
Replit’s Agent creates a checkpoint automatically at key points as it works: a full snapshot of the files, the configuration, and even the AI conversation itself, not just the code.
Checkpoints and rollbacks, Replit docsRolling back restores the whole workspace
One click returns your project to an earlier checkpoint (files and configuration together, and optionally the database), which is broader than a typical code-only undo, so a rollback after real data has changed is worth a second look before you confirm it.
GitHub keeps a copy outside Replit
Connect a repository from the Git pane, free on every plan, and stage, commit, and push changes back to GitHub with a click, or pull in anything changed outside Replit.
Using the Git pane, Replit docsIt’s also how an existing project gets in
Point Replit at a public repository’s URL for a fast import, or use the guided import for a private one. Either way, Replit detects the stack and installs everything on its own.
Import from a provider, Replit docsYou rarely type git commands
The Git pane’s buttons cover staging, committing, and pushing. If you’d rather type them yourself, the workspace Shell stays in sync with whatever the pane just did.
Going live without external hosting
Skip third-party hosting and external database setup. Your database, backend, and domain live in the same Replit workspace. Just click Publish to go live.
| Host | Best for | Notes | Free tier |
|---|---|---|---|
| Autoscale | Most chat apps | Grows with traffic and shrinks back when nobody is typing, which suits this app well, because people use a chat app in bursts and nothing needs to run overnight. It is the default choice and enough for everything a person clicks. Two things to confirm: that your ceiling is counted in the database rather than in one process’s memory, since more than one copy of your server can be running, and that a long streamed reply is not cut short by a request timeout. | Metered - billed with your plan |
| Reserved VM | Long replies and steady use | Dedicated compute that never sleeps. The row to compare seriously on this particular app, because a streamed answer holds one response open for as long as the model takes, and a large model on a long question can take a while. Also the simpler answer if a team uses it through the whole working day rather than in bursts. | By machine size - billed with your plan |
| Scheduled | Tidying up, if you add any | Runs on a timer rather than answering requests. Nothing in this build needs it as it stands, but it is where a nightly job that emails you the week’s model spend, or one that ages out old conversations, would belong, and it publishes separately from the app. | Metered - billed with your plan |
| Static | Not this app | Files only, with no server behind them. Listed to rule out: your own server holds the provider key, enforces the ceiling, declares who is asking and streams every reply, none of which exists here. | Metered - billed with your plan |
All of these are Replit rather than a third party, so the choice is shape rather than vendor. Review who the app is visible to before the first release, since Publishing is what sets it, and on this application that setting decides who can spend against your provider key.
One thing to check on the day you publish, and it is not the hosting. Hold a conversation long enough for a reply to take a while, on a phone on mobile data rather than at your desk. A streamed answer runs over one long-lived response, so a request timeout or a flaky connection leaves half an answer on screen and half a row in your database. Confirm what the published app does with that, and confirm the ceiling is counted in the database rather than one process’s memory, because a limit held in memory resets every time a new instance starts.
Your database is already part of the workspace
Nothing to connect. Conversations and messages are small rows of text, so this is the least demanding database in the catalogue, and nothing here needs file storage at all.
| Service | Best for | Notes | Free tier |
|---|---|---|---|
| Replit Postgres | Data, built in | Managed Postgres with 20GB included free, provisioned from the same chat that builds the app, and since it is ordinary Postgres the access policies from step 02 and the calls table the ceiling reads both work exactly as they would anywhere else. What it does not include is a hosted identity service, which is why your own server declares the account before any policy can act on it. Conversations are text, so the storage figure is not the line to watch here. The line to watch is how many copies of your server are running when the ceiling is counted. | Free to start · 20GB included |
How you reach a second vendor
The answer may well be that you do not, and that is a valid technical choice rather than a compromise. One provider is a complete product: this template ships that way, and most users never need more. Read this section only when you have decided you genuinely want to offer models from different providers in the same dropdown menu.
The cheapest per token, because nobody sits in the middle, and the most work per vendor. Each one needs its own key, its own request shape and its own streaming format handled in your function, which is roughly a week for the second and less for the third. Choose this when the list is short and you expect it to stay short.
developers.openai.com · checked August 2026
Listed separately because it is the specific second vendor this template’s picker already names and does not reach. Its free tier makes it cheap to try before you commit to the work, and its paid text price sits between the two OpenAI models most people use, so what a conversation costs starts to depend on which model somebody picked. Price them side by side before you let users choose freely.
ai.google.dev · checked August 2026
One request shape and one streaming format for every model, so a new vendor becomes a string in a list rather than a week of work. Read the fee correctly, because it is easy to misread as a tax on inference: it applies when you load credit, so $100 of credit costs $105.50. Against a week of building and maintaining an adapter that is cheap, and against staying on one provider you are happy with it is money for nothing.
openrouter.ai · checked August 2026
Do the arithmetic before you choose, because the fee is smaller than it looks. Take the conversations you expect in a month, multiply by the tokens a typical one sends, and remember that a thread resends itself on every turn. At gpt-4o-mini rates a thousand medium conversations a month is a bill in single-figure dollars, and 5.5% of that is cents. At that size the decision is about your own time rather than the fee, so the answer is usually the aggregator or nothing at all. The fee starts to matter at a volume where you would be negotiating with providers directly anyway. Figures read on each vendor’s own page in August 2026.
Where AI genuinely helps a chat app
The AI is the app here rather than an addition to it, so the first prompt below is not a feature. It is the guard rail the one model-calling function is missing. The four after it are things you would actually want next, and your provider key stays in that same function for all of them.
Log every call and put a ceiling on it
Nothing records what the model was asked or what it cost, so the expensive calls are the ones with no history. Build this before anything else below, because everything below spends money too.
Add a calls table that records every model call (who made it, which conversation, which model, how many tokens went in and came back, whether it succeeded, and a cost estimate) and write to it from the chat function on every call, successful or not. Then add a ceiling: a limit per account per rolling window and a total across the whole app, both settings I can change, checked inside the function before it contacts the provider and returning a clear "you have reached your limit for today" rather than an error. Apply a tighter limit to demo accounts than to real ones. Do not let the client send the limit or the cost, because both are read on the server. Then add a small usage panel showing calls and estimated spend for the current period, by account.
Stop paying for the whole thread on every message
The conversation is resent in full on every turn, so a long thread quietly gets expensive. This is the one change that makes a chat app cheaper to run without making it worse to use.
Change what gets sent to the model. Keep the most recent messages in full up to a token budget I can set, and for anything older send a running summary instead, stored on the conversation and updated when messages fall out of the window. Show me the token count for the next request in the interface while I am testing, so I can watch the effect. Keep the full history in the database untouched, because this is about what is sent rather than what is stored, and make the budget a setting rather than a number in the code.
Give a conversation a title worth scanning
A sidebar of threads named after the first sentence somebody typed is hard to search by eye, and it is the first thing that goes wrong once there are forty of them.
After the first exchange in a conversation, make one cheap model call to write a short title of at most six words describing what the conversation is about, and save it on the conversation. Do it once rather than on every message, let me rename it by hand afterwards and never overwrite a title I have edited myself, and count that call against the same log and ceiling as everything else. If the call fails, keep the current title rather than showing an error.
Ask before assuming somebody wants a picture
Deciding between a text answer and an image by looking for words like "image" or "draw" in the message is cheap and wrong often enough to notice, and it is wrong in the expensive direction.
Replace the keyword test that decides whether a message is an image request. Give me an explicit control in the composer for asking for an image, so the choice is mine and the app never guesses. Where you keep any automatic detection at all, make it a separate cheap classification call rather than a substring match, show me which mode a message was sent in, and let me resend the same message in the other mode without retyping it. Count image calls against the ceiling at their own higher cost rather than as one call.
Search your own history, and answer from it
After a few months the conversations know things you do not: what you asked before, what worked, and the answer you are now trying to reconstruct from memory.
Add search across my own conversations. Do the finding with database queries over the message text rather than with a model, show the matching messages with their conversation and date, and let me open one at the right place. Then add an optional panel that answers a question from my own history, sending only the messages the query actually matched and quoting which conversation each part of the answer came from. Never send my whole history in one request, and where the search finds nothing, say so instead of answering from general knowledge.
A cheap model is plenty for most of the prompts above. Save Pro’s stronger models for the one or two spots where the extra reasoning actually pays for itself. Add any provider key through Replit’s own Secrets tool rather than hard-coding it, and keep every AI feature behind one server-side function so a single key covers the whole app.
Get a head start with our template
Every route above begins at an empty folder, and there is one that does not. This app streams already, keeps every conversation under its own sign-in already, and renders what a model sends back already, so the weeks that the streaming, the thread and the accounts would have cost turn into an afternoon of adding your key and your name.
Multi-LLM Chat
The exact chat app this guide builds, packaged so you can open it, point it at your own backend, and make it yours from there. A multi-model chat app with streaming replies and saved conversation history. Switch between models like GPT-5, GPT-4o and Gemini 2.5, all running on your own provider key as a private, branded product.
The key benefits of starting with a template
Streaming replies, saved conversations, sign-in with a one-click demo, attachments, voice input, and Markdown rendering with code blocks. Read the security section above before you go live, and the fourth FAQ below for the one claim to check.
Building the core from scratch
~98 hrs
Opening the template, already built
~1 hr
~97 hrs of building you skip
Two deliberately different measurements. The build is the ~98 hrs. The hour is what adoption costs: a database of your own, a provider key in the function’s secrets, your name on the header, and one conversation held end to end to prove it works. Setting your own spending limit costs the same on either path, so neither figure includes it.
Streaming replies, handled properly
The reply arrives a word at a time over one long-lived response, and the code that reads it keeps a buffer for fragments that arrive split down the middle rather than dropping them. That buffering is the part a first attempt gets wrong, it produces answers with words missing, and it is already done here.
Conversations saved under your own sign-in
Email and password sign-in, a session that survives a refresh, and a sidebar of saved threads ordered by what you touched last, with renaming and deleting. There is also a one-click demo account for visitors, which is genuinely useful on a landing page and is the first thing to put a tighter limit on.
A composer that takes files and speech
Up to ten attachments at 20 MB each go to the model with your message, and dictation into the text box uses the browser’s own speech recognition, so it costs no tokens at all. Two honest limits: the browser dictation works in Chrome and Edge and largely does not in Firefox, and attachments are sent rather than stored, so the file name survives in the thread and the file itself does not.
Replies rendered the way models write them
Models answer in Markdown, and this renders it: headings, lists, and code in a monospace block rather than a paragraph full of backticks. Light and dark themes are both there, and it has been tested on real phones rather than only in a narrow browser window.
The provider key never reaches the browser
Every model call goes through one server-side function that checks for a valid session first and refuses without one, and your key lives in that function’s secrets. It handles the provider saying "slow down" gracefully too. What it does not do is cap anything, which is why the first prompt in the AI section above exists and why it is not optional.
One account per conversation, 11 live access policies
Every row traces back to the account that owns it, and 11 live row-level security policies out of 13 written decide who may read and change each table. Two were removed in later migrations, both of them read rules that had been too generous. There are no roles here, so everyone who signs in can do the same things, which is the right shape for a personal assistant and something to change deliberately if you add an admin.
From founders who build on our templates
We needed a live product in front of users fast. Instead of building from scratch, I grabbed this template, customized the logic with AI, and shipped in several days. What usually takes a dev team weeks took us a weekend.
Jeevan ThomasFounder & CEO, Hado.aiCommon questions
Only one, and this is the first thing to know before comparing it with anything. The model picker lists five names and one of them is Gemini 2.5 Flash, while the function behind it calls OpenAI and nothing else. Pick a model it does not recognise and it quietly answers with the default instead, which is currently gpt-4o-mini, with nothing on screen saying so. So what you are buying is a polished single-vendor chat app with a picker that is ready for more, rather than a working multi-vendor one. The vendors section above is the honest answer to what adding a second one costs, and the first build step in this guide has you make the picker tell the truth before you do anything else.
As it stands, yes, and it is the first thing to add. The model function is properly locked to signed-in users and handles the provider saying "slow down", so an anonymous stranger cannot call it directly. What is missing is any cap on somebody who is signed in: no log of calls, no quota, no rate limit, and no total. Two things make that sharper here than on most apps. Signing up is one click, because the app ships a demo-account function anybody can trigger. And a conversation resends itself to the model on every turn, so cost climbs as a thread gets longer. The first prompt in the AI section above adds the log and the ceiling together.
Whatever your provider charges for the tokens, and the answer that matters is the one you measure rather than the one you read. Two things to know before you look. Prices are per million tokens and differ by an order of magnitude between a small model and a large one, so which model somebody picks changes the bill more than how much they type. And the whole thread is sent again on every turn, so the fortieth message costs roughly forty times what the first one did. Send a realistic conversation with the model you plan to default to, then read your provider’s own usage page. That measurement is worth more than any figure quoted anywhere else.
No. Up to ten files at 20 MB each go to the model with your message, and only the name, size and type are kept on the message afterwards. Reopen the conversation tomorrow and you will see that a file called quarterly.pdf was attached and you will not be able to open it. That is a deliberate trade rather than an oversight, because it means the app needs no file storage and no rules over it, but it does mean "file attachments" promises less than a reader might assume. Keeping the files is a described addition: a storage bucket, access rules over it, and a link on the message.
Yes, through the same function, and the way it decides to is worth changing early. Rather than giving you a control, it looks at your message for words like image, picture, photo or draw, and sends anything containing one to the image endpoint instead of the chat model. So a question about optimising image loading in your code comes back as a picture, and image calls cost considerably more than text ones. The fourth prompt in the AI section above replaces the guess with a control you press on purpose.
It works where the browser supports it, which in practice means Chrome and Edge, and largely not Firefox. It uses the browser’s own speech recognition rather than sending audio to a model, which is why it costs nothing per use and why it is not consistent between browsers. Dictation that behaves the same everywhere means sending the audio to a transcription model instead, which is a described change and adds a per-minute cost to a feature that currently has none.
Several people, yes, and each one sees only their own conversations. Different permissions, no: this template has no roles at all, so everyone who signs in can do the same things. An administrator who can see usage, or a reviewer who may read a thread they did not write, is a described addition rather than a setting. Think about it before you add one, because a conversation is the most personal thing in this database and somebody who can read every thread is a decision worth making deliberately.
Yes, and that is the main reason to start from this rather than rent something. You get the full source under a licence that allows client work, so the name, the colours, the copy and the domain are yours to change. Charging your own users means adding billing, which this template does not include: a payment provider, a plan per account, and a link between the plan and the limits you set. Add the spending ceiling first, because a paid plan whose users can cost you more than they pay is a worse problem than no plan at all.
Three suppliers. A database, a host, and the model provider. The first two have free tiers you can stay on for a long time, because conversations are small rows of text and no files are stored. The third is the one that tracks how much people type and has no ceiling until you build one. If you upgrade anything first, make it Supabase Pro from $25/mo, and do it for the pause rather than the storage: a free project sleeps after a quiet week, and an app people open when a question happens to come up is exactly the sort that goes quiet.
Nothing here is proprietary. Conversations and messages sit in plain PostgreSQL tables that any Postgres host accepts from a standard dump, and the messages are ordinary text. The model calls go to your provider on your own key, so moving to a different vendor is a change in one function rather than a migration. The only thing that does not come with you is anything that was attached rather than typed, because attachments were never stored.
Yes, and every host listed above attaches one in a few clicks with HTTPS included. Do it before you invite anybody, because the domain is on every sign-in link and every password reset, so moving afterwards breaks those links for the people who already saved them.
No. You describe what you want in the chat, and the Agent handles the rest: the code, the database, and a live version of the app right there in the workspace. The setup section above covers the account and plan you need first.
Replit hosts it. Publishing takes the same project live on a Replit domain, or your own if you connect one, with monitoring and access controls included, so you never open a separate hosting account.
Starter’s daily credits and a paid plan’s monthly grant both refill on their own schedule. Hitting either limit mid-build doesn’t touch what you’ve already made. Move up a plan for more headroom right away, or wait it out.
References
Sources checked August 2026- 01Pricing (plans, per-seat and per-user rates), ChatGPT docs. learn.chatgpt.com
- 02Pricing (one-time licence tiers, bulk licence, bring-your-own-key terms), TypingMind. typingmind.com
- 03Subscription plans (points allowances, yearly-billed rates), Poe. poe.com
- 04Pricing (workspace credits, seat policy), Juma. juma.ai
- 05API pricing (per-million-token rates by model), OpenAI. developers.openai.com
- 06Gemini API pricing (paid-tier rates, free tier), Google. ai.google.dev
- 07FAQ (markup policy, credit and bring-your-own-key fees), OpenRouter. openrouter.ai
- 08LICENSE (MIT), LibreChat. github.com
- 09Pricing (Pro plan, free-tier project pausing, backups), Supabase. supabase.com
- 10Web developer hourly rates 2026 (freelance and agency benchmarks). developex.com
- 11Row Level Security, Supabase docs. supabase.com
- 12Edge Functions secrets and environment variables, Supabase docs. supabase.com
- 13Pricing (Starter, Core, Pro), Replit. replit.com
- 14Built-in database, Replit docs. docs.replit.com
- 15Publishing overview, Replit docs. docs.replit.com
- 16Deployment types, Replit docs. docs.replit.com
- 17Checkpoints and rollbacks, Replit docs. docs.replit.com
- 18Using the Git pane, Replit docs. docs.replit.com
- 19Import from a provider, Replit docs. docs.replit.com
- 20Secrets, Replit docs. docs.replit.com
This guide is general information, not legal advice. What a model provider may do with what you send it, and what you must tell the people signing in to your app about where their conversations go, are set by that provider’s terms and by your own local rules, so read both before other people type anything into what you build. Third-party prices, plan terms, and market rates are quoted from the sources above and were last checked on the date shown. Vendors change them without notice, and model prices move faster than anything else here, so confirm before you budget. Build hours and the cost estimates derived from them are our own estimates, not quotes. Replit is a product of Replit, Inc. Verify current capabilities and pricing before relying on them.