<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: yanggmtl</title>
    <description>The latest articles on DEV Community by yanggmtl (@yanggmtl).</description>
    <link>https://dev.to/yanggmtl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3810117%2F0f0bf201-5cbd-4b26-bfac-1ad429b826d3.png</url>
      <title>DEV Community: yanggmtl</title>
      <link>https://dev.to/yanggmtl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yanggmtl"/>
    <language>en</language>
    <item>
      <title>Schema-Driven, Framework-Agnostic Forms: Building a Runtime Engine for React, Vue, Angular &amp; Vanilla JS</title>
      <dc:creator>yanggmtl</dc:creator>
      <pubDate>Mon, 30 Mar 2026 15:21:12 +0000</pubDate>
      <link>https://dev.to/yanggmtl/schema-driven-framework-agnostic-forms-building-a-runtime-engine-for-react-vue-angular--3o26</link>
      <guid>https://dev.to/yanggmtl/schema-driven-framework-agnostic-forms-building-a-runtime-engine-for-react-vue-angular--3o26</guid>
      <description>&lt;p&gt;In this article, I explain how to build dynamic, schema-driven forms that work across React, Vue, Angular, and Vanilla JS using a registry-driven runtime engine. The forms fully decouple data, UI, and logic, and support conditional logic, dynamic validation, and plugin extensibility—all without hardcoding components.&lt;br&gt;
You can try it out here: &lt;a href="https://github.com/Formitiva/formitiva-monorepo" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt; | &lt;a href="https://www.npmjs.com/org/formitiva" rel="noopener noreferrer"&gt;Install via npm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In most form systems, even schema-driven ones, logic is still tightly coupled to structure or UI.&lt;/p&gt;

&lt;p&gt;The goal of Formitiva is to go further:&lt;/p&gt;

&lt;p&gt;Fully decouple &lt;strong&gt;data&lt;/strong&gt;, &lt;strong&gt;presentation&lt;/strong&gt;, and &lt;strong&gt;behavior&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem with Traditional Separation
&lt;/h2&gt;

&lt;p&gt;Typical systems separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data (JSON schema)&lt;/li&gt;
&lt;li&gt;UI (components)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But logic often remains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;embedded in schema&lt;/li&gt;
&lt;li&gt;hardcoded in components&lt;/li&gt;
&lt;li&gt;tied to specific frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates hidden coupling.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Key Idea: Reference, Don’t Embed
&lt;/h2&gt;

&lt;p&gt;Instead of embedding logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"validatorHandlerName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"emailValidator"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The schema only &lt;strong&gt;references behavior&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It does not define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how validation works&lt;/li&gt;
&lt;li&gt;how UI renders&lt;/li&gt;
&lt;li&gt;how logic executes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Registry System
&lt;/h2&gt;

&lt;p&gt;All implementations live in a registry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;component registry&lt;/li&gt;
&lt;li&gt;validation registry&lt;/li&gt;
&lt;li&gt;logic/workflow registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The registry acts as a lookup system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string reference → actual implementation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Runtime Engine
&lt;/h2&gt;

&lt;p&gt;The runtime engine is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parsing schema&lt;/li&gt;
&lt;li&gt;Resolving references via registry&lt;/li&gt;
&lt;li&gt;Executing logic (validation, conditions)&lt;/li&gt;
&lt;li&gt;Delegating rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This transforms the system into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Schema → References → Registry → Runtime Execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Renderer Abstraction (Framework-Agnostic Design)
&lt;/h2&gt;

&lt;p&gt;The runtime does not render UI directly.&lt;/p&gt;

&lt;p&gt;Instead, it delegates to &lt;strong&gt;renderer adapters&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Vue&lt;/li&gt;
&lt;li&gt;Vanilla JS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each adapter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;receives abstract UI definitions&lt;/li&gt;
&lt;li&gt;maps them to framework-specific components&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Resulting Architecture
&lt;/h2&gt;

&lt;p&gt;You get a layered system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema → declarative intent&lt;/li&gt;
&lt;li&gt;Registry → implementation mapping&lt;/li&gt;
&lt;li&gt;Runtime → execution engine&lt;/li&gt;
&lt;li&gt;Renderer → UI layer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Extensibility Through Plugins
&lt;/h2&gt;

&lt;p&gt;Because everything is resolved via registry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new components can be added&lt;/li&gt;
&lt;li&gt;new validators can be injected&lt;/li&gt;
&lt;li&gt;new behaviors can be introduced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without modifying core logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This architecture enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;true separation of concerns&lt;/li&gt;
&lt;li&gt;cross-framework portability&lt;/li&gt;
&lt;li&gt;backend-driven UI&lt;/li&gt;
&lt;li&gt;low-code possibilities&lt;/li&gt;
&lt;li&gt;long-term scalability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Decoupling isn’t just about separating files or layers.&lt;/p&gt;

