Point it at an OpenAPI spec. Get a fully functional frontend. Zero boilerplate.
npx @uigen-dev/cli serve ./openapi.yaml
# → Your UI is live at http://localhost:4400
Documentation: Access Full Docs
No code. No config. No boilerplate. Just a spec.
From a single OpenAPI file, UIGen generates a complete, production-quality frontend:
POST /users/{id}/activateservers list# Run directly with npx - no install required
npx @uigen-dev/cli serve ./openapi.yaml
# Or with a remote spec URL
npx @uigen-dev/cli serve https://petstore3.swagger.io/api/v3/openapi.json
# Custom port
npx @uigen-dev/cli serve ./openapi.yaml --port 8080
# Override the target server
npx @uigen-dev/cli serve ./openapi.yaml --proxy-base https://api.yourapp.com
# Choose a renderer (default: react)
npx @uigen-dev/cli serve ./openapi.yaml --renderer react
Visit http://localhost:4400 to see your generated UI.
git clone https://github.com/darula-hpp/uigen
cd uigen
pnpm install && pnpm build
node packages/cli/dist/index.js serve examples/twilio_messaging_v1.yaml
UIGen parses your OpenAPI spec and converts it into an Intermediate Representation (IR) - a structured description of your resources, operations, schemas, authentication, and relationships. A pre-built React SPA reads that IR and renders the appropriate views.
The CLI serves the SPA and proxies your API calls to your real backend. When running from the monorepo it uses a Vite dev server; when installed via npm/npx it serves the pre-built static dist with a lightweight Node.js HTTP proxy - no Vite required at runtime.
Because the IR is framework-agnostic, the React layer is just the default. The same IR drives @uigen-dev/svelte and @uigen-dev/vue - same spec, different renderer, your choice of stack.
OpenAPI Spec (YAML/JSON)
│
▼
Adapter (parser)
│
▼
IR (typed config)
│
▼
React SPA (renderer)
│
▼ live API calls via proxy
Your API
The IR is the contract. Everything built on top of UIGen talks to the IR - not to the spec format or the UI framework.
| Format | Status |
|---|---|
| OpenAPI 3.x (YAML/JSON) | ✅ Supported |
| Swagger 2.0 | ✅ Supported |
| OpenAPI 3.1 | 🔜 Planned |
$ref handling, circular reference detectionhasMany from nested paths, belongsTo from URI fieldstextarea variant)x-enumNames support)Authorization header injection, logoutserversuigen serve - starts dev server with IR injecteduigen/
├── packages/
│ ├── core/ # Framework-agnostic: adapters, IR types, engine
│ ├── react/ # Opinionated React UI layer
│ └── cli/ # CLI entry point (Commander.js)
├── examples/
│ ├── twilio_messaging_v1.yaml # Twilio Messaging API spec
│ └── stripe.yaml # Stripe API spec
└── pnpm-workspace.yaml
Each package is independently publishable:
| Package | npm | Purpose |
|---|---|---|
@uigen-dev/core |
✅ published | IR types, adapters, engine - framework agnostic. Build your own renderer on top |
@uigen-dev/react |
✅ published | The default React renderer. Extend or swap components via the registry |
@uigen-dev/cli |
✅ published | The npx uigen entry point |
@uigen-dev/svelte |
planned | Svelte renderer - same IR, native Svelte components |
@uigen-dev/vue |
planned | Vue 3 renderer - same IR, native Vue components |
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run type checking
pnpm typecheck
# Run tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:coverage
This project uses Changesets for version management and publishing. See RELEASING.md for detailed instructions.
Quick reference:
# Create a changeset after making changes
pnpm changeset
# Update package versions
pnpm version
# Publish to npm
pnpm release
🚧 In development - not yet released
UIGen's override system lets you selectively customize specific views while keeping everything else auto-generated. You opt in per view - no changes needed to views you don't touch.
Three modes give you different levels of control:
import { overrideRegistry } from '@uigen-dev/react';
// Component mode: full ownership (data fetching, rendering, routing)
overrideRegistry.register({
targetId: 'users.list',
component: MyCustomUserList,
});
// Render mode: UIGen fetches, you control the display
overrideRegistry.register({
targetId: 'users.detail',
render: ({ data, isLoading }) => <MyCustomDetail data={data} loading={isLoading} />,
});
// useHooks mode: side effects only, built-in view renders normally
overrideRegistry.register({
targetId: 'users.create',
useHooks: ({ resource }) => {
useEffect(() => analytics.track('page_view', { resource: resource.uigenId }), []);
},
});
See packages/react/src/overrides/README.md for the full override system documentation.
x-uigen-*)Annotate your OpenAPI spec directly to control how fields are rendered:
x-uigen-label — custom field labelOverride the auto-generated label for any field. Works on object properties, array item schemas, and $ref targets. Supported in both OpenAPI 3.x and Swagger 2.0.
# OpenAPI 3.x
properties:
internal_code:
type: string
x-uigen-label: "Product SKU"
zip_code:
type: string
x-uigen-label: "ZIP / Postal Code"
tags:
type: array
items:
type: string
x-uigen-label: "Tag Value"
# Swagger 2.0 — same syntax
definitions:
Order:
properties:
acct_num:
type: string
x-uigen-label: "Account Number"
Precedence for $ref properties: a label on the referencing property wins over a label on the $ref target, which wins over the auto-humanized key.
Coming in the next release:
x-uigen-widget,x-uigen-hidden,x-uigen-order
Coming soon
// uigen.config.json
{
"theme": {
"primary": "hsl(220, 90%, 56%)",
"font": "Geist"
},
"resources": {
"users": { "label": "Team Members", "defaultPageSize": 50 }
}
}
x-uigen-widget, x-uigen-hidden, x-uigen-order vendor extensions - remaining spec annotationsx-uigen-label - custom field labels via spec annotationuigen.config.json - theme, labels, page sizes, field overridesuigen validate - lint your spec, report what can and can't be generated with actionable errorsuigen generate - output a static production build to a directory@uigen-dev/svelte - Svelte renderer consuming the same IR. Same adapters, different UI layer@uigen-dev/vue - Vue 3 renderer. Drop-in alternative to @uigen-dev/reactuigen ui:config - a visual configuration dashboard served alongside your generated UI. Point-and-click theme editing, field label overrides, resource reordering - no YAML editing required@uigen-dev/plugin-charts - auto-generate chart widgets from numeric data@uigen-dev/plugin-mapbox - map field renderer for geo coordinates$ref resolution works for most cases; deeply nested circular refs may degrade gracefullyGET /resource/{id} endpoint in your spec/services/{id}/members) appear in the sidebar only when viewing a parent detail pageIssues and PRs are welcome. See ARCHITECTURE.md for the full design documentation.
Building a renderer for another framework? The
@uigen-dev/corepackage is the only dependency you need. The IR contract is stable.
MIT