@uiresponse/server
v0.2.0
Published
Run a UI Response server: npx @uiresponse/server boots the API + web app on :8787 with seed data. One variable to generate: UIR_LLM_API_KEY.
Maintainers
Readme
@uiresponse/server
The standalone UI Response (UIR) server: the API and the web app in one process. Plain
node:http — no framework, no build step, no checkout.
npx @uiresponse/serverThat boots on http://localhost:8787 with deterministic seed data and no database to connect. Add
UIR_LLM_API_KEY (below) and it can generate. Open it in a browser and ask for something ("show me
every artist and their pipeline stage"); the answer arrives as a live, validated view rather than a
wall of text.
Configuration
Config is environment-only. Either export real environment variables, or drop a .env in the
directory you run the command from — both work, and a real environment variable always wins over
the file.
# ── Which model generates pages — ONE variable ─────────────────────────────────
UIR_LLM_API_KEY=sk-ant-… # your key — it stays on your server, and is never logged or echoed
# ── Which data it reads (optional; unset = the shipped seed fixture) ───────────
UIR_POSTGREST_URL=https://<project>.supabase.co # Supabase's data API IS PostgREST
UIR_POSTGREST_ANON_KEY=… # publishable-class key only, never service-role
PORT=8787The key chooses the provider. A key starting sk-ant is Anthropic. Any other key is an
OpenAI-compatible endpoint — OpenAI, OpenRouter, Groq, or a model on your own hardware — with
UIR_LLM_BASE_URL (default: OpenAI) as the only other thing to set. Ambient ANTHROPIC_API_KEY /
OPENAI_API_KEY work the same way, and UIR_LLM_PROVIDER=anthropic|openai overrides the inference.
With no key, the server still boots and serves — seed data, /health, validate, resolve — and
every ask returns one immediate error naming the variable to set. There is no hidden fallback model.
Verify what's actually live at any time:
curl -s localhost:8787/health
# {"ok":true,"connector":"seed","llm":{"provider":"anthropic","keyPresent":true,…}}/health reports the provider name and whether a key is present — never the key itself. The
connector field is the one to check after pointing at your own data: it reads postgrest-live
once UIR_POSTGREST_URL and UIR_POSTGREST_ANON_KEY are both set, and seed until then.
The full env surface — Airtable, model overrides, tenant name — is documented in .env.example,
shipped inside this package.
The wires
POST /v1/agui is the default generate wire — one run streamed as AG-UI protocol events (SSE,
data:-framed; pinned against @ag-ui/core 0.0.57). Every UIR surface consumes this route, and so
can any generic AG-UI client: the assembled document arrives via standard STATE_SNAPSHOT /
STATE_DELTA events, while UIR's per-block validation verdicts, repair rounds, and narration ride
namespaced uir.* CUSTOM events a foreign client may freely ignore.
Slots ride the same wire: a run input carrying a slot_id is a slot fill as an AG-UI run — the
verdict as a CUSTOM slot-envelope event, a stored snapshot as an immediate STATE_SNAPSHOT, the
live upgrade as the same run's events, on a thread derived from the slot identity. The slot's JSON
sidecar (POST /v1/ui) remains as documented legacy; both wires share the snapshot and pin stores.
POST /v1/generate (native SSE) is engine-internal/legacy. It streams the engine's own emit
vocabulary — the richer internal contract the AG-UI translation is derived from. It stays for
compatibility (existing embeds, tooling, tests) and as the engine↔server seam, but new clients
should speak AG-UI; this route's event names are not a public contract and may evolve with the
engine.
What it depends on
The server imports generation from @uiresponse/engine and data resolution from
@uiresponse/resolver, so it runs from a plain npm install with no checkout.
MIT.
