AI Portal
A self-hosted, multi-user portal that gives a team shared access to AI subscriptions — Claude, Gemini, OpenAI, and others — through one chat UI and an admin console. Supports both direct API providers and browser-automated providers (for services without a usable API), per-user access control, multi-tenant orgs, usage tracking, and a job queue for concurrent requests.
Architecture
Two long-running processes, one shared SQLite DB, Redis as the connective tissue:
┌────────────────────────┐
Browser ───────────▶│ server/index.js │◀── serves dist/ or pages/ (Vite dev/prod UI)
│ Express API server │
│ │
│ requireLogin/Admin ──┐ │
│ routes/*.js ◀────────┘ │
└───────┬─────────┬───────┘
│ │
inline job │ │ enqueue (API providers)
(browser provs) │ ▼
│ ┌─────────────┐ ┌──────────────┐
│ │ Redis │◀────▶│ queue/worker │
│ │ (sessions + │ │ .js │
│ │ BullMQ) │ └──────┬───────┘
│ └─────────────┘ │
▼ ▼
┌────────────────────────────────────────────┐
│ providers/<name>/*Provider.js │
│ API providers (Anthropic/OpenAI/Gemini/…) │
│ Browser providers (Playwright + Chromium) │
└───────────────────┬──────────────────────────┘
▼
┌───────────────────┐
│ data/portal.db │ (SQLite: conversations,
│ (better-sqlite3) │ messages, jobs, usage_log, published_shares)
└───────────────────┘
- API server (
server/index.js) — auth, UI serving (dev/production), job submission, SSE streaming; runs browser-provider jobs inline. - Worker (
server/queue/worker.js) — separate process; pulls API-provider jobs off a per-user BullMQ queue in Redis. - Vite Frontend — built from
pages/andsrc/into thedist/directory. Servedist/in production; Vite dev server handles HMR on port 5110 (governed port assignment for Anand's local development). - Graceful degradation — if Redis is down, API jobs fall back to inline execution in the API process. No Redis required to run it locally, just to scale it.
For the full module-by-module map (every file in server/, the job data-flow, the role hierarchy, browser-automation internals, tiered sharing) see CONTEXT.md — that document is the detailed architecture reference this README summarizes.
Quick start (local dev)
Requires Node ≥ 20 and, ideally, a local Redis (optional — see above).
cp .env.example .env # see "Environment" below
npm install
node scripts/add-user.js admin password admin
# Start API server, worker, and Vite dev server:
npm run dev:full
# → http://localhost:5110 (Vite frontend with API proxy to 3040)
Other useful scripts (from package.json):
| Command | What it does |
|---|---|
npm run dev:full |
Launches server, worker, and Vite frontend watcher concurrently (port 5110) |
npm run build |
Compiles TypeScript and runs Vite production build (tsc && vite build) |
npm run dev |
API server only (port 3040), auto-restart on change |
npm run dev:worker |
Worker only, auto-restart on change |
npm run start:all |
Production start for server and worker processes (requires built frontend) |
npm run add-user |
CLI: create a user (node scripts/add-user.js <username> <password> [role]) |
npm run add-subscription |
CLI: register a provider subscription |
npm run migrate |
Apply pending SQLite schema migrations |
npm run validate:skills |
Validate web-module skill definitions |
Environment setup
Copy .env.example to .env and fill in what you need. Everything not listed below is optional and provider-specific.
| Variable | Required? | Notes |
|---|---|---|
SESSION_SECRET |
Yes | openssl rand -base64 32. The app has an insecure random fallback for convenience in dev — never rely on it in production (see REMEDIATION.md S7). |
REDIS_URL |
Recommended | Default redis://localhost:6380. Without it: sessions and queues degrade to in-process/inline behavior — fine for a single-instance dev box, not for production. |
PORT |
No | Default 3040. |
*_API_KEY (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, …) |
Only for providers you use | See .env.example for the full list. Per-subscription keys (via the admin console) take priority over these env fallbacks. |
METRICS_TOKEN |
No | Bearer token to expose /metrics to something other than localhost (Prometheus scraping). |
NODE_ENV=production |
Production only | Also gates the session cookie's secure flag — see REMEDIATION.md S7 before deploying. |
For provider-specific browser-automation setup (Chromium sessions, Xvfb on a headless VPS) and the full production deployment walkthrough, see DEPLOY.md.
Project layout
server/
index.js Express entry point — mounts every route in routes/
auth/ Session guards, role/permission checks, org scoping
db/ SQLite connection + schema.sql
providers/ One folder per AI provider (API-based and browser-based)
queue/ BullMQ queue + worker + per-user queue logic
router/ Query classification / smart model routing
routes/ ~20 Express routers — one per API surface
web-module/ Browser-automation engine, SSRF guard, site adapters
pages/ Source HTML templates for the Vite pages
src/ Frontend TypeScript source code (chat UI, admin panels, shared)
dist/ Production bundled frontend (output of `npm run build`)
public/ Static assets (robots.txt, images, global CSS fallback)
scripts/ CLI utilities (add-user, add-subscription, migrate, …)
data/ Runtime state — gitignored (SQLite DB, session data, JSON configs)
docs/adr/ Architecture Decision Records — the "why" behind key choices
See CONTEXT.md for a file-by-file breakdown of every path above.
Further reading
| Doc | What's in it |
|---|---|
| CONTEXT.md | Full architecture reference — every module, the job data-flow, role hierarchy, browser-automation internals |
| DEPLOY.md | Production VPS/Docker deployment walkthrough |
| USER_GUIDE.md | End-user and administrator guide to the product itself |
| ROADMAP.md | Planned work, phased |
| docs/adr/ | Why the system is built the way it is — dual persistence, SQLite, browser automation, org/role model |
| REMEDIATION.md | Tracked findings from a technical due-diligence review — known gaps and their fixes, ranked by priority |
Status
Under active development. Several subsystems (multi-tenant orgs, per-user queues, additional providers, smart routing, groups) are implemented but not yet fully hardened for production multi-tenant use — see REMEDIATION.md before deploying this beyond a trusted, single-team setting.