Skip to content

Form Schema vs. VeeValidate and FormKit

VeeValidate and FormKit are both built around describing your form's structure in the component template — you write <Field>/<FormKit> per field, and logic (validation, show/hide, dependent options) hangs off that markup. That's a good fit when the form is known ahead of time and doesn't change at runtime.

Form Schema solves a different problem — a form whose structure is itself data: it arrives from the server, gets assembled from a CMS, depends on the user's role, or on the previous wizard step's answer. Instead of markup, an array of FieldDefinition; instead of a template, useForm(schema), which can render on top of that schema however you like — headless with your own markup, or ui-themes for a ready-made one.

Where this actually matters

  • The form changes at runtime. visible/disabled/options on a FieldDefinition accept functions of the form's current values — a field decides whether to show itself before you'd ever write a v-if in a template. In VeeValidate/FormKit the same logic is component-template code you write fresh for every such form.
  • The schema comes from the server. If a backend form builder returns JSON, it maps directly onto a FieldDefinition[] — nobody hand-generates a component with conditional markup for 30 fields.
  • SSR with no workarounds. useForm() doesn't touch the DOM on init — the form's state exists independently of wherever it eventually gets rendered.
  • Not locked into one validation schema. validators/asyncValidators are plain functions, but the same field can just as easily wrap an existing Zod/Yup/Valibot schema — no need to relearn validation if the project already has one of those in place.

Where VeeValidate/FormKit are still the more natural fit

If a form is static and known at write time — a login form, a contact form, a 5-field checkout — writing a FieldDefinition[] instead of markup is often just an extra layer of indirection. Form Schema is built for forms that change, not as a wholesale replacement for form markup for its own sake.

See also