Referenta is split across several Next.js apps, supporting services (mostly Docker, a couple of standalone Rust binaries), and shared workspace packages. This page is the map: what each piece is, which port it runs on, and how the root pnpm dev command stitches the developer-facing surface together.
For the dev loop and environment model, see Developer Setup. For the operator admin app (hosting, sign-in, permissions), see Admin App.
pnpm dev command. The admin and CMS apps are started on their own; the production-only Bundestag proxy has no local dev mode at all.Applications
| App | Path | Port | Tech | Purpose |
|---|---|---|---|---|
| Dashboard | apps/dashboard | 3000 | Next.js 16 | Main product UI — Assistant, Research, Knowledgebase, Contactbase, Press Monitor, Projects, Support. |
| Marketing site | apps/www | 3001 | Next.js 16 | Public marketing site at the apex domain. |
| Docs | apps/docs | 3002 | Next.js 16 + Fumadocs | This documentation site (public docs + this internal section + OpenAPI reference). |
| Admin | apps/admin | 3069 | Next.js 16 | Local-only admin tooling. Talks directly to hosted dev / prod Supabase to manage things like the Assistant model whitelist with a two-tier promotion flow. Never deployed. See Admin App. |
| CMS | apps/cms | 1337 | Strapi 5 | Headless CMS used to manage marketing-site content. |
Services
Long-running services live under services/. They split into two groups by lifecycle: services the root pnpm dev command boots locally for the dashboard, and services that only run in production (Dokploy). Deployment settings live per service in dokploy.json; the runbook is docs/dokploy-deployment.md.
Local (booted by pnpm dev)
| Service | Path | Host port | Container port | Purpose |
|---|---|---|---|---|
| xberg | services/xberg | 8000 | 8000 | OCR + text extraction (replaced Kreuzberg). Bearer-token gated behind a Caddy sidecar. |
| Presidio | services/presidio | 8080 | 8080 | PII masking via Microsoft Presidio. FastAPI wrapper, in-app token auth. |
| Gotenberg | services/gotenberg | 8090 | 3000 | PDF / document generation for the Assistant's generateDocument tool. |
| Press Monitor | services/press | 3009 | 8080 | Standalone Press Monitor backend (feed, article analysis, briefings, metrics, external proxy). Same Dockerfile Dokploy builds in prod. |
| Redis | services/redis | 6379 | 6379 | Hot buffer for resumable Assistant streams. Persistence disabled — stream buffers are ephemeral, the authoritative pointer lives on the chat row. |
Host ports are configurable through XBERG_PORT, PRESIDIO_PORT, GOTENBERG_PORT, PRESS_PORT, REDIS_PORT env vars (see docker-compose.yml). The dashboard reads *_BASE_URL / PRESS_API_UPSTREAM_URL env vars to find them; those URLs are auto-written into apps/dashboard/.env.development.local by supabase/dev.mjs (see pnpm dev orchestration below).
Production-only (not booted by pnpm dev)
| Service | Path | Tech | Notes |
|---|---|---|---|
| Bundestag proxy | services/external/bundestag | Rust / Axum | Standalone Bundestag automation endpoints (xAI Grok). Replaces the legacy api/src/bundestag/* flow. Deployed on Dokploy. |
Local Supabase
The repo root supabase/ directory is the only supported Supabase CLI project. When pnpm db:start (or the supabase/dev.mjs wrapper) brings up the local stack, the Docker bundle exposes these ports — declared in supabase/config.toml:
| Component | Port | Notes |
|---|---|---|
| REST API / Auth / Storage / Realtime | 24321 | What NEXT_PUBLIC_SUPABASE_URL points to locally. |
| Postgres | 24322 | Direct Postgres connection. |
| Postgres shadow DB | 24320 | Used by supabase db diff to compute schema deltas. |
| Postgres pooler | 24329 | Disabled by default. |
| Supabase Studio | 24323 | Web UI at http://127.0.0.1:24323. |
| Local SMTP / Mailpit | 24324 | Captures auth and notification emails. Declared as [local_smtp]; the container is still named supabase_inbucket_*. |
| Analytics (Logflare) | 24327 | Disabled in config.toml. It only backs the Studio Logs tab, and its vector log shipper crash-loops unless Docker Desktop exposes an unauthenticated TCP daemon. Use docker logs <container> instead. |
| Edge runtime inspector | 8083 | Chrome devtools attach point for edge functions. |
These are deliberately not the Supabase defaults (54320–54329). Anything
above 49152 sits in the OS ephemeral port range, and on Windows the Hyper-V
NAT service — installed alongside Docker Desktop and WSL2 — reserves random
100-port blocks out of that range on every boot. When a block lands on 543xx,
pnpm db:start fails with bind: An attempt was made to access a socket in a way forbidden by its access permissions, and it clears itself on the next
reboot, so it reads as flaky rather than as a port conflict. The 243xx block
is below the ephemeral range on Windows, macOS and Linux alike, so no OS ever
claims it. See the comment at the top of supabase/config.toml.
Packages
Shared workspace packages live under packages/:
packages/ui— shared React component library (shadcn/ui based) consumed by the apps.packages/editor— Tiptap v3 rich-text editor used by Research and the Assistant document tools. Carries the collaboration extensions for Yjs-backed editing.packages/quill-markdown— small, dependency-free Quill Delta ↔ Markdown converter. Retained to read documents written before the Tiptap migration.packages/migration— scripts for converting raw data during data migrations.packages/typescript-config— shared TypeScript configurations (base.json,nextjs.json, etc.).
Linting is Biome, configured once at the repo root (biome.json) — there is no shared ESLint package.
What pnpm dev orchestrates
The root pnpm dev runs turbo run dev filtered to the long-running tasks needed for end-to-end dashboard development:
turbo run dev \
--filter=www \
--filter=dashboard \
--filter=docs \
--filter=@referenta/presidio \
--filter=@referenta/xberg \
--filter=@referenta/gotenberg \
--filter=@referenta/press \
--filter=@referenta/redis \
--filter=@referenta/supabaseIn plain English, that starts:
- Three Next.js dev servers — dashboard (3000), www (3001), docs (3002).
- Five Docker services — xberg, presidio, gotenberg, press, redis (each via
docker compose -f docker-compose.yml up <service>). - The local Supabase stack —
@referenta/supabaseis the repo-rootsupabase/directory, and itsdevscript runssupabase/dev.mjs. That script startssupabase startif it isn't already running, then writesapps/dashboard/.env.development.localwith the local Supabase API URL + anon / publishable / service-role keys, plusUPSTASH_REDIS_REDIS_URL,XBERG_BASE_URL,PRESIDIO_BASE_URL,GOTENBERG_BASE_URL, andPRESS_API_UPSTREAM_URL. The dashboard auto-points at the local stack on next restart — no manual env wiring needed.
Because supabase/dev.mjs writes to apps/dashboard/.env.development.local on startup, after the first pnpm dev you may need to restart the dashboard process once to pick up freshly-written env values. Subsequent runs reuse the file as long as ports stay stable.
What is not in pnpm dev
These boot separately on purpose:
apps/admin— start withpnpm --filter admin dev. It targets hosted dev / prod Supabase directly (not local) and shouldn't run alongside the orchestrated local stack by default. See Admin App.apps/cms— start withpnpm --filter cms dev. Strapi is only needed when working on CMS-managed marketing content.services/external/bundestag— Rust service that runs on Dokploy in production. Usecargo runinside the service directory when developing against it locally.