Model or dataset
Zaki-1052/GPTPortal avatar
Zaki-1052/GPTPortal

GPTPortal: a self-hosted chat portal for OpenAI, Claude, Gemini and local models

A feature-rich portal to chat with GPT-4, Claude, Gemini, Mistral, & OpenAI Assistant APIs via a lightweight Node.js web app; supports customizable multimodality for voice, images, & files.

397 stars64 forksJavaScriptMIT

At a glance

What is it?
GPTPortal is a local-first Node.js web app that puts OpenAI, Anthropic, Google, Mistral, Groq, OpenRouter and your own OpenAI-compatible endpoints behind one streaming chat interface. The trade-off is that you run it, key it and secure it yourself.
Who is it for?
Adopt GPTPortal if you already pay several providers directly, want one streaming interface over all of them, and are comfortable running `node server.js` behind your own Basic Auth credentials. Skip it if you need multi-tenant accounts, a hosted service, or a packaged desktop binary; the README states there is no vector database, no RAG pipeline and no agent orchestration.
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 87 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Who GPTPortal is for, and the problem it removes

If you hold keys for more than one model provider, your working day is split across browser tabs. GPT-5.5 in one, Claude in another, Gemini in a third, and a local Llama behind a terminal. Each tab has its own history, its own system prompt box, and its own idea of what a conversation is. GPTPortal collapses that into one page served from your own machine.

The README is explicit about the intended user: a single person, or a trusted household, running the app locally. It is not a multi-tenant service. There is one Basic Auth login gate and per-browser session state. That framing matters, because it tells you which half of the feature list is real for you. Compare view, presets, cost tracking and the model picker are built for one operator who wants to move a prompt between vendors mid-project. Anything resembling user management, quotas or audit trails is absent by design.

The second half of the pitch is billing. You are billed by each provider through your own keys. There is no subscription and no middleman. For someone already paying for API access, the portal adds no line item. For a light user, the README estimates a few dollars a month. That is a different economic shape from a flat monthly chat subscription, and it only pays off if you actually use the APIs you already have.

How the Node/Express core and the provider layer fit together

The 2.0 rewrite is organised around a single entry point. Running `node server.js` starts `src/server/core/Application.js`, which wires three managers: MiddlewareManager handles Basic Auth, sessions, CORS, rate limiting, CSP, body parsing and static files; ServiceManager instantiates the services; RouteManager registers the routes. The README presents this as the whole map, and the repository layout backs it up: `src/`, `public/`, `server.js`, `scripts/`, `docs/`.

There is no build step, no bundler, no frontend framework and no database. The frontend is hand-written HTML, CSS and vanilla JavaScript under `public/`. The backend dependencies in `package.json` are ordinary Express-era packages: `express`, `express-basic-auth`, `express-session`, `express-rate-limit`, `body-parser`, `cors`, `multer`, `marked`, plus provider SDKs (`openai`, `@google/genai`) and token counting (`js-tiktoken`, `tiktoken`). Nothing here needs a compiler or a container runtime to start.

The provider layer is where the design earns its keep. A curated core catalog covering OpenAI, Anthropic, Google, xAI, DeepSeek, Groq, Moonshot and Mistral is defined in a single JSON file. The OpenRouter catalog is loaded live and cached. Your own OpenAI-compatible endpoints (Ollama, LM Studio, vLLM, LocalAI, a remote gateway) are added through environment variables with no code and auto-discovered into the model picker. That last path is the one to inspect if you plan to extend the app: adding a provider means editing configuration rather than writing a new route.

Installing GPTPortal and sending a first message

The README gives a single-command start for the local path. You need Node.js and at least one provider API key. The `.env.example` file in the repository root is the template: copy it to `.env` and fill in the keys you actually hold. The example lists `OPENAI_API_KEY`, `GOOGLE_API_KEY`, `MISTRAL_API_KEY`, `CLAUDE_API_KEY`, `GROQ_API_KEY`, `OPENROUTER_API_KEY`, `CODESTRAL_API_KEY`, `DEEPSEEK_API_KEY`, `GROK_API_KEY` and `KIMI_API_KEY`, alongside `USER_USERNAME` and `USER_PASSWORD` for the login gate. Leave the ones you do not use blank rather than inventing values.

bash
cp .env.example .env
node server.js

After the server starts, the homepage points at `http://localhost:3000/portal`. The login prompt is Basic Auth, using the `USER_USERNAME` and `USER_PASSWORD` you set. Once inside, the model picker is searchable and categorised, so you can type a family name instead of scrolling.

Defaults live in the same file. `DEFAULT_MODEL` in the example is set to `gpt-5.5`; the surrounding comments show `claude-opus-4-8` as an alternative. Temperature, max tokens, reasoning effort and verbosity are all commented out by default, and the comments list the accepted values for the last two (`minimal`, `low`, `medium`, `high` for reasoning effort; `low`, `medium`, `high` for verbosity).

bash
# in .env, uncomment to override
DEFAULT_MODEL='gpt-5.5'
# TEMPERATURE=1
# MAX_TOKENS=8000
# REASONING_EFFORT=medium
# VERBOSITY=medium

If you would rather not install Node locally, the repository ships a Dockerfile and a `docker-compose.yml`. The compose file mounts `./.env` into the container at `/app/.env` and publishes port 3000.

yaml
services:
  chagpt-ui:
    image: ghcr.io/zaki-1052/gptportal:latest
    volumes:
      - ./.env:/app/.env
    ports:
      - 3000:3000

