EU-hosted Formspree alternative

The form backend
for static sites.

One API key per form. Paste it as your action, get submissions in a clean dashboard, and get a system push notification for every new entry — even when the browser is closed.

Free tier: 5 forms · 200 submissions/month · No credit card.

contact.html
<form action="https://formhook.app/f/fh_…" method="POST">
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>

  <button type="submit">Send</button>
</form>

That's the integration. There is no step two.

Built for the way you actually ship.

Three things matter for a form backend behind a static site: notifications you actually notice, hosting you control, and an integration that takes thirty seconds.

Native push notifications

Get a system-level notification every time a form is submitted, even when your browser is closed. Works on macOS, Windows, Linux, Android, and iOS PWA.

EU data residency

One Hetzner VPS in Germany. Submissions live in our Postgres and stop there — nothing is forwarded to AWS, GCP, or any third-party data lake. Single tenant, no serverless chain.

Drop-in integration

Paste the API key as your form's action attribute. Works with raw HTML, fetch, React, anything that can POST. JSON, form-encoded, and multipart all supported.

Quickstart

Five lines of HTML, or one fetch call.

Sign up, create a form, copy the API key. From there it's identical to a normal HTML form post — Formhook handles parsing, normalization, abuse protection, and delivery to your dashboard.

  • Hidden honeypot field stops the lazy bots; Cloudflare Turnstile handles the rest.
  • Optional _redirect field for native form posts — strictly validated against your origin allowlist, no open redirects.
  • Per-form CORS allowlist. Browser submissions from unknown origins are rejected at the edge.
See the full integration guide
submit.tsTypeScript
// Or with fetch:
await fetch("https://formhook.app/f/fh_…", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    email: "[email protected]",
    message: "Hello",
  }),
});

Production defaults, no hand-rolling.

Everything below ships in the MVP. No buy-this-add-on, no premium tier required.

Spam & abuse

  • Hidden honeypot field
  • Per-IP sliding-window rate limit (10/min)
  • Per-form burst limit (60/min)
  • Cloudflare Turnstile (opt-in per form)
  • CORS allowlist enforcement

Reliability

  • Atomic Redis Lua rate limiter
  • Rolling 30-day quota with alerts at 80%
  • Body-size cap (64 KB)
  • JSON / form-encoded / multipart accepted
  • Native systemd service with restart-on-failure

Notifications

  • Web push (VAPID, no third-party service)
  • Server-sent events for live dashboard updates
  • Per-form push toggle to mute noisy forms
  • Multiple devices per user
  • PWA installable on iOS for home-screen push

Security

  • argon2id password hashing
  • Email verification gated at sign-in
  • 30-day JWT session with version-bump invalidation
  • Encrypted Postgres backups (age) with off-box upload
  • TLS via Let’s Encrypt & HSTS in Nginx

Free for the projects that fit.

One tier. No card. Paid tiers come with billing — not before.

Free tier

$0/ month

Enough for portfolios, landing pages, side projects, and the kind of contact form that gets one submission a week.

Create your account

Includes

  • 5 forms
  • 200 submissions / month (rolling)
  • Web push notifications
  • Honeypot, rate limiting, CORS
  • Cloudflare Turnstile (optional)

Ship the form, not the backend.

You shouldn't have to write a form receiver in 2026. Spend ten seconds connecting your HTML, then move on.