&lt;p&gt;It’s about removing &lt;strong&gt;direct knowledge between parts of the system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The registry pattern achieves that by introducing &lt;strong&gt;controlled indirection at runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s what makes Formitiva fundamentally different.&lt;/p&gt;

</description>
      <category>react</category>
      <category>vue</category>
      <category>angular</category>
      <category>vanilla</category>
    </item>
    <item>
      <title>Schema-Driven Forms in React: Comparing RJSF, JSON Forms, Uniforms, Form.io, and Formitiva</title>
      <dc:creator>yanggmtl</dc:creator>
      <pubDate>Thu, 12 Mar 2026 14:43:35 +0000</pubDate>
      <link>https://dev.to/yanggmtl/schema-driven-forms-in-react-comparing-rjsf-json-forms-uniforms-formio-and-formitiva-2fg2</link>
      <guid>https://dev.to/yanggmtl/schema-driven-forms-in-react-comparing-rjsf-json-forms-uniforms-formio-and-formitiva-2fg2</guid>
      <description>&lt;p&gt;Modern applications often need forms that are &lt;strong&gt;dynamic, configurable, and reusable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding forms in JSX, many teams adopt &lt;strong&gt;schema-driven forms&lt;/strong&gt;, where the structure of a form is defined using data.&lt;/p&gt;

&lt;p&gt;Several libraries implement this idea, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React JSONSchema Form&lt;/li&gt;
&lt;li&gt;JSON Forms&lt;/li&gt;
&lt;li&gt;Uniforms&lt;/li&gt;
&lt;li&gt;Form.io&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools allow developers to define forms declaratively and generate the UI automatically.&lt;/p&gt;

&lt;p&gt;However, they differ significantly in &lt;strong&gt;how they separate data, UI, and business logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article compares these approaches and explains why registry-based logic can make schema-driven forms more scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Schema-Driven Forms Exist
&lt;/h2&gt;

&lt;p&gt;Traditional React forms often combine multiple responsibilities inside the same component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data structure&lt;/li&gt;
&lt;li&gt;UI rendering&lt;/li&gt;
&lt;li&gt;validation logic&lt;/li&gt;
&lt;li&gt;submission workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;validatePassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach works well for small forms, but it becomes difficult to scale when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;many forms exist across a platform&lt;/li&gt;
&lt;li&gt;validation rules must be reused&lt;/li&gt;
&lt;li&gt;forms are generated dynamically&lt;/li&gt;
&lt;li&gt;domain-specific field types are needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Schema-driven forms attempt to solve this by defining forms using structured data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Layers of a Form System
&lt;/h2&gt;

&lt;p&gt;A useful way to analyze form libraries is to look at three concerns:&lt;/p&gt;

&lt;h3&gt;
  
  
  Data
&lt;/h3&gt;

&lt;p&gt;Defines the structure of the form:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fields&lt;/li&gt;
&lt;li&gt;data types&lt;/li&gt;
&lt;li&gt;constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usually represented as &lt;strong&gt;schemas or JSON definitions&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI
&lt;/h3&gt;

&lt;p&gt;Responsible for rendering inputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;components&lt;/li&gt;
&lt;li&gt;widgets&lt;/li&gt;
&lt;li&gt;layouts&lt;/li&gt;
&lt;li&gt;design system integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Logic
&lt;/h3&gt;

&lt;p&gt;Handles behavior such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;conditional rules&lt;/li&gt;
&lt;li&gt;submission workflows&lt;/li&gt;
&lt;li&gt;API integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key architectural question becomes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does business logic live?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison Overview
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;UI&lt;/th&gt;
&lt;th&gt;Logic&lt;/th&gt;
&lt;th&gt;Decoupling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RJSF&lt;/td&gt;
&lt;td&gt;JSON Schema&lt;/td&gt;
&lt;td&gt;Widgets&lt;/td&gt;
&lt;td&gt;Component logic&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON Forms&lt;/td&gt;
&lt;td&gt;JSON Schema&lt;/td&gt;
&lt;td&gt;UI Schema&lt;/td&gt;
&lt;td&gt;Rules engine&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uniforms&lt;/td&gt;
&lt;td&gt;Schema adapters&lt;/td&gt;
&lt;td&gt;Themes&lt;/td&gt;
&lt;td&gt;Component logic&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form.io&lt;/td&gt;
&lt;td&gt;JSON definitions&lt;/td&gt;
&lt;td&gt;Renderer&lt;/td&gt;
&lt;td&gt;Embedded logic&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Formitiva&lt;/td&gt;
&lt;td&gt;Schema definition&lt;/td&gt;
&lt;td&gt;Component registry&lt;/td&gt;
&lt;td&gt;Registered logic&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  RJSF
&lt;/h2&gt;

