Astro is a joy to build with, right up until you need a form. There's no server on the other end — so the default move is a hosted endpoint (Formspree, Netlify Forms, Web3Forms) that emails you the raw submission. Fine for one contact form. It falls over fast once you need several forms with real logic behind them.

Concrete case: a summer camp site. Registration, a medical form, a photo release, a liability waiver, maybe a deposit. Some fields only apply if an earlier answer was "yes." Files get uploaded. Branded confirmation emails go out. A mailto-style endpoint can't do any of that — and standing up five separate hosted forms, each with its own dashboard and submission cap, is its own headache.

The shape I landed on: keep Astro fully static, and point every form at one WordPress backend running CraftForms. WordPress does the things it's actually good at — storing, validating, routing, emailing. Astro keeps doing the thing it's good at — serving fast static pages.

How it wires together

Build the form once in WP with CraftForms. On the Astro side, a small component renders a placeholder <div>. At runtime, a tiny loader script (embed.js) fetches the live form definition from the backend and boots it in place. Submissions POST back to the backend, which validates, stores, and emails.