this is my implementation with RHF + Zod for both Client + Server side validation with server actions :
"use client";
....
const formSchema = z.object({
        .....
});
    const [loading, setLoading] = useState(false);
    const form = useForm<ProductFormValues>({
        resolver: zodResolver(formSchema),
        defaultValues,
    });
    const clientAction = async (formData: FormData) => {
        try {
            // trigger client-side validation
            form.trigger();
            if (!form.formState.isValid) {
                return;
            }
            setLoading(true);
                const {
                    errors, // from zod validation from the server
                    message = "",
                    data, // result of successful mutation 
                } = await updateProduct(product.id.toString(), formData);
              //Show toast  with a success message
                toast.custom(`... ${data.title} is Created 🚀`);
         
        } catch (error: any) {
            toast.error("Something went wrong.", JSON.strinfy(errors));
        } finally {
            setLoading(false);
        }
    };
    
    ...
    
     <Form {...form}>
                <form action={clientAction} className="w-full space-y-8">
                    <div className="gap-8 md:grid md:grid-cols-3">
                     ...
    - server action :
"use server"
const formSchema = z.object({
 ....
});
/**
 ** Creates a new product.
 *
 * @param {FormData} formData - The form data of the new product.
 * @returns {Promise<Product>} A promise that resolves to the created product.
 */
export async function createProduct(formData: FormData) {
    try {
        const validatedFields = formSchema.safeParse({
          ...
        });
        // Return early if the form data is invalid
        if (!validatedFields.success) {
            return {
                errors: validatedFields.error.flatten().fieldErrors,
            };
        }
        const res = await axios.post(
            `${API_URL}/products`,
            validatedFields.data,
        );
        revalidatePath("/admin/products");
        revalidatePath("/products");
        return { message: "Create Product successfully", data: res.data };
    } catch (error) {
        console.error(`Failed to create product:`, error?.response?.data);
        return {
            errors: {
                title: "There was an error with this title",
                description: "There was an error with this description",
                 ...
            },
            message: error?.response?.data,
        };
    }
}