Skip to content

Support other schema libraries through Standard Schema #2

Open

Description

@gabrielgrant

This looks awesome! Would it be possible to support other schema libs? Or is it too closely coupled to the valibot implementation?

Activity

  1. rnza0u commented on Jul 22, 2025

    @rnza0u

    Yep, that would be very nice indeed.

    It would also make it more stable in the long run, especially when validation libraries have breaking changes.

  2. fabian-hiller commented on Jul 23, 2025

    @fabian-hiller
    Member

    Yes, I can replace the Valibot-specific code with the Standard Schema interface for v1. I am a Standard Schema co-creator by the way. However, I must point out that Formisch initializes the form store (each state of the form is a signal) based on the schema structure, but Standard Schema does not provide this information because each schema library is implemented differently. Supporting multiple schema libraries would therefore require us to use adapters for each one, which would decrease DX. Please comment below to let me know which schema library you are interested in using with Formisch.

  3. LeCarbonator commented on Jul 23, 2025

    @LeCarbonator

    @fabian-hiller I'll gladly request a Zod adapter. However, I also got a question regarding the schemas:

    Are there other benefits you see of focusing on valibot specifically instead of Standard Schema apart from the form's store?
    Perhaps working with some of the features that valibot provides that other validation libraries don't? Or maybe playing into Valibot's types?

  4. fabian-hiller commented on Jul 27, 2025

    @fabian-hiller
    Member

    Right now no. But there might be benefits in the long run. For example, we could extract information from the schema to output HTML specific attributes like required automatically for better accessibility. Until the library is more popular it is probably not worth investing time into supporting Zod or other schema libraries as I should probably focus on providing docs and support for meta frameworks first.

  5. gabrielgrant commented on Aug 1, 2025

    @gabrielgrant
    Author

    Personally quite interested in usage with Arktype, but understand there are obviously more features that can be more easily provided by more closely integrating with one/a smaller number of validation/schema libs

  6. Khauri commented on Dec 5, 2025

    @Khauri

    Since there's plans already to support StandardSchema, I think exposing an adapter API and leaving it up to the community to create adapters could be something to consider and isn't too much of a DX hit imo

    import { createForm, Field, Form } from '@formisch/solid';
    import {type} from 'arktype';
    import formischAdapterArkType from 'formisch-adapter-arktype';
    
    const LoginSchema = type({
      email: "string.email",
      password: "string >= 8",
    });
    
    export default function LoginPage() {
      const loginForm = createForm({
        schema: LoginSchema,
        adapter: formischAdapterArkType
      });
      // ...
    }
    
  7. CamilleHbp commented on Dec 9, 2025

    @CamilleHbp

    I concur. This would also do a lot for the library in the long run. A lot of form libraries are tightly coupled with Frontend framework and validation libray. While totally understandable, if Formish supports the biggest frontend frameworks and validation libraries, it would increase adoption, IMO. 💪

  8. fabian-hiller commented on Dec 12, 2025

    @fabian-hiller
    Member

    Thank you for your feedback! If you want to use Formisch with a different schema library than Valibot, don't forget to give the top comment a thumb up. I will use the feedback here to decide whether to include this feature in Formisch v1 or a later version.

  9. frasza commented on Dec 22, 2025

    @frasza

    I would absolutely love to get support for this, since current solution we are using at work is falling behind but we still actively use Zod at the moment. Otherwise library looks fantastic, hope for this to land.

  10. sandros94 commented on Jan 24, 2026

    @sandros94

    For once, I'll be the one who goes against the grain.

    Don't get me wrong, I love StandardSchemaV1. Not only I've helped integrating it in various aspects of the Nuxt/Nitro/h3 ecosystems but I also daily drive it in all projects and personal libraries.

    I personally consider validation schemas the main source of truth for all forms. In todays world if you leave a public-facing form unattended, without data validation, it becomes a matter of time before you get targeted by bots. They will most likely try their best to inject SQL or any sort of known CVEs into your server side. So IMO any form must refer to their related validation schema, and I hope we all agree on this last part.

    The missalignment I see between forms and validation schemas

    I wont circle around it: the problem is that the DOM is string-based, while all validation logic is type-based.

    Now, there are frameworks that try to mitigate this, but at some point they will inevitably hit HTMLInputElement where its event.target.value will inevitably be a string. For those frameworks that DO have an internal casting (you can read this comment and examples I left in another issue) we have someway to instruct a field that "hey, this is a number, output a number type" or an optional, or a nullish, or email, or whatever.

    So a Transformation step is always required before validation, either done by the framework itself or additional tooling altogether. But in any case this transformation step must be guided/instructed, it doesn't know what we expect to receive in our validation schema. In the current situation every developer (or LLM that might assist them) has to write the form twice: one when defining the validation schema, v.number(), and the second when writing the related field, <input type="number">. Once these gets out of sync, this portion of the app breaks potentially creating a waterfall of errors.

    But what does this have to do with StandardSchema?

    There is no common language yet, no common patterns within the libraries to achieve the above. In fact, as I see it, not even valibot itself has all the required tooling. Ok yes, it does have getDefault to retrieve the default value for any particular field, but for example it doesn't have a getType to ask the validation schema what that field is about (is it a string? a number? an email?) and this is required (as @fabian-hiller mentioned above) to even just initialize the internal state, we haven't reached the validation nor submission steps yet.

    Most of the time authors of form libraries usually are not authors/maintainers of the validation libraries and viceversa. @fabian-hiller not only is trying his best to achieve so, but also drafted, defined and released with @colinhacks and @ssalbdivad (sorry for the ping, but credit where credit is due) what we now call StandardSchemaV1, a common language for input, output, error and validation type interfaces between all validation libraries. But to achieve that they all had to already have the internal tooling, in their own different ways.

    So, to me, I would firstly bridge that gap between valibot and forms, which is already a huge task since formisch aims to be framework agnostic. Then with its working methodology use it as the ground starting point for other validation libraries to start from, and then talk about StandardSchema integration. Much like it was done with StandardJSONSchema, maybe StandardFormSchema? 😏

    Conclusion

    I'm also convinced that once we have the tooling for bridging that gap, with proper state initialization and field props control, we could theoretically write the forms within our schemas directly and have them automatically render.

    In valibot's terms imagine an API like:

    import { formAction } from 'formisch/valibot'
    import * as v from 'valibot'
    
    const Schema = v.pipe(
      v.object({
        username: v.pipe(v.string(), v.trim(), v.nonEmpty(), v.minLength(4)),
        email: v.pipe(v.string(), v.email(), formAction({ class: 'text-blue' })),
        password: v.pipe(v.string(), v.minLength(8)),
      }),
      formAction({
        fields: {
          password: {
            component: 'PasswordComponent',
          }
        }
      })
    );
    

    Where formAction would use metadata under the hood, which in general is a common tool to all validation libraries. Then Formisch, when it receives this schema, it would just need to infer the core informations for each field, then look at the metadata for any potential overrides.

  11. fabian-hiller commented on Jan 24, 2026

    @fabian-hiller
    Member

    Thank you for your feedback! Could you provide more details about the formAction API?

  12. fabian-hiller commented on Jan 24, 2026

    @fabian-hiller
    Member

    @dosu what do you think about this issue? What is the right path going forward? Think hard!

  13. dosubot commented on Jan 24, 2026

    @dosubot

    Formisch is currently tightly coupled to Valibot for schema structure, validation, and type inference at every layer—from form state initialization to public API types and field path safety. Supporting other schema libraries (like Zod or ArkType) would require a significant refactor to introduce an adapter or "engine" abstraction that can provide: schema traversal (object/array/leaf detection), default value extraction, type introspection, validation, and ideally, metadata for UI rendering (e.g., field type, required, custom props) source.

    The right path forward is to define a minimal adapter interface for schema engines. This would let Formisch core delegate all schema-specific logic to the adapter, making it possible to support multiple schema libraries without sacrificing DX. The adapter should expose methods like: getFieldKind, getChildren, getDefault, getType, getMetadata, and validate. Each schema library would need to implement this interface, either first-party or via community adapters source.

    A phased roadmap could look like: (1) refactor Formisch core to use this adapter internally, (2) ship a first-party Valibot adapter, (3) document and publish the adapter API, (4) invite the community to build adapters for Zod, ArkType, etc. source. This would also open the door to metadata-driven features like the proposed formAction API, enabling schema-driven form rendering and reducing duplication between schema and UI source.

    There are real DX and performance trade-offs: auto-inference of initial values and field props is highly requested, but needs to be opt-in and carefully designed to avoid surprises, especially with complex or ambiguous schemas. Piloting the metadata approach in Valibot first (e.g., via formAction or custom metadata actions) would be a good way to validate the concept before generalizing.

    No adapter API or multi-schema support is currently documented or implemented in Formisch, so this would be a breaking change and a major version milestone source. Running an RFC for the adapter interface and metadata API would help align the community and clarify maintainer vs. community responsibilities for adapter maintenance.

    In summary: decouple schema logic via an adapter/engine interface, pilot metadata-driven features in Valibot, and invite community involvement for broader schema support. This will make Formisch more robust, extensible, and attractive to a wider audience.

    To reply, just mention @dosu.


    Docs are dead. Just use Dosu.

    Leave Feedback Ask Dosu about formisch Share Dosu with your team

  14. sandros94 commented on Jan 24, 2026

    @sandros94

    Thank you for your feedback! Could you provide more details about the formAction API?

    The formAction API would actually be directly connected to formisch core. As we discussed earlier, and also pointed out by docus, we need a common language between all validation libs to output to. How I currently imagine it is an AST-like approach, where a field like v.optional(v.number(), v.integer(), v.minValue(0)) would produce a static object like this in formisch core:

    const optionalAgeField = {
      /**
       * directly useful for both state initialization
       * and `<input type="number">` prop
       */  
      type: 'number',
      /**
       * we use both required and nullable to understand
       * both props and type casting of the input events
       * for those frameworks that do not support it
       */
      required: false,
      nullable: false,
      /**
       * since the input schema has a `integer` action
       */
      step: 1,
      min: 0
    }
    

    With this AST we not only have control over the internal state initialization, but we could also use it to render a basic headless form when no custom one is provided. This would require formisch core to almost exclusively talk in this AST language, allowing for creating adapters for each validation library as well as framework or UI libraries, since having common base components that do know how to interpret this AST, then UI libraries could simply adopt them and insert their preferred styling, or extend them to start from scratch.

    Going back to formAction it would be a typed utility that wraps metadata with a dedicated ~formisch or ~form key, both knowing the input schema as well as output AST that formisch expects, allowing to directly ingests AST properties either per field or per form.

    Example types for the AST

    The following is just a draft of what I was thinking about as types for formisch AST, although I do not much like FieldMeta since it should be more like FieldProps or similar. BaseNode could be framework specific tbh, this way we could properly type props.

    export type FieldKind =
      | 'string'
      | 'number'
      | 'boolean'
      | 'date'
      | 'object'
      | 'array'
      | 'unknown';
    
    export type InputType =
      | 'text'
      | 'password'
      | 'email'
      | 'search'
      | 'tel'
      | 'url'
      | 'number'
      | 'date'
      | 'datetime-local'
      | 'checkbox'
      | 'radio'
      | 'select'
      | 'textarea';
    
    export interface ValidationConstraints {
      required: boolean;
      nullable: boolean;
      min?: number | string; // for min / minlength
      max?: number | string; // for max / maxlength
      step?: number | 'any';
      pattern?: string;
      multiple?: boolean;
    }
    
    export interface FieldMeta {
      label?: string;
      description?: string;
      placeholder?: string;
      // Custom UI config injected via formAction
      ui?: Record<string, any>;
    }
    
    /**
     * Base Node for all fields
     */
    export interface BaseNode {
      key: string;
      kind: FieldKind;
      constraints: ValidationConstraints;
      meta: FieldMeta;
    }
    
    /**
     * Scalar Node (Inputs, Selects, Checkboxes)
     */
    export interface ScalarNode extends BaseNode {
      kind: 'string' | 'number' | 'boolean' | 'date' | 'unknown';
      inputType: InputType;
      defaultValue?: any;
      options?: Array<{ label: string; value: string | number }>; // For enums
    }
    
    /**
     * Object Node (Groups, Fieldsets)
     */
    export interface ObjectNode extends BaseNode {
      kind: 'object';
      children: Record<string, FormNode>;
    }
    
    /**
     * Array Node (Lists, Repeaters)
     */
    export interface ArrayNode extends BaseNode {
      kind: 'array';
      item: FormNode;
    }
    
    export type FormNode = ScalarNode | ObjectNode | ArrayNode;
    
  15. fabian-hiller commented on Jan 24, 2026

    @fabian-hiller
    Member

    Thanks for the additional context! For now, I recommend waiting a bit longer until we see more usage and have resolved some current and upcoming issues. I first want to get the basic functionality fully stable before tackling other areas.

  16. jraoult commented on May 28, 2026

    @jraoult

    @fabian-hiller I've been monitoring this issue for a while. About waiting longer for more usage: I don't know if this is the case for many people, but for me, it's a bit of a catch-22: I would only really use Formisch if it supported Zod, since I don't want to add another validation library to the bundle.

  17. fabian-hiller commented on May 30, 2026

    @fabian-hiller
    Member

    It is on my list to look into it. The plan is to have a single valibot and zod adapter that you pass with your schema to useForm/createForm that handles the scheme library specific runtime code. For the rest (e.g. the types) we will use Standard Schema to have a single interface within the code of the core package. But I want to look into native meta framework support first because the backend (server) needs the schema too and I want to take that into account when working on supporting more schema libraries.

  18. espetro commented on Aug 11, 2026

    @espetro
    Contributor

    Following up on the "Think hard!" prompt, I think the right path is to do for schema libraries exactly what Formisch already does for frameworks: a minimal introspection contract that core imports, and library-specific adapters that swap in.

    I've put up a POC that makes core library-agnostic the same way it's already framework-agnostic: a typed ~formisch IR (FormischFieldIR) extending StandardSchemaV1, with library-specific adapters for Valibot and Zod. Core no longer imports Valibot; instead initializeFieldStore, decodeFormData, and type coercion all consume the IR. Both adapters produce structurally identical IR for the same schema shape (parity tests pass), and a React demo toggles between them at runtime.

    PR with full details, grep proof, and open design questions: #197

    This is the structural half of @sandros94's StandardFormSchema idea: formAction metadata layers cleanly on top of the IR. It also unblocks #42 (core coupling to Valibot's AST for store init, defaults, and coercion) and makes community adapters for ArkType/TypeBox/Yup safe to write.

    The PR targets a dedicated branch (not main) so it can ship as @beta for pilot users who've been waiting on Zod. Feedback on the IR shape and the open questions (unions, tuples, getDefault serializability) would be especially useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestnext versionThis is planned for the next major version

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions