new-form
Scaffold a React Hook Form with Zod validation, useMutation, and toast notifications
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Scaffold a React Hook Form with Zod validation, useMutation, and toast notifications
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Generate a semver-compliant release note from git history; on user confirmation, bump version, update CHANGELOG, create git tag, and publish a GitHub Release with gh
Scaffold a new backend server action with auth check, Zod input validation, repository call, and error handling
Scaffold a typed React client component with props interface, Tailwind styling, and shadcn/ui primitives
Create a Zod input schema file in src/backend/services/inputs/ for a domain entity
Scaffold a Next.js App Router page with optional server-side session check, metadata, and layout
Scaffold TanStack Query useQuery and/or useMutation hooks for a feature, calling a backend server action
| name | new-form |
| description | Scaffold a React Hook Form with Zod validation, useMutation, and toast notifications |
Create a form component using React Hook Form + Zod + TanStack Query mutation in techdiary.dev.
"use client" at the topzodResolver from @hookform/resolvers/zodsrc/backend/services/inputs/<domain>.input.ts — do not duplicate schema definitionsfilterUndefined() for default values to avoid uncontrolled→controlled warningsSubmitHandler<z.infer<typeof Schema>>useMutation, never call it directly in onSubmitForm, FormField, FormItem, FormLabel, FormControl, FormMessage"use client";
import { useForm, SubmitHandler } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation } from "@tanstack/react-query";
import { toast } from "sonner";
import { z } from "zod";
import {
Form, FormControl, FormField, FormItem, FormLabel, FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import * as <domain>Actions from "@/backend/services/<domain>.action";
import { <Domain>Input } from "@/backend/services/inputs/<domain>.input";
import { filterUndefined } from "@/lib/utils";
type FormValues = z.infer<typeof <Domain>Input.<schemaName>>;
interface Props {
// initial data if editing
}
export const <Name>Form: React.FC<Props> = ({ /* props */ }) => {
const form = useForm<FormValues>({
defaultValues: filterUndefined({
field: "",
}),
resolver: zodResolver(<Domain>Input.<schemaName>),
});
const mutation = useMutation({
mutationFn: (payload: FormValues) => <domain>Actions.<actionName>(payload),
onSuccess: () => {
toast("Saved successfully");
form.reset();
},
onError: (error) => {
toast.error(error.message ?? "Something went wrong");
},
});
const onSubmit: SubmitHandler<FormValues> = (payload) => {
mutation.mutate(payload);
};
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="field"
render={({ field }) => (
<FormItem>
<FormLabel>Label</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" disabled={mutation.isPending}>
{mutation.isPending ? "Saving..." : "Save"}
</Button>
</form>
</Form>
);
};