@openuidev/lang-core

The framework-agnostic parser, prompt generator, and runtime evaluator behind OpenUI Lang, the DSL that lets LLMs stream typed UI trees.

Library
npm
v0.2.17
8,550stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
74/100Good
Development Activity100
Maintenance52
Community60
Maturity44
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture84
Code Quality82
Innovation78
Learning Curve65

@openuidev/lang-core is the engine underneath OpenUI Lang, a small domain-specific language that lets a large language model describe an application’s UI as a tree of typed component calls rather than raw JSX or markup. This package has no React, Vue, or Svelte dependency — it owns tokenizing and parsing OpenUI Lang source (including incremental, streaming input as it arrives token-by-token from a model), generating the system prompt that teaches an LLM the DSL and available components/tools, evaluating reactive expressions and $variable bindings against live query results at runtime, and merging incremental edits into an already-rendered tree without discarding untouched nodes.

Framework packages like @openuidev/react-lang, @openuidev/vue-lang, and @openuidev/svelte-lang re-export everything here and layer framework-specific components and hooks on top, so lang-core is the piece to reach for when building a new renderer target or working with the DSL directly outside any UI framework.

What You Get

  • One-shot and streaming parsers (createParser, createStreamingParser) that resolve forward references as DSL statements arrive incrementally
  • generateSystemPrompt / generatePrompt to build the exact system prompt an LLM needs from a component library spec and ToolSpec[] tool definitions
  • A runtime evaluator and query manager (evaluate, createQueryManager, createStore) for resolving reactive $variable bindings against live query/mutation state
  • mergeStatements to reconcile incremental LLM edits into an existing element tree without discarding unrelated nodes
  • A typed AST and validation layer (ValidationError, OpenUIError, builtInValidators) shared by every framework-specific OpenUI package
  • An MCP-shaped ToolSpec/McpClientLike surface so tool definitions and errors line up with the Model Context Protocol

Common Use Cases

  • Building a new renderer target for OpenUI Lang (beyond the existing React/Vue/Svelte packages) by consuming the parser and typed AST directly
  • Streaming an LLM’s UI generation token-by-token into a live tree with createStreamingParser, resolving forward references as they arrive
  • Generating the system prompt for a custom component library so an LLM emits valid OpenUI Lang calls against your own components and tools
  • Applying an LLM’s incremental edit to an already-rendered dashboard or chat UI via mergeStatements without a full re-render
  • Wiring reactive $variable bindings and query/mutation results into a custom runtime store outside any of the supported frontend frameworks

Under The Hood

Architecture The package is organized as four largely independent layers under src/: parser/ (lexer → tokenizer → statement splitter → expression/AST parser → prompt generator → serializer, orchestrated through parser/parser.ts and re-exported via parser/index.ts), runtime/ (an evaluator, query manager, and store that resolve reactive expressions and MCP-style tool calls against live state, in runtime/evaluator.ts, runtime/queryManager.ts, and runtime/store.ts), library.ts (the defineComponent/createLibrary registry that ties Zod prop schemas to prompt-signature generation), and a top-level reactive.ts marker used to tag schemas as reactive across the other layers. src/index.ts is a thin barrel re-exporting the public surface of all four layers, so the module boundary is enforced by directory structure rather than by a single facade class; a consumer only importing parser/index.ts never pulls in the runtime evaluator, which is what lets framework packages depend on subsets of this surface.

Tech Stack TypeScript targeting ES2022, built with tsdown into dual ESM (dist/index.mjs) and CJS (dist/index.cjs) outputs plus split .d.mts/.d.cts type declarations, validated pre-publish with publint and @arethetypesreal/attw (check:attw) to catch package-export mismatches. Zod is a peer dependency (versioned via the monorepo’s pnpm catalog) used both for component prop schemas and for tagging/discovering nested schemas inside prompt generation; @modelcontextprotocol/sdk is an optional peer dependency for MCP-shaped tool errors. The only runtime dependency is ci-info, used to suppress postinstall telemetry in CI environments. Tests run on Vitest 4.

Code Quality The package has a dedicated __tests__ directory at the top level and inside parser/ and runtime/, exercising prompt-signature generation, schema tagging/discovery (including nested arrays and unions), and streaming-parser forward-reference resolution: library.test.ts alone asserts on generated prompt output for tagged, array-nested, and union-nested Zod schemas. Errors are modeled as a typed OpenUIError union (OpenUIErrorSource, OpenUIErrorCode) rather than thrown strings, giving callers structured source/code fields to branch on instead of parsing error messages. tsconfig.json enables strict, noUncheckedIndexedAccess, noImplicitReturns, and noFallthroughCasesInSwitch; ESLint and Prettier run in CI via the package’s own ci script (lint:check && format:check), and the monorepo’s GitHub Actions workflows (build-js.yml) build and typecheck on every push.

What Makes It Unique Most LLM-driven UI generation approaches have a model emit JSON or JSX-like text that is validated wholesale after the fact. lang-core instead defines a purpose-built DSL with a streaming parser designed to resolve forward references incrementally — a component referenced before its definition arrives can still resolve once the definition streams in later — which lets a UI tree render progressively as an LLM’s response streams rather than waiting for a complete, parseable document. Combined with mergeStatements, which reconciles a subsequent incremental edit into an already-materialized tree without discarding untouched nodes, this gives OpenUI a live-editing model closer to how a human editor would apply a diff than to a typical “regenerate the whole document” LLM UI pattern.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search