Form fields

All inputs are 38px tall. Wrap in <Field> for label + hint + error. Use useForm() for binding.

Inputs

We'll never share this.
Phone number is required
What clients see on your public profile.

File upload

Drag-drop or click. Image previews built in.

Click to upload or drag and drop
JPG, PNG up to 10MB

useForm — RHF + Zod

See src/components/ui/useForm.tsx. The Form + Field helpers wire validation to the kit Field automatically.

const { Form, Field, formState } = useForm({
  schema: z.object({
    email: z.string().email(),
    bio:   z.string().max(500),
  }),
  defaultValues: { email: '', bio: '' },
  onSubmit: values => api.saveProfile(values),
});

<Form>
  <Field name="email" label="Email" required>
    {(props) => <Input {...props} />}
  </Field>
  <Field name="bio" label="Bio">
    {(props) => <Textarea {...props} />}
  </Field>
  <Button type="submit" disabled={formState.isSubmitting}>Save</Button>
</Form>