@letar/forms

Quick Start

Build your first form in under 5 minutes

1. Define Your Schema

Use Zod to define validation rules and UI metadata:

import { z } from 'zod/v4'

const ContactSchema = z.object({
  name: z
    .string()
    .min(2)
    .max(100)
    .meta({
      ui: { title: 'Full Name', placeholder: 'John Doe' },
    }),
  email: z
    .string()
    .email()
    .meta({
      ui: { title: 'Email', placeholder: 'john@example.com' },
    }),
  message: z
    .string()
    .min(10)
    .max(1000)
    .meta({
      ui: { title: 'Message', placeholder: 'Tell us about your project...' },
    }),
})

2. Create the Form

import { Form } from '@letar/forms'

function ContactForm() {
  return (
    <Form
      schema={ContactSchema}
      initialValue={{ name: '', email: '', message: '' }}
      onSubmit={async ({ value }) => {
        const response = await fetch('/api/contact', {
          method: 'POST',
          body: JSON.stringify(value),
        })
        if (response.ok) {
          alert('Message sent!')
        }
      }}
    >
      <Form.Field.String name="name" />
      <Form.Field.String name="email" />
      <Form.Field.Textarea name="message" />
      <Form.Button.Submit loadingText="Sending...">Send Message</Form.Button.Submit>
    </Form>
  )
}

3. That's It!

The form automatically:

  • Validates fields against the Zod schema
  • Displays validation errors
  • Extracts labels and placeholders from .meta({ ui: ... })
  • Applies maxLength, min, max constraints from Zod rules
  • Handles submit state (loading, disabled)

What's Next?

On this page