Typed form engine for TypeScript

One form contract. Every framework. Any backend.

The typed contract between your backend and every frontend form. State, validation, drafts and submission live in a framework-independent engine; the form itself can travel as data.

npm i @modyra/core

One contract, running

A form contract

A hook keeps form logic in your components. A contract takes it out: one validated document any renderer can run, and any backend — Rust, Java, or a visual builder — can produce.

// contract.json — from a service, a CMS, Studio, or a model
[
  { "name": "email", "kind": "text", "label": "Email",
    "validators": { "required": true, "email": true } },
  { "name": "country", "kind": "select", "label": "Country",
    "options": [{ "value": "IT", "label": "Italy" }] }
]

import { parseDynamicForm } from "@modyra/core";

const doc = parseDynamicForm(contract, { mode: "strict" });
if (!doc.ok) return report(doc.diagnostics);

mountMdyForm(host, doc.fields, doc);        // framework-free
const form = useMdyDynamicForm(doc.fields); // React
// <mdy-dynamic-form [fields]="doc.fields" />  — Angular

Safe enough for strangers — and agents

A contract that arrives over a network is untrusted input, and Modyra parses it that way: a bounded set of kinds, validators, layout nodes and rule operators, rejected or reported before anything renders. That is the boundary an LLM or an agent runtime needs when the form it emits must validate, cancel safely and never execute.

One model, explicit boundaries

Behavior in the engine

Typed state, validation, arrays, drafts, history and submission are independent of the rendering layer.

Rendering is optional

Use the framework-free renderer, connect a framework adapter, or keep the form in a server, worker or test.

Limits stay visible

Adapters differ in UI coverage, SSR behavior and integration depth. Those differences are documented rather than hidden.

When Modyra is the wrong tool

One login form in one React app? react-hook-form is the lighter, safer pick. Modyra pays off when the same form must live in more than one application — or arrive from somewhere you do not control.

The engine measures 26.7 KB gzipped on a realistic typed form with arrays, validation, drafts and undo (core 2.4.0, measured 2026-08-21; reproduce with npm run test:core-bundle). That is the heaviest entry in our own comparison — it is what drafts, cancellation and undo cost when you stop maintaining them yourself.

Start from the layer you need

@modyra/core 2.4.0 ·MIT licensed · eight adapters, two schema adapters, two backend SDKs · engine and widget contract at 2.4.0; adapters, SDKs and Studio below 1.0