&lt;p&gt;React JSONSchema Form is one of the most popular schema-driven form libraries for React.&lt;/p&gt;

&lt;p&gt;It renders forms directly from &lt;strong&gt;JSON Schema.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The form engine maps schema types to UI components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;strong JSON Schema support&lt;/li&gt;
&lt;li&gt;automatic form generation&lt;/li&gt;
&lt;li&gt;customizable widgets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;Submission logic typically remains inside the React component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means business logic is still &lt;strong&gt;tied to UI components&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Forms
&lt;/h2&gt;

&lt;p&gt;JSON Forms introduces a clearer separation between data and UI.&lt;/p&gt;

&lt;p&gt;It uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Schema (JSON Schema)&lt;/li&gt;
&lt;li&gt;UI Schema (layout definition)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example UI schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VerticalLayout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scope&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/properties/username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;explicit separation of structure and layout&lt;/li&gt;
&lt;li&gt;rule-based UI behavior&lt;/li&gt;
&lt;li&gt;framework-agnostic architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;Submission workflows and business logic are usually implemented outside the schema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uniforms
&lt;/h2&gt;

&lt;p&gt;Uniforms focuses on &lt;strong&gt;schema adapters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It supports multiple schema systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON Schema&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;SimpleSchema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AutoForm&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;flexible schema support&lt;/li&gt;
&lt;li&gt;good integration with UI frameworks&lt;/li&gt;
&lt;li&gt;minimal boilerplate&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;Validation and workflows are still mostly handled in React logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Form.io
&lt;/h2&gt;

&lt;p&gt;Form.io is closer to a complete form platform.&lt;/p&gt;

&lt;p&gt;Forms are defined entirely in JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"textfield"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;visual form builder&lt;/li&gt;
&lt;li&gt;dynamic forms&lt;/li&gt;
&lt;li&gt;built-in conditional logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;Logic is usually embedded inside the form definition itself, which can reduce reuse across forms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Comparison
&lt;/h2&gt;

&lt;p&gt;Different libraries organize form responsibilities differently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RJSF
Schema → Renderer → Component Logic

JSON Forms
Schema + UI Schema → Renderer → Rules

Uniforms
Schema Adapter → UI Theme → Component Logic

Form.io
Form Definition → Renderer → Embedded Logic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most approaches successfully separate &lt;strong&gt;data and UI&lt;/strong&gt;, but logic often remains tied to forms or components.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Registry-Driven Approach
&lt;/h2&gt;

&lt;p&gt;Formitiva takes a different approach.&lt;/p&gt;

&lt;p&gt;Instead of embedding logic in schemas or components, it introduces a &lt;strong&gt;registry system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Schemas reference behaviors declaratively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_information&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;validationHandlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user:passwordMatch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;submitHandlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user:userSubmission&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual implementations are registered separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerFormValidationHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user:passwordMatch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;passwordMatchValidator&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;registerSubmissionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user:userSubmission&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;submitUserData&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Formitiva Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------------+
|      Form Schema     |
|      (Data Layer)    |
+----------------------+
           |
           v
+----------------------+
|       Registry       |
| (UI + Logic Mapping) |
+----------------------+
           |
           v
+----------------------+
|       Renderer       |
|       (React UI)     |
+----------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture separates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data definitions&lt;/li&gt;
&lt;li&gt;UI components&lt;/li&gt;
&lt;li&gt;business logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Registration-Based Logic Helps
&lt;/h2&gt;

&lt;p&gt;The registry pattern enables several advantages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reusable Validation
&lt;/h3&gt;

&lt;p&gt;Validators can be reused across many forms.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user:passwordMatch
geo:coordinateValidator
payment:cardValidator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reusable Workflows
&lt;/h3&gt;

&lt;p&gt;Submission logic becomes reusable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API integration&lt;/li&gt;
&lt;li&gt;workflow orchestration&lt;/li&gt;
&lt;li&gt;event triggers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Domain-Specific Field Types
&lt;/h2&gt;

&lt;p&gt;Custom fields can be registered once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;point2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PointInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any schema can use that type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Form Platforms
&lt;/h3&gt;

&lt;p&gt;The architecture works well for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dynamic forms from APIs&lt;/li&gt;
&lt;li&gt;low-code platforms&lt;/li&gt;
&lt;li&gt;domain-specific applications&lt;/li&gt;
&lt;li&gt;large systems with many forms&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Use Each Approach
&lt;/h2&gt;

&lt;p&gt;Different libraries work best in different situations.&lt;/p&gt;

&lt;h3&gt;
  
  
  RJSF
&lt;/h3&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simple JSON Schema forms&lt;/li&gt;
&lt;li&gt;rapid prototyping&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JSON Forms
&lt;/h3&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dynamic UI layouts&lt;/li&gt;
&lt;li&gt;rule-based behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Uniforms
&lt;/h3&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;projects using schema adapters&lt;/li&gt;
&lt;li&gt;strong design system integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Form.io
&lt;/h3&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;full form platforms&lt;/li&gt;
&lt;li&gt;visual form builders&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Formitiva
&lt;/h3&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reusable form ecosystems&lt;/li&gt;
&lt;li&gt;dynamic form platforms&lt;/li&gt;
&lt;li&gt;domain-specific workflows&lt;/li&gt;
&lt;li&gt;large applications with many forms&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Schema-driven forms are a powerful way to build dynamic user interfaces.&lt;/p&gt;

&lt;p&gt;Libraries like &lt;strong&gt;RJSF, JSON Forms, Uniforms, and Form.io&lt;/strong&gt; already separate &lt;strong&gt;form structure from UI rendering&lt;/strong&gt;, making forms easier to maintain.&lt;/p&gt;

&lt;p&gt;However, business logic is often still tied to &lt;strong&gt;components or form definitions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A registry-based architecture pushes this separation further by treating validation, workflows, and UI components as independent, reusable modules.&lt;/p&gt;

&lt;p&gt;This approach makes schema-driven forms not just a UI convenience, but a foundation for scalable form platforms.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Decouple Data, UI and Logic in React Forms Using the Formitiva Registry System</title>
      <dc:creator>yanggmtl</dc:creator>
      <pubDate>Wed, 11 Mar 2026 17:38:24 +0000</pubDate>
      <link>https://dev.to/yanggmtl/decouple-data-ui-and-logic-in-react-forms-using-the-formitiva-registry-system-67n</link>
      <guid>https://dev.to/yanggmtl/decouple-data-ui-and-logic-in-react-forms-using-the-formitiva-registry-system-67n</guid>
      <description>&lt;p&gt;Most React forms mix several responsibilities in the same place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data definition&lt;/li&gt;
&lt;li&gt;UI components&lt;/li&gt;
&lt;li&gt;validation logic&lt;/li&gt;
&lt;li&gt;submission workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first this feels natural. A form component renders inputs, validates data, and submits the data to an API.&lt;/p&gt;

&lt;p&gt;But as applications grow, this approach becomes harder to maintain. Forms start to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reuse the same validation rules&lt;/li&gt;
&lt;li&gt;trigger shared workflows&lt;/li&gt;
&lt;li&gt;appear dynamically from a backend&lt;/li&gt;
&lt;li&gt;evolve independently from UI implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When data structure, UI rendering, and business logic are tightly coupled inside React components, even small changes can ripple across the codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Traditional React Forms Don't Scale
&lt;/h2&gt;

&lt;p&gt;The main challenge is that forms often become &lt;strong&gt;mini applications inside a single React component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Over time, the component starts handling multiple responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;defining the data structure&lt;/li&gt;
&lt;li&gt;rendering UI inputs&lt;/li&gt;
&lt;li&gt;performing validation&lt;/li&gt;
&lt;li&gt;coordinating submission workflows&lt;/li&gt;
&lt;li&gt;integrating with APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This works for small forms, but the complexity grows quickly when applications require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dozens or hundreds of forms&lt;/li&gt;
&lt;li&gt;reusable validation logic&lt;/li&gt;
&lt;li&gt;domain-specific field types&lt;/li&gt;
&lt;li&gt;dynamic forms generated from APIs or databases&lt;/li&gt;
&lt;li&gt;visual form builders or low-code systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When UI, data, and business logic are tightly coupled, forms become harder to reuse, extend, or generate dynamically.&lt;/p&gt;

&lt;p&gt;This is the problem &lt;strong&gt;Formitiva&lt;/strong&gt; tries to solve.&lt;/p&gt;

&lt;p&gt;Formitiva introduces a &lt;strong&gt;registry system&lt;/strong&gt; that separates &lt;strong&gt;form data, UI components, and business logic&lt;/strong&gt;. Instead of embedding validation and submission logic inside form components, those behaviors are registered once and referenced by schema definitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formitiva in One Sentence
&lt;/h2&gt;