The service name in that file is spelled `chagpt-ui`, which is worth noticing before you script against it. The Dockerfile builds on `node:lts`, installs `dumb-init`, runs `npm ci --only=production --legacy-peer-deps`, and starts with `dumb-init node server.js` as the `node` user. The `--legacy-peer-deps` flag in the build is a signal that the dependency tree is not peer-clean; expect that to matter when you bump packages.

Where GPTPortal stops being the right tool

The Basic Auth gate is the first real constraint. One username and one password sit in front of the whole app. The README says you can expose it on a network, but that it is designed for one person or a trusted household. There is no account model to fall back on if that assumption breaks, and no per-user conversation isolation beyond browser session state.

The second constraint is storage. Conversations are held in your browser session, and file uploads optionally land in `public/uploads/`. That directory sits under the static file root. The README does not document a cleanup job for those uploads, so a long-running instance will accumulate whatever you attach. If you bind the server to anything other than localhost, that is the first path to check.

The third is scope. The README states plainly that there is no vector database, no RAG pipeline, no agent-orchestration subsystem and no packaged desktop binary. If your requirement is retrieval over a document corpus, or a chained multi-step agent, GPTPortal is a base rather than a solution. The Assistants mode is the one stateful, tool-using path the project offers, and it is OpenAI-specific.

Finally, maintenance. The last push to the repository was on 2026-07-06. The most recent tagged release is v1.1.2 from 2024-02-27, while `package.json` declares version 2.0.0. Treat git history, not the release list, as the current state of the code, and read `MODEL_UPDATE.md` before assuming a given model name in the catalog still resolves.

GPTPortal compared with LibreChat and Open WebUI

The closest alternatives in this space are LibreChat and Open WebUI. Both are also self-hosted chat frontends over multiple providers, and both are considerably larger projects with their own deployment stories. The difference is the constraint each one optimises for.

LibreChat targets a full application: user accounts, persistent conversation storage in a database, and a plugin and tool layer. Adopting it means adopting a database and a migration path. GPTPortal makes the opposite choice. No database, no bundler, no frontend framework. Conversations live in the browser session. The README frames this as a tool you own and understand rather than a black box you deploy and forget, and the repository layout supports that claim: you can read `src/` and `public/` end to end in an afternoon.

Open WebUI leans toward a polished, model-server-centric experience, typically paired with an Ollama backend. GPTPortal's local-endpoint support is narrower and more explicit: you register OpenAI-compatible base URLs through environment variables, and they appear in the picker. If your world is mostly local models, Open WebUI's tighter integration will feel more natural. If your world is a rotating set of hosted APIs plus one local fallback, GPTPortal's curated catalog and live OpenRouter list are the more direct fit.

The honest summary: pick GPTPortal when the absence of a database and a build step is the feature you want. Pick LibreChat or Open WebUI when you want persistence, accounts and a plugin ecosystem and are willing to run the infrastructure that comes with them.

Licence, upgrade cost and what to check before you commit

GPTPortal is MIT licensed, so you can read, modify, redistribute and run it commercially under the terms of that licence. The repository includes a `LICENSE` file at the root. This is not legal advice, and MIT says nothing about the provider terms you accept when you paste API keys into `.env`; those are separate agreements with OpenAI, Anthropic, Google and the rest.

The upgrade cost is dominated by the dependency tree, not by application code. There is no build step and no database schema to migrate, so pulling a new commit and restarting is the normal path. The friction sits in `package.json`: the Dockerfile passes `--legacy-peer-deps` to `npm ci`, which means a clean install without that flag may not resolve. If you fork the project, that flag is the first thing to test against a newer Node release.

Model names are the other recurring maintenance task. The core catalog is a single JSON file, and `MODEL_UPDATE.md` exists at the repository root specifically to track model changes. Provider deprecations will break entries in that file before they break anything else. The `scripts/smoke-test.js` file, wired to `npm test`, is the cheapest way to check that a catalog edit did not break the app.

bash
npm test

Editorial conclusion

Adopt GPTPortal if you already pay several providers directly, want one streaming interface over all of them, and are comfortable running `node server.js` behind your own Basic Auth credentials. Skip it if you need multi-tenant accounts, a hosted service, or a packaged desktop binary; the README states there is no vector database, no RAG pipeline and no agent orchestration. Before trusting it with work conversations, verify the Basic Auth gate and rate limiting in `src/server/core/Application.js`, confirm which provider keys your `.env` actually contains, and check that `public/uploads/` is not exposed on the interface you bind to.

Frequently asked questions

Does GPTPortal need a database or a build step?

No. The README states there is no build step, no bundler, no frontend framework and no database. The backend is modular Node/Express and the frontend is hand-written HTML, CSS and vanilla JavaScript under `public/`.

How does GPTPortal handle my API keys and conversations?

Keys live in a `.env` file that is never committed, and the README says nothing is sent anywhere except the API calls to whichever provider you chose for a given message. Conversations are held in your browser session and, optionally, in files under `public/uploads/`.

Can GPTPortal talk to a local model like Ollama or LM Studio?

Yes. Custom OpenAI-compatible endpoints are added through environment variables with no code, and the README lists Ollama, LM Studio, vLLM, LocalAI and remote gateways as examples. Those models are auto-discovered into the model picker.

Is GPTPortal a hosted service with user accounts?

No. The README describes a single Basic Auth login gate with per-browser session state, intended for one person or a trusted household running it locally. It is not a hosted, multi-tenant SaaS.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. Zaki-1052/GPTPortal on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zaki-1052-gptportal.svg)](https://hysenlabs.com/projects/zaki-1052-gptportal)