Introduction

Dynamic form system for React with TypeScript, Zod validation, and shadcn/ui integration.

Introduction

@saastro/forms is a dynamic form system for React applications. It combines the power of React Hook Form, Zod validation, and dependency injection to create type-safe, configurable forms with 30+ field types.

Why @saastro/forms?

Build complex forms with minimal code, maximum type safety, and full UI flexibility.

Traditional form libraries make you choose: either you get type safety and write a lot of boilerplate, or you get convenience and lose type safety. @saastro/forms gives you both:

  • Zero-config mode — Auto-discover shadcn components, no Provider needed
  • Type-safe configuration — Full TypeScript support with autocomplete
  • JSON-serializable — Store form configs in databases, send over APIs
  • Declarative validation — Zod schemas or simple rules objects
  • UI agnostic — Bring your own components via dependency injection
  • 30+ field types — Text, select, slider, date, checkbox groups, and more
  • Multi-step forms — Built-in wizard support with progress indicators
  • Conditional logic — Show/hide/disable fields based on values

Key Features

The simplest way to get started — just pass your components:

import { Form, FormBuilder } from '@saastro/forms';

// Auto-discover all shadcn components with Vite's glob
const uiComponents = import.meta.glob('@/components/ui/*.tsx', { eager: true });

const config = FormBuilder.create('contact')
  .addField('name', (f) => f.type('text').label('Name').required())
  .addField('email', (f) => f.type('email').label('Email').required().email())
  .addStep('main', ['name', 'email'])
  .build();

function ContactForm() {
  return (
    <Form config={config} components={uiComponents} onSubmit={(values) => console.log(values)} />
  );
}

2. FormBuilder API

Fluent, chainable API for building forms:

const config = FormBuilder.create('contact')
  .layout('manual') // Fixed 12-column grid
  .columns(12)
  .addField(
    'name',
    (f) =>
      f.type('text').label('Name').required('Name is required').columns({ default: 12, md: 6 }), // Full width mobile, half on md+
  )
  .addField('email', (f) =>
    f
      .type('email')
      .label('Email')
      .required()
      .email('Please enter a valid email')
      .columns({ default: 12, md: 6 }),
  )
  .addStep('main', ['name', 'email'])
  .build();

3. JSON Configuration

Same forms, defined as JSON (perfect for CMSes and visual builders):

{
  "id": "contact",
  "columns": 12,
  "fields": {
    "name": {
      "type": "text",
      "label": "Name",
      "schema": { "required": true, "requiredMessage": "Name is required" },
      "columns": { "default": 12, "md": 6 }
    },
    "email": {
      "type": "email",
      "label": "Email",
      "schema": { "required": true, "format": "email" },
      "columns": { "default": 12, "md": 6 }
    }
  },
  "steps": [{ "name": "main", "fields": ["name", "email"] }]
}

4. Dependency Injection

Use any UI library. Pass components directly or use a Provider:

// Zero-config (recommended)
<Form config={config} components={uiComponents} />

// Or explicit components
<Form
  config={config}
  components={{
    Input: MyCustomInput,
    Button: MyCustomButton,
  }}
/>

// Or legacy Provider pattern
<ComponentProvider components={registry}>
  <Form config={config} />
</ComponentProvider>

Field Types

@saastro/forms includes 30+ field types out of the box:

CategoryFields
Texttext, email, tel, textarea, input-group
Selectionselect, native-select, combobox, command, radio, button-radio
Togglecheckbox, switch, checkbox-group, switch-group, button-checkbox
Specialslider, date, daterange, otp, button-card, html

When to Use @saastro/forms

Perfect for:

  • Dynamic forms that change based on configuration
  • Visual form builders and CMSes
  • Multi-step wizards and onboarding flows
  • Applications that need consistent form UX
  • Teams that want type-safe form development

Consider alternatives if:

  • You need a single, static form (just use React Hook Form directly)
  • You’re not using React
  • You need server-side form handling (consider Remix forms)

Architecture

@saastro/forms
├── FormBuilder         # Fluent API for building configs
├── Form                # Main render component (zero-config ready)
├── ComponentProvider   # DI container for UI components (optional)
├── PluginManager      # Extensibility (analytics, autosave, etc.)
├── Validation         # Zod schema compiler from JSON rules
└── Renderers          # Field type implementations

Ready to Start?

Head to the Installation guide to set up @saastro/forms in your project.

Or browse the Field Types to see all available fields with interactive examples.