&lt;p&gt;Formitiva lets you &lt;strong&gt;define forms as schema data while registering the UI and logic those schemas should use&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A form definition can stay small and declarative:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInformationDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_information&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User Information&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;validationHandlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user:passwordMatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;submitHandlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user:userDataSubmission&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;validationHandlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passwordValidator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;confirmPassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Confirm Password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;validationHandlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passwordValidator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This definition describes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the fields in the form&lt;/li&gt;
&lt;li&gt;the field types&lt;/li&gt;
&lt;li&gt;the validation and submission handlers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it does &lt;strong&gt;not contain&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React components&lt;/li&gt;
&lt;li&gt;validation functions&lt;/li&gt;
&lt;li&gt;API calls&lt;/li&gt;
&lt;li&gt;workflow logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The schema only describes &lt;strong&gt;intent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The actual behavior is resolved through the &lt;strong&gt;registry system&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separating Data, UI, and Logic
&lt;/h2&gt;

&lt;p&gt;Formitiva intentionally separates forms into three independent concerns:&lt;/p&gt;

&lt;p&gt;At a high level, the architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------------+
|      Form Schema     |
|      (Data Layer)    |
+----------------------+
           |
           v
+----------------------+
|       Registry       |
| (UI + Logic Mapping) |
+----------------------+
           |
           v
+----------------------+
|       Renderer       |
|       (React UI)     |
+----------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data (Form Definition)
&lt;/h3&gt;

&lt;p&gt;The schema describes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fields&lt;/li&gt;
&lt;li&gt;data types&lt;/li&gt;
&lt;li&gt;constraints&lt;/li&gt;
&lt;li&gt;references to behaviors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It represents the &lt;strong&gt;data model of the form&lt;/strong&gt;, which means it can come from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a database&lt;/li&gt;
&lt;li&gt;a backend service&lt;/li&gt;
&lt;li&gt;a CMS&lt;/li&gt;
&lt;li&gt;a visual form builder&lt;/li&gt;
&lt;li&gt;configuration files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because definitions are pure data, they are portable and easy to version.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI (Field Components)
&lt;/h3&gt;

&lt;p&gt;The UI layer is responsible only for &lt;strong&gt;rendering inputs and collecting user input&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Field components are mapped to field types through the registry.&lt;/p&gt;

&lt;p&gt;The schema never references a specific React component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logic (Validation and Workflows)
&lt;/h3&gt;

&lt;p&gt;Business logic such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validation rules&lt;/li&gt;
&lt;li&gt;submission workflows&lt;/li&gt;
&lt;li&gt;button actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;is implemented separately and registered with the system.&lt;/p&gt;

&lt;p&gt;Schemas only reference logic by &lt;strong&gt;name&lt;/strong&gt;, not by function implementation.&lt;/p&gt;

&lt;p&gt;This separation allows forms to evolve without tightly coupling the layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Registry System Does
&lt;/h2&gt;

&lt;p&gt;The Formitiva registry is a &lt;strong&gt;central lookup system&lt;/strong&gt; that connects schema references to real implementations.&lt;/p&gt;

&lt;p&gt;Instead of embedding logic directly inside form definitions or components, you &lt;strong&gt;register behaviors once&lt;/strong&gt; and &lt;strong&gt;reference them by name&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The registry supports registering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;field validation handlers&lt;/li&gt;
&lt;li&gt;form validation handlers&lt;/li&gt;
&lt;li&gt;submission workflows&lt;/li&gt;
&lt;li&gt;button actions&lt;/li&gt;
&lt;li&gt;custom field components&lt;/li&gt;
&lt;li&gt;plugins that bundle multiple extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At runtime, Formitiva reads the schema and resolves those references through the registry.&lt;/p&gt;

&lt;p&gt;This design is what allows &lt;strong&gt;form data, UI, and business logic to remain independent&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registering Field and Form Validation
&lt;/h2&gt;

&lt;p&gt;Validation is one of the first things that tends to get mixed into UI components.&lt;/p&gt;

&lt;p&gt;For example, many form implementations attach validation logic directly to inputs or inside React components.&lt;/p&gt;

&lt;p&gt;Formitiva moves validation logic into the registry.&lt;/p&gt;

&lt;p&gt;You can register validation handlers like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerFormValidationHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user:passwordMatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;passwordMatchValidator&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the schema references those handlers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"validationHandlerName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:passwordMatch"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach has several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validation logic is reusable across many forms&lt;/li&gt;
&lt;li&gt;schemas remain simple and declarative&lt;/li&gt;
&lt;li&gt;validation is no longer tied to UI components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The schema only says which validator to use, while the registry provides the implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registering Submission Workflows
&lt;/h2&gt;

&lt;p&gt;Submission logic is another area where business logic often leaks into UI components.&lt;/p&gt;

&lt;p&gt;In many React applications, the form component contains API calls or workflow orchestration inside its submit handler.&lt;/p&gt;

&lt;p&gt;Formitiva separates this by registering submission handlers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerSubmissionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user:userDataSubmission&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;userDataSubmissionHandler&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The schema then references that handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"submitHandlerName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user:userDataSubmission"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps workflows reusable and independent from the UI.&lt;/p&gt;

