Neo Chat: A Self-Hostable AI Workspace Where the Browser Holds the Data
A local-first AI chat workspace for models, agents, skills, plugins, search, RAG, voice, memory, and artifacts.
At a glance
- What is it?
- Neo Chat is a Next.js chat workspace from u14app that connects your own model providers and keeps conversations in browser storage by default. The interesting part is the storage model, and the part to plan around is that agent and research runs die when you close the tab.
- Who is it for?
- Adopt Neo Chat if you want a single-user or small-team chat workspace where model keys stay yours, conversations stay in the browser, and you are willing to run the Docker image or a Vercel/Cloudflare deployment. Skip it if you need multi-user accounts: the README states the deployment password is an access gate, not an account system.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Neo Chat solves, and who it is actually for
Most hosted chat products make the same trade: you get a polished interface, and the provider holds the conversation history, the uploaded files, and the model routing. Neo Chat inverts that. The README describes it as bringing multi-model chat, agents, and deep research into a self-hostable workspace, with conversation history kept in the browser by default. You connect Google, OpenAI, Anthropic, or any OpenAI-compatible endpoint, and the requests go out through the app's own API routes.
The audience is narrow and specific. It fits an engineer or a small team that already pays for model API access, wants one interface across several providers, and would rather run a container than trust a third party with internal documents. The repository is TypeScript throughout, built on Next.js, React, and Zustand, so it also suits people who intend to read the source and patch it. It does not fit organisations that need per-user accounts, audit trails, or an admin console. The README is explicit that the deployment password is an access gate, not a multi-user account system, and that local-first storage does not mean inference runs offline.
How the local-first data model and server routes fit together
The architecture splits cleanly in two. The UI is a Next.js application; conversations and workspace files live in browser storage by default. Anything that needs a secret or a network call goes through the app's API routes on the server. That is why the README can promise local-first storage while still sending content to model providers: the browser holds the record, the server holds the credentials and makes the calls.
The server side is where the operational detail lives. The Dockerfile builds a standalone Next.js output and runs it as a non-root user on port 3000, with a health endpoint at /api/health that the Compose healthcheck accepts as either 200 or 401. Credential encryption is handled by a BYOK key pair: BYOK_PRIVATE_KEY_PEM and BYOK_KEY_ID in .env.example. When the private key is empty on a hosted single-instance deployment, the process falls back to an ephemeral key, and the README warns that this causes key rollover across restarts and replicas. Three stores are configurable as memory or Upstash: RATE_LIMIT_STORE, DOCUMENT_PARSE_JOB_STORE, and PLUGIN_REGISTRY_STORE. The .env.example notes that document jobs, plugin registration, sharing, and multi-instance deployments still require Upstash for consistent or durable behaviour, and that Deep Research's arXiv, PubMed, EPO OPS, and SEC EDGAR adapters use the same Upstash pair for cross-instance rate coordination.
Execution is foreground-orchestrated. Agent and Research runs happen while the page is open; closing it interrupts execution, and saved runs need an explicit resume. That is a deliberate simplicity choice, and it has a cost.
Installing Neo Chat and running a first conversation
The README gives two paths. The source route requires Node.js 24 and pnpm 10.30.3 through Corepack:
git clone https://github.com/u14app/neo-chat.git
cd neo-chat
corepack pnpm install --frozen-lockfile
corepack pnpm devAfter that, localhost:3000 serves the app. You add a model provider and API key in Settings, then start a conversation. Most options are configured in the interface; deployment-wide defaults come from copying .env.example to .env.local.
The container route skips the checkout entirely:
docker run --rm -p 127.0.0.1:3000:3000 \
-e ACCESS_PASSWORD='replace-with-a-strong-password' \
-e BYOK_ALLOW_EPHEMERAL_KEY=true \
ghcr.io/u14app/neo-chat:latestYou open localhost:3000 and enter the access password. The README flags this example as local-only: it uses ephemeral credential-encryption keys, and stable BYOK keys should be configured before production to avoid key rollover across restarts and replicas.
For a Compose deployment, docker-compose.yml wires the same variables, including DEPLOYMENT_MODE, NEXT_PUBLIC_SITE_URL, TRUST_PROXY_HEADERS, and SHARING_ENABLED, which defaults to false. The mcp-bridge service sits behind the mcp profile and receives only its explicit values.
If you want the keys generated rather than pasted, package.json exposes a script for it:
corepack pnpm byok:generateCloudflare Workers is a third target: run corepack pnpm build:worker, then corepack pnpm deploy:worker. The deploy script passes --keep-vars so dashboard variables survive the deploy.
Where Neo Chat stops being the right tool
The foreground execution model is the sharpest limitation. Agent and Deep Research runs are orchestrated in the page, so closing the browser interrupts them; a saved run has to be resumed explicitly. If your workflow depends on long research jobs finishing unattended, this design is working against you.
The second constraint is the storage boundary. Backups exclude credentials and external service data, and the README states that Research extensions such as custom templates, steering, and report Q&A are browser-local and excluded from both ZIP backups and encrypted sync. So a browser profile wipe can take those with it. Encrypted sync through WebDAV or S3/MinIO is opt-in, not automatic.
The third is operational. The .env.example describes the memory-backed defaults as acceptable for local and single-instance hosted use, with hosted rate limiting falling back to process memory when Upstash is unavailable. Anything multi-instance, or anything relying on document parsing jobs, plugin registration, or sharing, wants Upstash. Deploying the Docker image to more than one replica without that configuration is a misconfiguration, not a scaling step.
Finally, the access gate is a single shared password. There is no per-user identity, so you cannot attribute a conversation or revoke one person's access without rotating the password for everyone.
How Neo Chat differs from Open WebUI and LibreChat
The obvious alternatives in this space are Open WebUI and LibreChat, both self-hosted chat front ends with multi-provider support. The difference is where the data lives. Those projects centre on a server-side database: users authenticate, conversations are stored in the backend, and an administrator can inspect them. Neo Chat goes the other way. Conversations and workspace files stay in browser storage by default, and the server is mostly a credential holder and proxy.
That choice buys privacy from your own server operator and costs you central management. There is no admin view of conversations because the server does not hold them. Backups are ZIP files you export, and sync is an optional encrypted path through WebDAV or S3/MinIO rather than a database dump. If you need SSO, per-user quotas, or a shared conversation archive, a server-database design is the better fit and you should pick one of those projects instead.
The second difference is scope. Neo Chat bundles Agent mode, Deep Research with reviewable plans and cited reports, Text Skills, OpenAPI plugins, remote MCP servers, voice, and editable artifacts. That is a lot of surface for one application, and it is the main reason the store configuration in .env.example matters as much as it does.
Maintenance, release cadence and what the MIT licence means here
The repository is not archived, and the last push was on 2026-09-13. Releases are frequent: v2.5.0 landed on 2026-09-11, v2.4.0 on 2026-08-01, and v2.3.0 on 2026-07-19, with package.json at version 2.5.2. That cadence means upgrades arrive often, and each one can touch the environment surface. The .env.example is the file to diff on upgrade, because variables such as DEPLOYMENT_MODE, RATE_LIMIT_STORE, and the BYOK pair change behaviour rather than just defaults.
The Dockerfile is a three-stage build that copies the standalone output, so image rebuilds are the normal upgrade path for container users. NEXT_DEPLOYMENT_ID is optional and build-time; the .env.example says to use the same value for every replica in one rollout, and that omitting it makes each build generate a unique identifier. That is the kind of detail that matters when you run several replicas behind a proxy.
The licence is MIT, which permits commercial use and modification. The practical implication is that you carry the support burden: there is no vendor SLA behind the ghcr.io/u14app/neo-chat image. Note also that the package is marked private in package.json, so this is an application to deploy, not a library to publish from.
Editorial conclusion
Adopt Neo Chat if you want a single-user or small-team chat workspace where model keys stay yours, conversations stay in the browser, and you are willing to run the Docker image or a Vercel/Cloudflare deployment. Skip it if you need multi-user accounts: the README states the deployment password is an access gate, not an account system. Before rolling it out, verify three things in your own environment: that BYOK_PRIVATE_KEY_PEM is stable across restarts and replicas, that RATE_LIMIT_STORE, DOCUMENT_PARSE_JOB_STORE and PLUGIN_REGISTRY_STORE point at Upstash rather than process memory, and that foreground run interruption is acceptable for how your team actually uses Agent and Deep Research modes.
Frequently asked questions
What is Neo Chat?
It is a self-hostable AI chat workspace from u14app that connects your own model providers and keeps conversation history in browser storage by default. It bundles multi-model chat, an Agent mode, Deep Research, knowledge-base retrieval, plugins, voice, and artifacts under the MIT licence.
Does Neo Chat run in the browser only?
No. The interface and stored conversations are browser-side, but requests go through the app's API routes to the model providers and services you configure. Local-first storage does not mean inference runs offline.
Can I download and self-host Neo Chat?
Yes. The README gives a Docker command using ghcr.io/u14app/neo-chat:latest, plus source, Vercel, and Cloudflare Workers deployment paths. The source route needs Node.js 24 and pnpm 10.30.3 via Corepack.
Does Neo Chat need an access password?
Not necessarily. ACCESS_PASSWORD can be left empty to disable the password gate, though production local API access then also requires ALLOW_INSECURE_LOCAL_PRODUCTION=true. The README describes the password as an access gate rather than a multi-user account system.
What happens to an Agent or Deep Research run if I close the browser?
It is interrupted. Runs are orchestrated in the foreground, and the README states that saved runs require explicit resume. Closing the page stops execution.
Is Neo Chat's conversation history included in backups?
Conversations can be exported through ZIP backup and restore, but the README says backups exclude credentials and external service data. Research extensions such as custom templates, steering, and report Q&A are browser-local and excluded from both ZIP backups and encrypted sync.
Community notes