Frontend .mdc

React Formengine AI Form Builder

Cursor rules for generating React forms from screenshots, PDFs, HTML, or text descriptions with validated FormEngine JSON schema. Renders through RSuite, Material UI, or Mantine.

How to use
  1. Copy the rule content.
  2. In your project root, create .cursorrules or .cursor/rules/react-formengine-ai-form-builder.mdc
  3. Paste the content and save.

FormEngine — AI Form Builder for React

Generate production-ready React forms from a screenshot, PDF, HTML, or text description. The output is a validated FormEngine JSON schema plus a runnable App.tsx — portable data, not throwaway JSX.

Default target: FormEngine Core (MIT, free) via @react-form-builder/core

  • @react-form-builder/components-rsuite (or Material UI / Mantine).

Source repo: https://github.com/lukinov/ai-form-builder

What you produce — every time

  1. form.json — a normalized FormEngine schema, validated against the real list of component types from the target UI library.
  2. App.tsx — a runnable React file that imports the schema and renders it through <FormViewer>.
  3. A short validation report (Screen root, unique keys, layout-only css, no smuggled HTML markup, valid validation rule keys).
  4. Install command + a link to the free Online FormBuilder (https://formbuilder.formengine.io) so the user can tweak visually.

Hard rules — never violate

Schema invariants

  • Root is type: "Screen" (NOT "Form").
  • Every component node has key (unique within the tree), type (must exist in the chosen library), and usually props.
  • Every prop value is wrapped: "label": { "value": "Email" } — never "label": "Email".
  • Validations live under schema.validations on the field component that owns the data — never on the Screen root.
  • Use the correct tooltip/error types:
    • RSuite: RsTooltip / RsErrorMessage
    • MUI: MuiTooltip / MuiErrorWrapper
    • Mantine: MtTooltip / MtErrorWrapper

Layout vs. styling

  • css and wrapperCss are layout-only — flex, grid, box-model, margin, padding, gap, width/height, alignment. Never color, font, background, border, shadow, radius, opacity, transform.
  • Visual styling belongs in the UI library’s theme provider in App.tsx (<CustomProvider> / <ThemeProvider> / <MantineProvider>).
  • The legacy style field is forbidden — use css / wrapperCss.
  • The shape is { "any": { "object": { "<layout-key>": "<value>" } } }, never a plain CSS string.
  • No companion .css file alongside App.tsx. No root className. No <style> blocks. No styled-components.

Plain-text strings only

Every string inside any prop is plain text. No HTML markup of any kind, anywhere — no <h1>, <p>, <strong>, <small>, <br>, no style="...", no class="...", no <style> block. Express section headings and structure with components (RsCard with header prop, RsHeader, RsDivider) — not embedded HTML.

Validation rule keys — Zod set only

Valid keys: required, nonEmpty, min, max, length, email, url, uuid, ip, datetime, regex, includes, startsWith, endsWith, lessThan, moreThan, integer, multipleOf, truthy, falsy. There is no minLength / maxLength — use min / max with args.limit.

UI library defaults

  • Default to RSuite. Reference library; widest component set including RsWizard for multi-step forms.
  • Material UI when the user mentions MUI, Material, or their project is on MUI.
  • Mantine when the user mentions Mantine or needs a component that’s Mantine-only (color picker, rich date pickers, segmented control).

State the choice explicitly in the first sentence of the response.

Common renames — always emit the right name

WrongRight
FormScreen
RsFormRsCard or RsContainer
RsSelectPickerRsDropdown
RsRadioRsRadioGroup
RsTextareaRsTextArea (capital A)
RsInputNumberRsNumberFormat
RsUploadRsUploader
MtDatePickerSingleMtDatePicker
MtTextFieldMtTextInput

Side-by-side fields

Use RsContainer with display: flex and children with wrapperCss.any.object.flex: "1". RSuite has no FlexboxGrid/Stack adapter — flex on RsContainer is the mechanism.

Section headings

Use RsCard with the header prop, or RsHeader — never <h1> / <h2> embedded in RsStaticContent content strings.

Conditional rendering

Use renderWhen: { "jsCode": "data.X === Y" } and pair with validateWhen if validations should also be conditional.

App.tsx — minimal starter

Import only the library’s stylesheet. Theme via the library’s provider. No companion CSS. No root className. Layout-level inline styles (maxWidth, margin, padding) on the wrapping <div> are fine.

import "rsuite/dist/rsuite.min.css";
import { FormViewer, BiDi } from "@react-form-builder/core";
import { view } from "@react-form-builder/components-rsuite";
import formJson from "./form.json";

const getForm = () => JSON.stringify(formJson);

export default function App() {
  return (
    <div style={{ maxWidth: 720, margin: "40px auto", padding: 16 }}>
      <FormViewer
        view={view}
        getForm={getForm}
        onFormDataChange={(d) => console.log(d)}
        biDi={BiDi.LTR}
      />
    </div>
  );
}

Free vs. commercial — stay on the MIT side

FormEngine Core is MIT and free. The Designer and some Premium components (Signature, DataGrid, Rich Text, QR Code, Google Maps) are commercial. Don’t emit Premium component types unless the user explicitly asks. Direct people to the free Online FormBuilder (https://formbuilder.formengine.io) for visual editing.

Response shape

Lead paragraph (library + field count) → form.jsonApp.tsx → validation checklist → install command → “tweak visually in the Online FormBuilder” link → 3 next-step doc links into FormEngine Core docs.

Reference

Similar rules

More in Frontend →