Skip to content

enixCode/jsontoui

Repository files navigation

jsontoui

MIT License TypeScript Web Components React Vite Tailwind CSS Zero Dependencies

Define UIs as JSON. Render them anywhere with Web Components.

Warning - This project is for internal/experimental use only. Not production-ready. Use at your own risk.

jsontoui is a complete system for building and rendering user interfaces from JSON definitions - a visual drag-and-drop editor to design layouts, and a standalone renderer library to deploy them.

Screenshots

Visual Editor

Drag-and-drop 16 builtin components onto a 12-column grid. Edit properties, configure actions, preview the result.

Editor

Preview Mode

Live preview inside the editor - toggle to see the rendered result without leaving.

Preview

Rendered Output

The same JSON rendered as a production-ready UI - no editor, no framework, just Web Components on a CSS grid.

Renderer

How It Works

Editor (design tool)  -->  layout.json  -->  Renderer (production)
  1. Design in the visual editor - drag components, set properties, configure actions
  2. Export a .json file describing the layout
  3. Render that JSON anywhere - in a standalone page, or embedded in your app via the renderer library

Quick Start

npm install
npm run dev       # Editor at http://localhost:5173

Render a layout from code

import { registerBuiltins, mount } from "jsontoui/renderer";

await registerBuiltins();

const layout = {
  version: 1,
  meta: { name: "hello" },
  grid: { columns: 12, rowHeight: 40, gap: 8 },
  components: [
    {
      id: "title",
      tag: "jtu-heading",
      src: "builtin",
      layout: { col: 0, row: 0, colSpan: 12, rowSpan: 1 },
      props: { text: "Hello World", level: 2 }
    },
    {
      id: "btn",
      tag: "jtu-button",
      src: "builtin",
      layout: { col: 0, row: 1, colSpan: 4, rowSpan: 1 },
      props: { label: "Submit", variant: "default" },
      actions: {
        click: { type: "webhook", target: "/api/submit", method: "POST" }
      }
    }
  ]
};

const cleanup = await mount(layout, "#app");

Render from a URL

render.html?src=https://api.example.com/layout.json

No build step - just point to a JSON endpoint and it renders.

Generate a form from JSON Schema

import { renderFromSchema, collectFormData } from "jsontoui/renderer";

const schema = {
  type: "object",
  properties: {
    name: { type: "string", description: "Full name" },
    age: { type: "number", minimum: 0 },
    role: { type: "string", enum: ["admin", "user", "guest"] },
    active: { type: "boolean", default: true }
  },
  required: ["name", "role"]
};

const { cleanup } = await renderFromSchema(schema, document.getElementById("form"));
const data = collectFormData(document.getElementById("form"));
// { name: "John", age: 25, role: "admin", active: true }

Features

Editor

  • Drag-and-drop 16 components onto a 12-column grid
  • Type-aware property editing (text, number, boolean, enum, JSON)
  • Import / export LayoutJSON files
  • Preview mode
  • Actions config on buttons (webhook POST, URL navigation)
  • Component palette with category grouping

Renderer

  • mount(json, target) - one-liner to render any layout
  • renderFromSchema(schema, target) - auto-generate forms from JSON Schema Draft-07
  • collectFormData(container) - extract form values as a plain object
  • Actions system - wire clicks to webhook POSTs or redirects
  • render.html?src=URL - standalone render page
  • Zero framework dependencies

Plugins

  • External components loaded at runtime via dynamic import()
  • Plugins are Web Components that define their own ParamSchema for editor integration

Builtin Components

16 Web Components, all using src: "builtin":

Category Components
Display jtu-heading jtu-text jtu-badge jtu-card jtu-avatar jtu-separator
Form jtu-input jtu-textarea jtu-select jtu-checkbox jtu-switch jtu-radio jtu-label
Action jtu-button jtu-toggle jtu-dropdown

LayoutJSON Format

interface LayoutJSON {
  version: 1;
  meta: { name: string; description?: string; author?: string };
  grid: { columns: 12; rowHeight: number; gap: number; maxWidth?: number };
  components: ComponentJSON[];
  theme?: Record<string, string>;
}

interface ComponentJSON {
  id: string;
  tag: string;           // "jtu-input", "jtu-button", etc.
  src: string;           // "builtin" or URL to external Web Component
  layout: { col: number; row: number; colSpan: number; rowSpan: number };
  props: Record<string, unknown>;
  style?: Record<string, string>;
  actions?: Record<string, ActionConfig>;
}

interface ActionConfig {
  type: "webhook" | "navigate";
  target: string;        // URL (http/https only)
  method?: string;       // "POST" | "GET" (webhook only)
  headers?: Record<string, string>;
}

Commands

npm run dev              # Start editor dev server
npm run build            # Build editor + renderer
npm run build:renderer   # Build renderer only
npm run preview          # Preview production build
npm test                 # Run tests
npm run typecheck        # TypeScript type checking

Production Builds

Output Description
dist/editor/ Deployable SPA (the visual editor)
dist/renderer/jsontoui-renderer.js Importable library (ES + UMD)

API

Function Async Description
registerBuiltins() yes Register all 16 builtin Web Components
parseLayout(input) no Parse and validate JSON into LayoutJSON
render(layout, target) yes Render a layout to a DOM element. Returns cleanup function
mount(input, target) yes Parse + render in one call
renderFromSchema(schema, target) yes Generate form from JSON Schema. Returns { cleanup, unmappedFields }
collectFormData(container) no Read form values as Record<string, unknown>

License

MIT

About

JSON-driven UI renderer and visual drag-and-drop editor with Web Components plugin system

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors