FAQ#

Do I need an AI API key to use Janux?#

No. The framework is a complete SSR/islands framework without any key. The copilot endpoint answers a setup card until you set JANUX_MODEL or a provider key — nothing else changes.

Does every visitor pay for an LLM?#

Only if they use the copilot. Pages, islands, api() calls — none of it touches a model. The agent runs per copilot conversation, server-side, under your key and your maxTurns cap.

Why can't I mutate state outside run()?#

Because every mutation being a named, validated, guard-checked intent is what makes the agent surface trustworthy — and what gives you audit trails, proposals and browserless tests for free. It's the framework's one big constraint; everything else falls out of it.

Can an agent approve its own proposal?#

No. approve endpoints/bridges execute a stored closure exactly once, and approval affordances live in your UI for humans. Give your copilot chrome human-only intents (guard: 'forbidden') so the model can't even see them.

What happens if my component throws during resume?#

The island fails in isolation — other islands and the static page keep working. Errors surface as janux:error DOM events. The same holds during SSR: an island's throw renders its error view (or the closest ancestor's), never a dead page.

Is x-janux-origin spoofable?#

Yes, and that's fine: human is the default and most-privileged origin, so lying about it grants nothing. Real authentication belongs in src/ctx.ts; guards govern agent behavior, not network trust.

How do I do i18n / dark mode / router transitions?#

i18n is built in: a src/i18n.ts config turns on locale-prefixed routing (/en, /es), typed t() with plurals and interpolation, locale detection with a JANUX_LOCALE cookie, and page-scoped client messages — only the keys a page's islands use are shipped (i18n). Dark mode: a store (theme) read by islands + CSS. Client-side route transitions: built in — SPA navigation is on by default (diffed HTML over the Navigation API), with persist islands and surviving app-scope stores. See SPA navigation.

Why Bun?#

janux start executes TSX directly — no server build, no transpile step drift. Dev uses Vite for HMR and the client pipeline. You can still deploy anywhere a container runs.

Can I deploy without a server?#

Yes — set output: "static" in your app config and janux build prerenders every page (dynamic routes enumerated by staticParams) plus llms.txt into dist/client, ready for any static host. You keep SSR HTML and islands; you give up everything under /_janux/* — api tools, manifest, proposals, copilot. See Deploying → Static export.

Where's the memory / guardrails / RAG story?#

In defineAgent({ harness }), opt-in and provider-direct — no extra runtime to adopt:

Field What it adds
memory Thread-aware turns: history read from storage, replies remembered (agent memory)
processors A guardrail pipeline before every turn; aborting returns a typed refusal (guardrails)
rateLimit + identityFor Per-caller limits and thread ownership (rate limit)

Durable workflows, attachments and outbound MCP clients sit alongside it. RAG is not a framework feature: give the agent retrieval tools (api() functions over your index) and it retrieves — the docs site you're reading does exactly that.

Is this production-ready?#

It's a young v0.x with an unusually strong test story (the guarantees are asserted, not promised). Ship a side project; read the roadmap before betting the company.