&lt;p&gt;Submission handlers can perform tasks such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calling APIs&lt;/li&gt;
&lt;li&gt;triggering backend workflows&lt;/li&gt;
&lt;li&gt;saving data&lt;/li&gt;
&lt;li&gt;dispatching events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, &lt;strong&gt;this business logic no longer lives inside React components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The form component simply renders the UI, while the submission handler controls what happens after submission.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registering Custom Field Components
&lt;/h2&gt;

&lt;p&gt;The most powerful extension point in the registry system is &lt;strong&gt;custom field types&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Schemas describe what type of data a field represents, but they do not define how the field is rendered.&lt;/p&gt;

&lt;p&gt;Instead, the registry maps field types to React components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registering a Custom Field Type
&lt;/h3&gt;

&lt;p&gt;For example, you can register a new field type called point2d:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;point2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Point2DInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once registered, any schema field with this type will be rendered using the Point2DInput component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"point2d"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows schemas to remain UI-agnostic, while the registry determines how each field should appear.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registering a Type Validator
&lt;/h3&gt;

&lt;p&gt;A field type can also have a type-level validator that checks whether the data matches the expected format.&lt;/p&gt;

&lt;p&gt;For example, a built-in &lt;code&gt;int&lt;/code&gt; type validator might check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether the value is a valid integer&lt;/li&gt;
&lt;li&gt;whether it satisfies constraints such as min and max&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Custom types can register their own validator as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerFieldTypeValidationHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;point2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pointValidator&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The validator ensures that values for the point2d type follow the expected structure (for example [x, y] coordinates).&lt;/p&gt;

&lt;p&gt;Registering a type validator is &lt;strong&gt;optional&lt;/strong&gt;. If a custom type does not require additional validation, it can be omitted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;p&gt;This design allows you to create &lt;strong&gt;domain-specific field types&lt;/strong&gt; while keeping schemas clean and declarative.&lt;/p&gt;

&lt;p&gt;It also makes integration with design systems easier, because schemas only reference &lt;strong&gt;field types&lt;/strong&gt;, not specific UI components.&lt;/p&gt;

&lt;p&gt;As a result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schemas describe data&lt;/li&gt;
&lt;li&gt;components handle presentation&lt;/li&gt;
&lt;li&gt;validators enforce data correctness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each concern remains independent, which keeps forms easier to maintain and extend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizing Extensions with Plugins
&lt;/h2&gt;

&lt;p&gt;As your form platform grows, you may want to group related extensions together.&lt;/p&gt;

&lt;p&gt;Formitiva supports this through plugins.&lt;/p&gt;

&lt;p&gt;A plugin can bundle components, validators, and submission handlers into a single package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PointPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;point_plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;point2d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Point2DInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;fieldCustomValidators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;point2d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;nonNegativePoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;formValidators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;point2d:regionValidator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;regionValidator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;submissionHandlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;point2d:alertSubmission&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;alertSubmissionHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PointPlugin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps extensions organized instead of scattering logic across different parts of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Formitiva Architecture
&lt;/h2&gt;

&lt;p&gt;A helpful way to understand Formitiva is to think of it as three layers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Definition
     ↓
Registry
     ↓
Renderer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Definition (Data Layer)
&lt;/h3&gt;

&lt;p&gt;The schema describes the &lt;strong&gt;data structure of the form&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It can come from code, APIs, databases, or visual builders.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registry (Logic &amp;amp; UI Mapping)
&lt;/h3&gt;

&lt;p&gt;The registry maps schema references to implementations such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validators&lt;/li&gt;
&lt;li&gt;workflows&lt;/li&gt;
&lt;li&gt;components&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Renderer (UI Layer)
&lt;/h3&gt;

&lt;p&gt;The renderer converts the definition into a working form UI at runtime.&lt;/p&gt;

&lt;p&gt;Because of this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schemas remain pure data&lt;/li&gt;
&lt;li&gt;UI components stay focused on rendering&lt;/li&gt;
&lt;li&gt;business logic stays reusable&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When This Architecture Works Best
&lt;/h2&gt;

&lt;p&gt;The registry-first approach becomes especially valuable when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;forms are stored in databases or APIs&lt;/li&gt;
&lt;li&gt;many forms exist across a platform&lt;/li&gt;
&lt;li&gt;domain-specific field types are required&lt;/li&gt;
&lt;li&gt;submission workflows are reused&lt;/li&gt;
&lt;li&gt;a visual form builder or low-code system is needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your application only has a few static forms, traditional JSX-based forms may be enough.&lt;/p&gt;

