con un clic
create-form
Generate a validated form with Zod schema, react-hook-form, and i18n
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Generate a validated form with Zod schema, react-hook-form, and i18n
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Transform the base template into a specific application
Add or update i18n keys in both English and Arabic locale files
Scaffold a UI component with unistyles variants pattern
Scaffold a complete feature module with types, service, hooks, schema, and constants
Add a new screen or tab to the app with routing and i18n
Review changed code against project conventions and rules
| name | create-form |
| description | Generate a validated form with Zod schema, react-hook-form, and i18n |
| auto-invocable | true |
| triggers | ["create a form","add a form","build an input form","form with validation","new form"] |
Generate a complete form with Zod v4 schema, react-hook-form integration, and i18n support.
Ask the user for:
src/features/<feature>/ (which feature module)// src/features/<feature>/schemas/<name>Schema.ts
import { z } from 'zod/v4';
export const <name>Schema = z.object({
// String fields
name: z.string().min(1, 'validation.required').max(100, 'validation.nameTooLong'),
// Email fields
email: z.email('validation.emailInvalid'),
// Number fields
price: z.number({ message: 'validation.required' }).min(0, 'validation.priceMin'),
// Enum fields
role: z.enum(['admin', 'user', 'viewer']),
// Optional fields
bio: z.string().max(500, 'validation.bioMax').optional(),
// Array fields
tags: z.array(z.string()).min(1, 'validation.tagsRequired').optional(),
// Boolean fields
acceptTerms: z.literal(true, { message: 'validation.mustAcceptTerms' }),
});
export type <Name>FormData = z.infer<typeof <name>Schema>;
Schema rules:
z from zod/v4, NOT zod'validation.required', 'validation.emailInvalid'z.email() for email validation (Zod v4 syntax)z.number({ message: ... }) for required number with custom message// src/features/<feature>/components/<Name>Form.tsx
import { View } from 'react-native';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useTranslation } from 'react-i18next';
import { StyleSheet } from 'react-native-unistyles';
import { Button } from '@/common/components/Button';
import { FormField } from '@/common/components/FormField';
import { Input } from '@/common/components/Input';
import { Select } from '@/common/components/Select';
import { Checkbox } from '@/common/components/Checkbox';
import { TextArea } from '@/common/components/TextArea';
import { <name>Schema, type <Name>FormData } from '../schemas/<name>Schema';
interface <Name>FormProps {
onSuccess?: () => void;
defaultValues?: Partial<<Name>FormData>;
}
export function <Name>Form({ onSuccess, defaultValues }: <Name>FormProps) {
const { t } = useTranslation();
const {
control,
handleSubmit,
formState: { isSubmitting },
} = useForm<<Name>FormData>({
resolver: zodResolver(<name>Schema),
defaultValues: {
// Provide sensible defaults for every field
...defaultValues,
},
});
const onSubmit = async (data: <Name>FormData) => {
// If wired to a mutation hook:
// await mutation.mutateAsync(data);
onSuccess?.();
};
return (
<View style={styles.form}>
{/* String field */}
<FormField name="name" control={control} label={t('fields.name')} required>
<Input autoCapitalize="words" />
</FormField>
{/* Email field */}
<FormField name="email" control={control} label={t('fields.email')} required>
<Input keyboardType="email-address" autoCapitalize="none" autoComplete="email" />
</FormField>
{/* Number field */}
<FormField name="price" control={control} label={t('fields.price')} required>
<Input keyboardType="numeric" />
</FormField>
{/* Select/enum field */}
<FormField name="role" control={control} label={t('fields.role')} required>
<Select
options={[
{ label: t('roles.admin'), value: 'admin' },
{ label: t('roles.user'), value: 'user' },
{ label: t('roles.viewer'), value: 'viewer' },
]}
/>
</FormField>
{/* TextArea field */}
<FormField name="bio" control={control} label={t('fields.bio')}>
<TextArea maxLength={500} />
</FormField>
{/* Checkbox field */}
<FormField name="acceptTerms" control={control}>
<Checkbox label={t('fields.acceptTerms')} />
</FormField>
<Button
title={t('common.submit')}
onPress={handleSubmit(onSubmit)}
loading={isSubmitting}
fullWidth
/>
</View>
);
}
const styles = StyleSheet.create((theme) => ({
form: {
gap: theme.metrics.spacingV.p16,
},
}));
Form component rules:
FormField + child input pattern (FormField handles error display)keyboardType for each field typeautoCapitalize, autoComplete for better UXt() functionisSubmitting or mutation.isPending for loading stateimport { useCreate<Entity> } from '../hooks/use<Name>';
export function <Name>Form({ onSuccess }: <Name>FormProps) {
const createEntity = useCreate<Entity>();
const onSubmit = async (data: <Name>FormData) => {
await createEntity.mutateAsync(data);
onSuccess?.();
};
return (
// ...
<Button
loading={isSubmitting || createEntity.isPending}
// ...
/>
);
}
Update BOTH src/i18n/locales/en.json and src/i18n/locales/ar.json:
{
"fields": {
"<fieldName>": "<Field Label>"
},
"validation": {
// ... any new validation message keys
}
}
Add field labels under a "fields" namespace (or feature-specific namespace).
Add any new validation keys under "validation".
Run npm run validate to ensure no TypeScript or lint errors.
| Field Type | Input Component | KeyboardType | Zod Validator |
|---|---|---|---|
| Text | <Input /> | "default" | z.string() |
<Input /> | "email-address" | z.email() | |
| Password | <Input /> | "default" + secureTextEntry | z.string().min(8) |
| Number | <Input /> | "numeric" | z.number() |
| Phone | <Input /> | "phone-pad" | z.string() |
| URL | <Input /> | "url" | z.url() |
| Multiline | <TextArea /> | "default" | z.string().max(n) |
| Select | <Select /> | N/A | z.enum([...]) |
| Checkbox | <Checkbox /> | N/A | z.boolean() or z.literal(true) |
| Toggle | <Switch /> | N/A | z.boolean() |
z from zod/v4, NOT zodStyleSheet from react-native-unistyles, NOT react-native@/ path aliasesany typesuseTranslation()