Docs/Forms

Forms

Choose where your site's contact forms send submissions: Formspree, Web3Forms, any form service with a custom endpoint, or WordPress.

Forms

Your site is static, so a contact form needs somewhere to send its submissions. Forms settings picks that place once, for every form on the site.

Opening Forms Settings

Open Site ▾ › Forms settings (in the Settings column), or press ⌘K (Ctrl+K) and type "Forms".

Choosing a Provider

Pick one option and fill in its field:

OptionWhat you enterWhere submissions go
NoneNothingForms stay disabled: the submit button is greyed out
FormspreeFormspree form ID (for example xyzabc12)Your form on formspree.io
Web3FormsWeb3Forms access keyweb3forms.com, which emails them to you
Custom endpointForm endpoint URLAny service that accepts a form POST, such as Formspark, Getform or Basin
WordPressRecipient email (optional); defaults to your WordPress admin emailSent with wp_mail by your WordPress site

Click Save.

Custom endpoint

Use this for any form service that isn't listed. Paste the full URL the service gives you for the form, form ID included, for example https://submit-form.com/your-form-id for Formspark. The URL must start with https:// (or http://); Forms settings won't save anything else.

The form is sent from the visitor's browser as a regular form POST (multipart/form-data) with an Accept: application/json header. Any status from 200 to 299 counts as sent, unless the service answers with JSON containing "success": false. On an error, the form shows the service's error or message text if it sends one.

WordPress

WordPress needs a connected WordPress site with the PhantomWP Connect plugin. Without a connection, the option is greyed out with Connect WordPress to enable this option.

Forms post to your own site at /api/contact, which passes the message to WordPress using your project's WP_API_URL and WP_ACCESS_SECRET. Saving with this option also writes that route (src/pages/api/contact.ts). The route runs on the server, so your hosting has to support server-side routes, as Vercel and Cloudflare Workers do. If WordPress delivery returns an error, update the PhantomWP Connect plugin.

What Gets Saved

Saving writes:

  • src/config/forms.json: the provider and its setting. If the file doesn't exist yet, Forms settings says so and creates it when you save.
  • src/lib/forms.ts: the helper your forms read. It's rewritten every time you save Forms settings, so don't put your own code in it.
  • src/pages/api/contact.ts: only with the WordPress option.

Like any other edit, the change goes live when you publish.

Which Forms Use It

These read Forms settings:

  • the Contact Page template in the Create Page dialog
  • the contact sections in the Component Library

Each one sends name, email, subject and message fields, plus a hidden _gotcha field that many services use to catch spam bots. With Web3Forms, the access key is sent as a hidden access_key field. After sending, the form shows "Thank you! Your message has been sent." or an error, without leaving the page.

Your own forms

To make a form you wrote yourself use the same setting, read it from @/lib/forms:

---
import { getFormDelivery } from '@/lib/forms';
const delivery = getFormDelivery();
---

<form action={delivery.action} method={delivery.method}>
    {delivery.accessKey && <input type="hidden" name="access_key" value={delivery.accessKey} />}
    <input type="email" name="email" required />
    <textarea name="message" required></textarea>
    <button type="submit" disabled={!delivery.enabled}>Send</button>
</form>

delivery.enabled is false until a provider is chosen and its field is filled in. A form written like this does a full-page POST to the provider. The Component Library's contact sections include a small script that sends the form in the background and shows the result on the page instead.

Next Steps