formcn
v1.0.4
Published
Schema-driven React form generator using React Hook Form, Zod, and shadcn/ui
Downloads
305
Maintainers
Readme
formcn
Schema-driven React form generator built on top of React Hook Form, Zod, and shadcn/ui.
formcn generates fully typed, validated React form components from an interactive CLI workflow. It is designed to reduce boilerplate while staying aligned with shadcn/ui conventions.
Features
- Zero-configuration form generation
- Type-safe schemas using Zod
- shadcn/ui component integration
- Single-step and multi-step forms
- Schema-first validation
- Interactive CLI workflow
- Automatic dependency detection and installation
- Predefined templates for common use cases
Prerequisites
Before using formcn, ensure you have:
- Node.js 18+
- A React project with TypeScript
- shadcn/ui initialized in your project
Initialize shadcn/ui if needed:
npx shadcn@latest initInstallation
Install globally using npm:
npm install -g formcnOr using yarn:
yarn global add formcnOr run directly with npx:
npx formcnUsage
Run the CLI:
formcnThe interactive workflow will guide you through:
- Form name
- Form type (single-step or multi-step)
- Template selection
- Field definitions and validation rules
- Style preset selection
Example
$ formcn
formcn
✔ react-hook-form detected
✔ @hookform/resolvers detected
✔ zod detected
✔ shadcn/ui components detected
Form name: register
Form type: single step
Template: registration
Preset: default
✔ Form generated at src/components/forms/registerGenerated Output
Single-step form
src/components/forms/{formName}/
├── schema.ts
└── form.tsxMulti-step form
src/components/forms/user-registration/
├── personal-info-schema.ts
├── personalInfoStep.tsx
├── account-details-schema.ts
├── accountDetailsStep.tsx
├── contact-info-schema.ts
├── contactInfoStep.tsx
└── UserRegistrationForm.tsxSupported Field Types
- Text
- Password (with optional confirmation)
- Number
- URL
- Textarea
- Select
- Checkbox
- Radio
- Date
Templates
Single-step
- Registration
- Login
- Contact
Multi-step
- Registration (personal info, account details, contact info)
Style Presets
Single-step
default— minimal layout with subtle borders and spacing
Multi-step
minimalsidebarSteppersoftTypestepperTop
Example Output
Schema (schema.ts)
import { z } from "zod";
export const schema = z
.object({
first_name: z.string().min(1, "First Name is required"),
last_name: z.string().min(1, "Last Name is required"),
email: z.string().email("Invalid email"),
password: z.string().min(8, "Password must be at least 8 characters"),
passwordConfirmation: z.string(),
age: z.coerce.number().min(18, "Age must be at least 18"),
website: z.string().url("Invalid URL").optional().or(z.literal("")),
bio: z.string().optional(),
country: z.union([z.literal("us"), z.literal("ca"), z.literal("uk")], {
error: "Please select a country",
}),
newsletter: z.boolean().optional(),
})
.refine((data) => data.password === data.passwordConfirmation, {
message: "Passwords do not match",
path: ["passwordConfirmation"],
});
export type SchemaFormValues = z.infer<typeof schema>;Form (form.tsx)
"use client";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button } from "@/components/ui/button";
import { FieldGroup } from "@/components/ui/field";
import { schema, type SchemaFormValues } from "./schema";
export default function RegisterForm() {
const form = useForm<SchemaFormValues>({
resolver: zodResolver(schema),
});
function onSubmit(values: SchemaFormValues) {
console.log(values);
}
return (
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-6 max-w-3xl mx-auto border rounded-lg p-6"
>
<FieldGroup />
<div className="flex justify-end">
<Button type="submit" disabled={!form.formState.isValid}>
Submit
</Button>
</div>
</form>
);
}Troubleshooting
Command not found
Ensure your global npm bin directory is in your PATH:
npm config get prefixshadcn/ui not detected
npx shadcn@latest initMissing dependencies
npm install react-hook-form @hookform/resolvers zodContributing
Contributions are welcome.
- Fork the repository
- Create a feature branch
- Commit your changes
- Push the branch
- Open a pull request
License
MIT License
Author
Fares Galal
Acknowledgments
- React Hook Form
- Zod
- shadcn/ui
- Tailwind CSS
- TypeScript