&lt;p&gt;But once forms become &lt;strong&gt;a platform capability rather than just page components&lt;/strong&gt;, separating UI and business logic becomes much more important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Separating UI and business logic in forms is harder than it first appears.&lt;/p&gt;

&lt;p&gt;In many React applications, form components gradually accumulate responsibilities: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;defining data structures&lt;/li&gt;
&lt;li&gt;rendering inputs&lt;/li&gt;
&lt;li&gt;validating data&lt;/li&gt;
&lt;li&gt;calling APIs&lt;/li&gt;
&lt;li&gt;coordinating workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This works for small forms, but it becomes difficult to scale when forms need to be reused or dynamically generated.&lt;/p&gt;

&lt;p&gt;Formitiva addresses this with its &lt;strong&gt;registry system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of embedding logic inside form components, Formitiva lets you &lt;strong&gt;register validation handlers, submission workflows, and field components separately&lt;/strong&gt;, while schemas define the &lt;strong&gt;data structure and reference those behaviors declaratively&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This separation of data, UI, and logic keeps schemas portable while making UI components and business logic reusable.&lt;/p&gt;

&lt;p&gt;And that separation is what turns schema-driven forms from a &lt;strong&gt;nice idea into a practical architecture for real applications&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Currently Formitiva supports React forms, while &lt;strong&gt;Vue and Angular integrations are currently in testing&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javasctipt</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Stop Hardcoding React Forms: Build Dynamic Schema-Driven Forms with Formitiva</title>
      <dc:creator>yanggmtl</dc:creator>
      <pubDate>Fri, 06 Mar 2026 16:34:42 +0000</pubDate>
      <link>https://dev.to/yanggmtl/stop-hardcoding-react-forms-build-dynamic-schema-driven-forms-with-formitiva-5d14</link>
      <guid>https://dev.to/yanggmtl/stop-hardcoding-react-forms-build-dynamic-schema-driven-forms-with-formitiva-5d14</guid>
      <description>&lt;p&gt;React developers write a lot of forms.&lt;/p&gt;

&lt;p&gt;Contact forms. Admin panels. Settings pages. Onboarding flows.&lt;/p&gt;

&lt;p&gt;And in most React apps, we build them the same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write JSX&lt;/li&gt;
&lt;li&gt;Wire up validation&lt;/li&gt;
&lt;li&gt;Connect submission logic&lt;/li&gt;
&lt;li&gt;Repeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It works… until the form needs to change without redeploying.&lt;/p&gt;

&lt;p&gt;What happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forms need to change &lt;strong&gt;without redeploying&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Non-frontend teams must &lt;strong&gt;configure fields&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your backend &lt;strong&gt;drives the structure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You support &lt;strong&gt;multi-tenant platforms&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suddenly, hardcoded JSX forms become a bottleneck.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;Formitiva&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Formitiva?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Formitiva/React&lt;/strong&gt; is a schema-driven form platform for React.&lt;/p&gt;

&lt;p&gt;Instead of building forms directly in JSX, you define them as JSON schemas and render them at runtime.&lt;/p&gt;

&lt;p&gt;Your form definition can live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your &lt;strong&gt;source code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In a &lt;strong&gt;database&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Inside a &lt;strong&gt;CMS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Behind an &lt;strong&gt;API&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Formitiva reads the definition and renders the entire form automatically.&lt;/p&gt;

&lt;p&gt;No handcrafting every &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt;.&lt;br&gt;
No redeploy required for structural changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Think of It as a Runtime Form Engine
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Formitiva&lt;/strong&gt; isn’t trying to replace traditional form libraries like Formik or React Hook Form.&lt;/p&gt;

&lt;p&gt;Those tools are fantastic for static, code-defined forms.&lt;/p&gt;

&lt;p&gt;Formitiva is different.&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema-first&lt;/strong&gt; – Forms are defined as structured JSON&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime-configurable&lt;/strong&gt; – Update structure without redeploying&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend-friendly&lt;/strong&gt; – Store, version, and serve form definitions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portable&lt;/strong&gt; – Reuse forms across multiple apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s built for dynamic environments where form structure is data — not UI code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Schema-Driven Forms Matter
&lt;/h2&gt;

&lt;p&gt;Most React form libraries assume:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The structure is mostly static&lt;/li&gt;
&lt;li&gt;Developers define fields in JSX&lt;/li&gt;
&lt;li&gt;Structural changes require a redeploy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s fine for marketing forms or simple CRUD screens.&lt;/p&gt;

&lt;p&gt;But in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SaaS platforms&lt;/li&gt;
&lt;li&gt;Enterprise systems&lt;/li&gt;
&lt;li&gt;Multi-tenant applications&lt;/li&gt;
&lt;li&gt;CMS-driven architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those assumptions quickly become limitations.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Formitiva&lt;/strong&gt;, the UI becomes a &lt;strong&gt;rendering layer&lt;/strong&gt;. The structure lives in data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Core Mental Model
&lt;/h2&gt;

