# jev-ui > React components that resolve which component to render, how to order a list, and > whether to show an affordance — from calibrated judgments returned by TypeSafe’s Jev. - `` — Choice with a no-match outcome; picks one subtree. - `` — Choice or one Score per item; orders, filters, truncates a candidate set. - `` — Noul; shows an affordance when a condition holds. - `useScore` — a graded dimension that drives props rather than a subtree. --- # Getting started > Install, wire a Server Action, and render your first judgment. jev-ui resolves three kinds of interface question from calibrated judgments: which component to render, how to order a list, and whether to show an affordance. A fourth, `useScore`, answers how much — you describe a scale in words and get back a number to use as an ordinary prop. The model returns typed answers with probabilities; your code decides what to do with them. ## Install ```bash bun add jev-ui # npm install jev-ui · pnpm add jev-ui · yarn add jev-ui ``` ## Add your key The key never reaches the browser. Put it in the environment file at the root of your app — Next.js loads it with no extra tooling, and so does bun. ```bash # .env TYPESAFE_API_KEY=apikey-... ``` > Add that file to your .gitignore before you paste anything into it. With no key the library falls back to the replay transport, so a checkout without one still runs against recorded fixtures rather than crashing. ## Wrap your app in the provider `jev-ui/action` is a ready-made Server Action. The key is read there, on the server — the browser never sees it, and because the client passes only decisions and data, it cannot be turned into a general proxy to your key. ```tsx // app/providers.tsx 'use client'; import { JevProvider } from 'jev-ui'; import { askJev } from 'jev-ui/action'; export function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ## Configuration Everything is environment-driven, so the common case needs no code of your own. | variable | default | what it does | | --- | --- | --- | | `TYPESAFE_API_KEY` | — | Your key. Server-side only. | | `JEV_TRANSPORT` | `live` with a key, else `replay` | `live`, `record`, `replay`, `mock`, `auto` | | `JEV_MODEL` | `jev-latest` | Model id to send | | `JEV_FIXTURES_DIR` | `fixtures` | Where `record` writes and `replay` reads | Write the action yourself when you need something the environment cannot express — a custom transport, per-request model selection, or your own pricing table: ```ts // app/actions.ts 'use server'; import { createResolver } from 'jev-ui/server'; const resolve = createResolver({ model: 'jev-1.13.0', pricing: myRates }); export async function askJev(decisions, state) { return resolve(decisions, state); } ``` ## Render a judgment ```tsx 'use client'; import { Branch, Option } from 'jev-ui'; export function Answer({ question }: { question: string }) { return ( ); } ``` > The `when` text is the single highest-leverage string in the component. It becomes the model's criteria, and a bare key like "chart" gives it nothing to reason about. ## The rules worth knowing up front - The judgment picks presentation; code owns actions. Nothing here should submit a form, spend money, or delete a row. - The library collects two things on its own — `recent_actions` and `time_spent`. Everything else goes in `app`, with whatever keys you like, and a question reads it by naming the path: `app.tier`. - Every judgment registered in one render pass becomes one request, because the state is ingested once for all of them. - Typed output guarantees the interface, not the truth. Always give a Branch a fallback and a confidence floor. --- # Branch > Pick one subtree out of several, with a no-match outcome and a confidence floor. Branch asks a Choice question and renders the matching child. It is the right primitive when the options are unordered and exactly one should win. ```tsx console.log(cost.shareUsd)} >