New architecture for the embedded chat widget: client -> litellm -> langflow.
This is a separate, leaner repo from PREAA — it only runs the services this architecture needs, instead of PREAA's full stack (LibreChat, RagFlow, n8n, Open WebUI, etc).
- Ariel — embedded chat widget experience (
packages/admin-v2's widget config + thedeep-chat-based embed script) - Anurag — backend services (LiteLLM, LangFlow, Langfuse, Keycloak)
deploy/ # docker-compose stack: litellm, langflow, langfuse, keycloak
docker-compose.yml
config/ # env samples + litellm.yaml (copy .sample -> real file, fill in secrets)
postgres-init/ # creates the langflow/litellm databases on first boot
packages/
admin-v2/ # widget config dashboard (Next.js + Prisma + NextAuth/Keycloak)
public/widget-loader.js # embeddable widget script, renders via deep-chat
prisma/schema.prisma # WidgetConfig model (bot name, theme, LangFlow flow id, ...)
packages/admin-v2 manages per-site widget configs (bot name, welcome message,
theme colors, which LangFlow flow + system prompt it talks to, streaming on/off)
backed by Postgres via Prisma, and proxies chat requests through to LangFlow.
It also has read-only pages for LangFlow flows, LiteLLM models/keys, and
Langfuse projects.
-
Copy the env samples and fill in real secrets:
cd deploy/config for f in .env.*.sample; do cp "$f" "${f%.sample}"; done
At minimum, set real passwords/keys in
.env.psql,.env.redis,.env.minio,.env.clickhouse,.env.litellm,.env.langfuse,.env.keycloak, and point.env.litellm/.env.langflow'sDATABASE_URLpasswords at the same one you set in.env.psql. -
Start the backend stack:
cd deploy docker compose up -d- LangFlow: http://localhost:7860
- LiteLLM: http://localhost:4000
- Langfuse: http://localhost:3000
- Keycloak: http://localhost:8080 (admin console,
start-devmode — not production-hardened yet)
-
Run the dashboard:
cd packages/admin-v2 cp .env.sample .env.local # fill in LangFlow/LiteLLM/Langfuse + Keycloak client values npm install npx prisma migrate deploy # creates the WidgetConfig table npm run dev # runs on :3019
Sign-in is gated by Keycloak (
src/proxy.ts— Next.js 16 renamedmiddleware.tstoproxy.ts). The widget config GET endpoint (/api/widgets/[id]) and the chat proxy (/api/widgets/[id]/chat) are intentionally left public since third-party pages call them directly, unauthenticated, viawidget-loader.js. -
Try the embed: open
http://localhost:3019/test-embed.htmlafter creating a widget at/widgets/new.
deploy/config/litellm.yamldoes not yet wire LiteLLM'scustom_provider_mapto LangFlow. PREAA does this viapackages/litellm/custom/langflow_handler.py, but that handler depends on a separate "helper backend" service for model -> flow mapping that isn't part of this stack. Anurag to decide how routing should work here before porting that handler over.- Keycloak runs in
start-devmode with an ephemeral dev database — fine for getting started, not for anything beyond local dev. widget-loader.jsloadsdeep-chatfrom a CDN (unpkg) at runtime rather than bundling it — fine for kicking off, but worth revisiting (self-host or pin a version) before this goes anywhere production-facing.