Installation

How to install and configure @saastro/forms in your React project.

Installation

Learn how to install and configure @saastro/forms in your React project.

Prerequisites

Before you begin, make sure you have:

  • React 18 or later
  • TypeScript 5.0 or later (recommended)
  • A UI component library (we recommend shadcn/ui)

@saastro/forms ships with a CLI that scaffolds example forms and installs everything they need — shadcn components and peer dependencies. The fastest path is three commands:

# 1. Install the package
npm install @saastro/forms

# 2. Generate two example forms (zero-config) in src/components/
npx @saastro/forms init

# 3. Install any missing shadcn components AND peer dependencies
npx @saastro/forms install-deps

That’s it. Open src/components/ExampleForm.tsx to see a FormBuilder example, or src/components/ExampleFormJson.tsx for the equivalent JSON-config form.

See the CLI reference for every flag and option.

How init and install-deps work

  • init creates two example files in src/components/:
    • ExampleForm.tsx — programmatic form with FormBuilder
    • ExampleFormJson.tsx — JSON-config form with auto-discovered components
  • install-deps:
    1. Reads your project’s components.json (shadcn config) and runs shadcn@latest add ... for any required components that are missing.
    2. Detects your package manager from the lockfile and installs any missing peer dependencies (zod, react-hook-form, react-day-picker, date-fns).

If you don’t have a components.json yet, run npx shadcn@latest init first.

Use the form in your page

import { ExampleForm } from '@/components/ExampleForm';

export default function ContactPage() {
  return <ExampleForm />;
}

The form auto-discovers shadcn components via Vite’s import.meta.glob. No FormProvider and no barrel file required.


Manual Setup

If you prefer to wire things up by hand, follow these four steps instead of running the CLI.

1. Install the package

npm install @saastro/forms
# or
pnpm add @saastro/forms
# or
bun add @saastro/forms

2. Install peer dependencies

@saastro/forms requires React Hook Form, Zod, date-fns, and react-day-picker:

npm install react-hook-form zod date-fns react-day-picker

3. Install shadcn/ui components

Install only the components you need. For a basic text form:

npx shadcn@latest add input button label field form

For all available field types:

npx shadcn@latest add input button label textarea select checkbox radio-group popover calendar tooltip slider switch separator dialog command input-otp field form

4. Create your first form (Zero-Config)

Auto-discover all your shadcn components with Vite’s glob:

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

const uiComponents = import.meta.glob('@/components/ui/*.tsx', { eager: true });

const config = FormBuilder.create('contact')
  .addField('name', (f) => f.type('text').label('Name').required().minLength(2))
  .addField('email', (f) => f.type('email').label('Email').required().email())
  .addStep('main', ['name', 'email'])
  .buttons({ submit: { type: 'submit', label: 'Send' } })
  .build();

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

No FormProvider, no barrel file, no manual component registration. The Form auto-discovers components by parsing the glob result.


Alternative: Explicit Components

If you prefer explicit imports or need to override specific components:

import { Form, FormBuilder } from '@saastro/forms';
import { Input, Button, Label } from '@/components/ui';
import { Field, FieldLabel, FieldDescription, FieldError } from '@/components/ui/field';
import { FormField, FormControl } from '@/components/ui/form';

<Form
  config={config}
  components={{
    Input,
    Button,
    Label,
    Field,
    FieldLabel,
    FieldDescription,
    FieldError,
    FormField,
    FormControl,
  }}
/>;

Provider Mode (Legacy)

For apps with many forms sharing the same components, you can use the provider pattern:

import { Form, FormBuilder, ComponentProvider, createComponentRegistry } from '@saastro/forms';
import * as shadcn from '@/lib/form-components'; // Your barrel file

const registry = createComponentRegistry(shadcn);

export function App() {
  return (
    <ComponentProvider components={registry}>
      <ContactForm />
      <SignupForm />
      <CheckoutForm />
    </ComponentProvider>
  );
}

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

  return <Form config={config} />;
}

Benefits of Zero-Config

  1. One line of setup — just import.meta.glob and you’re done
  2. Auto-discovers components — no manual registration needed
  3. Missing component fallback — shows helpful warnings with the install command
  4. No Provider boilerplate — just render <Form />
  5. Override per-form — mix glob with explicit overrides

Required Components by Field Type

When a component is missing, you’ll see a helpful warning with the recommended fix: npx @saastro/forms install-deps.

Field TypeRequired Components
text, email, telInput, Label, Field, FieldLabel, FieldError, FormField, FormControl
textareaTextarea, Label, Field, FieldLabel, FieldError, FormField, FormControl
selectSelect, SelectTrigger, SelectContent, SelectItem, SelectValue, Field, …
checkbox, switchCheckbox/Switch, Label, Field, …
dateCalendar, Popover, PopoverTrigger, PopoverContent, Button, Field, …
comboboxCommand, CommandInput, CommandList, Popover, Button, Field, …

Check Required Components Programmatically

import { getRequiredComponents, getInstallCommand } from '@saastro/forms';

const required = getRequiredComponents(config);
// ['Input', 'Button', 'Label', 'Field', ...]

const installCmd = getInstallCommand(required);
// 'npx shadcn@latest add input button label field form'

Tailwind CSS 4

If you’re using Tailwind CSS 4, add the following @source directive to your main CSS file so Tailwind can detect the classes used by this package:

@source "node_modules/@saastro/forms/dist/**/*.js";

TypeScript Configuration

For the best experience, ensure your tsconfig.json includes:

{
  "compilerOptions": {
    "strict": true,
    "moduleResolution": "bundler",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Next Steps