@scottjr632/juxi
v0.1.1
Published
Constrained adaptive React UI powered by Jev decisions
Readme
Juxi
Adaptive UI powered by Jev, with React and native SwiftUI renderers. Your application supplies the components and content; Jev chooses which approved view to show. It does not generate JSX, execute code, or invent component props.
This is an early 0.x library. See Distribution for pinned npm
releases and local snapshot consumption. The public JavaScript entry points remain
juxi, juxi/server, juxi/react, and optional juxi/react-query.
Install
npm install --save-exact juxi@npm:@scottjr632/[email protected]The npm package is @scottjr632/juxi. This alias preserves the juxi imports
used throughout these docs. You can also install the scoped package directly and
import from @scottjr632/juxi, @scottjr632/juxi/react, and the other subpaths.
Source and native adapter: srctl/juxi.
Run the demo
Requires Node.js 22.12 or newer.
npm install
npm run devWithout credentials, the demo uses clearly labeled keyword-based mock decisions.
To try Jev, copy .env.example to .env and set TYPESAFE_API_KEY, then restart the
server. Never use a VITE_ prefix for this secret: those variables are exposed to browsers.
npm run check # formatting, types, tests, library build, demo build
npm run format # format source and documentationTests mock the SDK's HTTP transport; they do not make paid model calls.
The demo starts with no selected view. Try Write me a poem for an unsupported request or Revenue or recent activity? I’m not sure for an ambiguous one. An explicit no-match choice or confidence below 0.7 leaves the dashboard empty; the demo explains the outcome without inventing a view. Live model decisions may vary; keyword-based mock mode demonstrates these cases deterministically.
Framework integrations
Juxi leaves fetching to the application. Start with the framework's native loader; add React Query if your app needs its cache and request lifecycle features.
npm run dev:next # Next.js App Router example, port 3100
npm run dev:start # TanStack Start example, port 3200
npm run build:examplesBoth examples server-render an initial plan, hydrate the same plan in the browser,
and load another plan on navigation. They use mock decisions unless explicitly
started with JUXI_USE_JEV=true and a server-side TYPESAFE_API_KEY.
See Framework integrations for SSR boundaries, optional React Query helpers, cache isolation, and browser test instructions.
Native SwiftUI
adapters/swiftui is a dependency-free local Swift
package for iOS 16+ and macOS 13+. Import JuxiSwiftUI, register application-owned
views with typed Decodable props, and render the same version-1 JSON plans. Unknown
components or invalid props fail closed; an empty plan renders nothing. Planning,
authentication, and credentials remain server-side. No WebKit or generated code.
npm run test:swift # requires a macOS Swift/Xcode toolchainHow it works
- Define your UI once.
defineUIgives each component a description and a Zod props schema. This shared module does not import React. - Choose allowed views.
ui.defineViewsvalidates every option against that same definition.ui.nodechecks component names and props as you write the options. - Bind React implementations.
createRenderer(ui, components)checks the bindings and returns a component that accepts a plan. No repeated descriptions or schemas. - Ask Jev.
createJevPlanner({ views })sends the application state, view descriptions, and shared component descriptions. Invalid or uncertain decisions use a fallback. - Render the plan. The bound renderer checks props with the shared schemas.
// Shared module — imported by both the planner and the rendering module.
const ui = defineUI({
Summary: {
description: 'A short overview of one topic.',
props: z.object({ title: z.string(), detail: z.string() }),
},
});
// Rendering module — implementations are checked against the shared definition.
const UI = createRenderer(ui, { Summary });
<UI plan={plan} />;See Shared UI definitions for complete examples and migration notes.
Vocabulary
- Node: a component name, its props, and an id.
- Option: a named group of nodes, such as an overview or a revenue breakdown.
- Slot: a region of the UI where one option is selected. Each slot has instructions, a fallback option, and a minimum confidence threshold.
- UI definition: component names, descriptions, and schemas shared by the planner and renderer.
- Views: allowed options and fallback rules, bound to a UI definition. Data can vary per request.
- Plan: the selected nodes plus a record of the decisions that selected them.
- Renderer: React implementations bound to the shared UI definition.
Where to start reading
| File | Responsibility |
| --------------------- | ------------------------------------------------------------------ |
| src/core.ts | Public, framework-independent exports |
| src/ui.ts | Shared definitions, typed node creation, and binding views |
| src/plans.ts | Plan validation, fallback decisions, and assembly |
| src/server.ts | Convert views and component descriptions into one Jev request |
| src/react.tsx | Bind React implementations to the shared UI |
| src/react-query.ts | Optional validated query and mutation options |
| demo/ui.ts | The demo's component descriptions and schemas |
| demo/views.ts | Approved combinations of components and fictional data |
| demo/components.tsx | React implementations, with no repeated schemas |
| demo/api.ts | Local endpoint, live calls, and explicit mock mode |
| demo/main.tsx | Intent form and rendering the returned plan |
| test/ | Runtime and compile-time API regression tests |
| adapters/swiftui/ | Native Swift package, usage documentation, and wire-contract tests |
The entry points are juxi, juxi/react, juxi/server, and optional juxi/react-query.
Only the last requires @tanstack/react-query. Import the server entry point only
from server code. The Vite demo uses source imports for fast iteration; framework
examples use the built package to test real consumer imports.
Limits and safety
- This MVP selects approved views, not arbitrary layouts or generated text.
- Jev confidence describes how concentrated its probability distribution is; it is not a guarantee of correctness. Tune thresholds for your application.
- Model decisions must never replace authorization or user confirmation for actions.
- Prop schemas still need to enforce application-specific rules, such as allowed URLs.
- The component returned by
createRendererhandles invalid plans and loading/request errors. Use your application's React error boundary for exceptions thrown inside custom components. - Fetching belongs to the application. The old effect-based
useUIPlanhook has been removed; use a framework loader, React Query, or another request library. - Keep SSR caches request-isolated and reuse the server plan for hydration. Only the JSON plan crosses the data boundary—not definitions, views, or React implementations.
- Shared definitions must not contain secrets or request-specific data. The rendering module imports those definitions too. Keep private data in server-side view construction.
- The demo endpoint is for local development only. Add authentication, rate limits, and an appropriate server before making it public.
build:demobuilds the frontend only; the Vite development API is not a production server.
Juxi is an independent project, not an official TypeSafe product. See the TypeSafe JavaScript SDK documentation for the underlying API.
Contributing
Read AGENTS.md for the project's readability guidelines. Prefer explicit, easy-to-follow
code over short or clever expressions. A new contributor should be able to trace an
intent from the demo form to the selected components without knowing the whole codebase.