&lt;p&gt;Formitiva is built around a few key concepts:&lt;/p&gt;
&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;p&gt;The JSON schema describing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fields&lt;/li&gt;
&lt;li&gt;Labels&lt;/li&gt;
&lt;li&gt;Validation rules&lt;/li&gt;
&lt;li&gt;Conditional logic&lt;/li&gt;
&lt;li&gt;Behavior&lt;/li&gt;
&lt;li&gt;Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The values object (for editing existing data or preloading state).&lt;/p&gt;
&lt;h3&gt;
  
  
  Renderer
&lt;/h3&gt;

&lt;p&gt;The React component that transforms a definition into a live form.&lt;/p&gt;
&lt;h3&gt;
  
  
  Registries
&lt;/h3&gt;

&lt;p&gt;Extension points for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom components&lt;/li&gt;
&lt;li&gt;Custom validators&lt;/li&gt;
&lt;li&gt;Submission handlers&lt;/li&gt;
&lt;li&gt;Button actions&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  i18n Support
&lt;/h3&gt;

&lt;p&gt;Translation helpers built into the system.&lt;/p&gt;

&lt;p&gt;This separation keeps things clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure → Data&lt;/li&gt;
&lt;li&gt;Rendering → Engine&lt;/li&gt;
&lt;li&gt;Customization → Registries&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Getting Started in 2 Minutes
&lt;/h2&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @formitiva/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a form definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Formitiva&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@formitiva/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;contactForm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Contact Form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multiline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formitiva&lt;/span&gt; &lt;span class="na"&gt;definitionData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1tcrz32js29qrdemowb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1tcrz32js29qrdemowb.png" alt="Formitiva rendering a schema-driven form" width="360" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No JSX per field.&lt;br&gt;
No manual wiring.&lt;br&gt;
The form renders entirely from your schema.&lt;/p&gt;
&lt;h3&gt;
  
  
  Handling Submissions
&lt;/h3&gt;

&lt;p&gt;Just pass an &lt;code&gt;onSubmit&lt;/code&gt; handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formitiva&lt;/span&gt;
  &lt;span class="na"&gt;definitionData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;instanceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also register named submission handlers — which is powerful when your backend decides how a form should be processed.&lt;/p&gt;

&lt;p&gt;Perfect for API-driven workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You Use Formitiva?
&lt;/h2&gt;

&lt;p&gt;Formitiva shines when forms are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generated from backend data&lt;/li&gt;
&lt;li&gt;Frequently updated&lt;/li&gt;
&lt;li&gt;Reused across multiple applications&lt;/li&gt;
&lt;li&gt;Managed by low-code teams&lt;/li&gt;
&lt;li&gt;Stored and versioned in a database&lt;/li&gt;
&lt;li&gt;Highly dynamic and rule-driven&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your forms are simple and static, traditional libraries are great.&lt;br&gt;&lt;br&gt;
If your forms are part of a configurable platform — Formitiva becomes very interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Low-Code Builder
&lt;/h2&gt;

&lt;p&gt;Formitiva also includes a drag-and-drop Builder.&lt;/p&gt;

&lt;p&gt;This enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designers to create forms visually&lt;/li&gt;
&lt;li&gt;Product teams to configure fields&lt;/li&gt;
&lt;li&gt;Non-frontend contributors to maintain workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While developers still retain full control through registries and customization hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Big Idea
&lt;/h2&gt;

&lt;p&gt;Most React form libraries treat forms as components.&lt;/p&gt;

&lt;p&gt;Formitiva treats forms as data.&lt;/p&gt;

&lt;p&gt;That shift unlocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtime configurability&lt;/li&gt;
&lt;li&gt;Backend-driven workflows&lt;/li&gt;
&lt;li&gt;Cross-application portability&lt;/li&gt;
&lt;li&gt;Cleaner separation of concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Define once. Render anywhere. Update without redeploying.&lt;br&gt;&lt;br&gt;
React-ready. Vue support in testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try Formitiva
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Builder:&lt;/strong&gt; &lt;a href="https://formitiva.com/builder" rel="noopener noreferrer"&gt;Try the Form Builder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://formitiva.com" rel="noopener noreferrer"&gt;formitiva.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/formitiva/react" rel="noopener noreferrer"&gt;github.com/formitiva/react&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@formitiva/react" rel="noopener noreferrer"&gt;npmjs.com/package/@formitiva/react&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building configurable systems, admin platforms, or dynamic SaaS products, schema-driven forms can unlock a much more flexible architecture.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
