Furrow Forms

Headless CMS · works with Furrow Forms

Contact forms for Sanity sites

Keep submissions out of your Content Lake — one endpoint, spam handled.

paste this into your agent

Fetch furrowforms.com/ai and set up a contact form backend for my Sanity site.

agent-readable recipe: /forms-for/sanity.md

prefer clicking? start in the dashboard

components/ContactForm.tsx
'use client';

export function ContactForm() {
  const loadedAt = Date.now();
  async function submit(formData: FormData) {
    await fetch('https://api.furrowforms.com/s/fp_k7m2', {
      method: 'POST',
      body: formData,
    });
  }

  return (
    <form action={submit}>
      <input type="text" name="_gotcha" style={{ display: 'none' }} tabIndex={-1} />
      <input type="hidden" name="_ft" value={loadedAt} />
      <input name="name" type="text" required />
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button>Send</button>
    </form>
  );
}

The gap

Why Sanity sites need a form backend

Sanity is deliberately a content platform, not an everything platform: structured documents, GROQ, real-time collaboration. Form submissions are explicitly not its job — and the workarounds people reach for (a write token mutating submissions into the dataset, or a hand-rolled serverless function) each create new problems. Furrow Forms is the boring, dedicated answer: your Next.js or Astro frontend POSTs to one endpoint; storage, spam, notifications, and signed webhooks are handled; your Content Lake stays content.

01

Write tokens don’t belong in browsers

Mutating submissions into your dataset from the client means shipping a token that can write to your production content — and inviting every bot on the internet to use it. Furrow’s public keys are safe in client HTML by design; protection comes from the spam stack, not secrecy.

02

Spam in the dataset is spam in the Studio

Submissions written into Sanity appear right where your editors work, count against your quotas, and need cleanup queries when the bots arrive. Rejected and honeypot-caught posts never even reach Furrow’s stored submissions — or your bill.

03

The serverless-function detour

The other standard answer — an API route that validates, filters, emails, and stores — is a small product you now maintain per site. Furrow is that product, already built, with retried webhooks when you want the data in your own pipeline.

Two ways in

Set it up yourself, or don’t

Hand it to your agent

[ recommended ]

Furrow’s whole control plane is an API and MCP server. Paste this prompt into Claude Code, Cursor, or any agent — it does the rest:

paste this into your agent

Fetch furrowforms.com/ai and set up a contact form backend for my Sanity site.
  1. 1.Registers the account over POST /api/register — you read one 6-digit email code
  2. 2.Provisions the site: client, project, and forms in one idempotent bootstrap_site call
  3. 3.Pastes the generated snippet into your codebase
  4. 4.Fires test_webhook and verifies the signed delivery

Or do it by hand

  1. 01Create a free account and a project for the site.
  2. 02Create the form and paste the generated snippet into your frontend — the Studio is untouched.
  3. 03Configure domains, notify emails, and an optional webhook once at the project level.
  4. 04Need submissions in your own systems? Wire the signed webhook to your endpoint — retried with backoff if you’re down.

free tier: 100 subs/mo · unlimited forms · full API + MCP · pricing →

FAQ

Sanity + Furrow Forms, answered

How do I handle form submissions with Sanity?

Don’t write them into your dataset. Point the form in your frontend at a dedicated form backend: POST to a Furrow Forms endpoint and let it store the submission, filter spam, notify your team, and deliver a signed webhook. Sanity stays the system of record for content, not inbound mail.

Can I store submissions in the Sanity Content Lake?

Technically yes, via a mutation with a write token — but that token cannot safely live in a browser, spam lands next to your editors’ documents, and submissions count toward dataset usage. A form backend avoids all three; if you still want submissions in Sanity, consume Furrow’s webhook server-side and write them in on your terms.

Does this work with Sanity + Astro or Sanity + Next.js?

Yes — the form is plain markup in whatever renders your frontend. Furrow generates snippets for HTML, Astro, and Next.js from the form’s field contract, honeypot and Turnstile included.

The form backend your agent can run.

paste this into your agent

Fetch furrowforms.com/ai and set up forms for this site.

Setup for agents →