--- name: form-handling description: form standards for Vue/Nuxt — VeeValidate with schema validation (Yup in existing code, Zod for new), accessible error handling, atom/organism split, submitting via TanStack Query mutations, server error mapping. Load when building, migrating, reviewing or testing forms. --- # Form handling ## Validation library - **Existing projects:** VeeValidate + **Yup**. Leave working forms on Yup. - **New code:** VeeValidate + **Zod** (stronger TS inference; schemas can be shared with Zod validation in server routes, see `nuxt-project-patterns`). - **Never mix Yup and Zod in the same form.** Migrate opportunistically, a form at a time when already touching it; no big-bang rewrite. Adapter API depends on the installed `vee-validate` version. Historically schemas were wrapped with `toTypedSchema` from `@vee-validate/zod` or `@vee-validate/yup`; newer versions may accept Standard Schema libraries directly. **Check the installed version's docs** (`pnpm why vee-validate`) before writing or copying the wiring; do not assume one API. ```ts // Adapter-based wiring; verify against the installed version import { useForm } from 'vee-validate' import { toTypedSchema } from '@vee-validate/zod' import { z } from 'zod' const schema = z.object({ email: z.string().email(), name: z.string().min(1) }) const { handleSubmit, errors, setErrors } = useForm({ validationSchema: toTypedSchema(schema), }) ``` ## Accessibility Baseline rules: `frontend-a11y-check`. Form-specific decisions: - Every field has a **visible `