48cef99257b0f965d051f54bfcfedb3158cf6dd0
Apps: - dwg-rooms: extract room numbers from DWG/DXF - dwg-counting: count symbols in PDF drawings (OpenCV template matching) - contract-check: review PDF contracts against a checklist (Claude vision + Tesseract OCR fallback) - email-drafter: bullet notes → polished Czech/English business emails - invoice-extractor: PDF/image invoice → structured data → Excel - translator: Czech-first translator across 19 languages with tone control - vv-check: find inconsistent unit prices across VV sheets in one workbook - vv-compare: diff original vs new VV files (changes / added / removed) - feature-request: portal users submit ideas + sample files Infrastructure: - LiteLLM gateway with per-app virtual keys + budgets - Langfuse observability - Geist font, shared theme, cross-subdomain back link + theme sync via cookie/URL - Caddy reverse proxy on *.klas.chat
AI Portal
Internal landing page that fronts a stack of AI tools (chat + workflow apps), all routed through company API keys with per-user budgets and observability.
See AI_PORTAL_HANDOFF.md for full architecture and rationale.
Phase 0 — what's running
- Landing page (Next.js 16 + Auth.js v5) — this repo,
landing/ - Open WebUI — already running on host (
127.0.0.1:8080) - Dify stack — already running (
docker_defaultnetwork, nginx on:443/:8090) - LiteLLM — already running on
localainetwork (:4000) - Langfuse — not yet (compose stub left in
docker-compose.yml)
Local dev
cd landing
cp ../.env.example ../.env # then edit secrets
pnpm install
pnpm dev # http://localhost:3000
Set at minimum:
AUTH_SECRET—openssl rand -base64 32DEV_PORTAL_PASSWORD— any string; gates the dev login
Production-style run (Docker)
From the portal/ directory:
docker compose up -d --build
The landing service binds to 127.0.0.1:3010. Caddy on the host fronts it at
https://ai.klas.chat.
Auth
Two providers, both wired through Auth.js v5:
- Microsoft Entra ID — production. Activated automatically when
AUTH_MICROSOFT_ENTRA_ID_IDandAUTH_MICROSOFT_ENTRA_ID_SECRETare set. - Dev Credentials — single shared password from
DEV_PORTAL_PASSWORD. Used only while Entra is not provisioned. Both can coexist; the login page shows whichever is configured.
All routes except /login and /api/auth/* are gated by proxy.ts.
Adding a new tile
Edit landing/src/data/apps.json and add an entry:
{
"id": "my-app",
"title": "My App",
"description": "What it does in one line.",
"category": "Documents",
"icon": "FileText",
"accent": "blue",
"href": "https://dify.klas.chat/app/<id>"
}
Icon names come from lucide-react. Accents:
violet, blue, cyan, emerald, amber, rose. Use "href": "#" to
mark a tile as "Coming soon".
What's next (post Phase 0)
- Wire Open WebUI to use LiteLLM as its OpenAI-compatible endpoint.
- Configure Dify model providers to point at LiteLLM (so spend is attributed).
- Stand up Langfuse (uncomment in
docker-compose.yml). - Map per-user identity → LiteLLM virtual keys.
- Provision Microsoft Entra app registration; flip prod auth on.
Description
Languages
Python
33.7%
CSS
32.6%
JavaScript
16.1%
HTML
11.2%
TypeScript
5.4%
Other
1%