Form Integration

Next.js contact form, no API route

Yes, you can skip app/api and Server Actions. Post your Next.js form straight to your Formbold endpoint and each submission is stored and emailed to you. The Free plan covers 250 submissions a month across 10 forms.

Contact Form for Next.js

What code do I paste into my Next.js app?

This client component. Save it as components/ContactForm.tsx, replace FORM_ID with the ID from your form's Form Setup tab, and render <ContactForm /> on any page. It works with the App Router, the Pages Router and static exports, because the browser talks to Formbold directly.

nextjs.tsx
// components/ContactForm.tsx
"use client";

import { useState } from "react";

export default function ContactForm() {
  const [loading, setLoading] = useState(false);
  const [responseMessage, setResponseMessage] = useState("");

  async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setLoading(true);

    const formData = new FormData(event.currentTarget);
    const json = JSON.stringify(Object.fromEntries(formData));

    try {
      const response = await fetch("https://formbold.com/s/FORM_ID", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
        body: json,
      });
      const result = await response.json();

      if (response.ok) {
        setResponseMessage(result.message || "Message sent successfully!");
        (event.target as HTMLFormElement).reset();
      } else {
        setResponseMessage(result.message || "Something went wrong");
      }
    } catch (err) {
      setResponseMessage("Failed to submit form.");
    } finally {
      setLoading(false);
      setTimeout(() => setResponseMessage(""), 4000);
    }
  }

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-4 max-w-[452px] mx-auto">
      {/* Email Address */}
      <div className="flex flex-col gap-2">
        <label htmlFor="email" className="text-sm font-medium text-gray-700">
          Email Address<span className="ml-0.5 text-red-500">*</span>
        </label>
        <input
          type="email"
          name="email"
          id="email"
          placeholder="Enter your email"
          required
          className="max-h-11 w-full rounded-xl border border-gray-300 bg-white px-4 py-2.5 text-base text-gray-900 transition-all placeholder:text-[#9ca3af] focus:border-[#5750f1] focus:ring-4 focus:ring-[#5750f1]/10 focus:outline-none"
        />
      </div>

      {/* Subject */}
      <div className="flex flex-col gap-2">
        <label htmlFor="subject" className="text-sm font-medium text-gray-700">
          Subject<span className="ml-0.5 text-red-500">*</span>
        </label>
        <input
          type="text"
          name="subject"
          id="subject"
          placeholder="Enter your subject"
          required
          className="max-h-11 w-full rounded-xl border border-gray-300 bg-white px-4 py-2.5 text-base text-gray-900 transition-all placeholder:text-[#9ca3af] focus:border-[#5750f1] focus:ring-4 focus:ring-[#5750f1]/10 focus:outline-none"
        />
      </div>

      {/* Message */}
      <div className="flex flex-col gap-2">
        <label htmlFor="message" className="text-sm font-medium text-gray-700">
          Message<span className="ml-0.5 text-red-500">*</span>
        </label>
        <textarea
          name="message"
          id="message"
          rows={5}
          placeholder="Type your message..."
          required
          className="w-full resize-y rounded-xl border border-gray-300 bg-white px-4 py-3 text-base text-gray-900 transition-all placeholder:text-[#9ca3af] focus:border-[#5750f1] focus:ring-4 focus:ring-[#5750f1]/10 focus:outline-none"
        />
      </div>

      {/* Submit Button */}
      <button
        type="submit"
        disabled={loading}
        className="flex h-12 w-full cursor-pointer items-center justify-center gap-2 rounded-xl bg-[#111827] px-5 py-3 text-base font-medium text-white shadow-xs transition-all hover:bg-black active:scale-[0.99] disabled:opacity-50"
      >
        {loading ? "Submitting..." : "Submit Message"}
      </button>

      {/* Feedback Alert */}
      {responseMessage && (
        <p className="rounded-xl p-3 text-center text-sm font-medium bg-gray-50 text-gray-800">
          {responseMessage}
        </p>
      )}
    </form>
  );
}
How it works

How do I add a contact form to Next.js?

If next dev is already running, this takes a few minutes.

1

Create a form

Sign up, open All Forms and click Create New Form. Free accounts can have 10 forms.

2

Copy the endpoint

Open the Form Setup tab and copy the URL that looks like https://formbold.com/s/FORM_ID. Paste it into the fetch call in the component.

3

Send a test

Run next dev, submit the form once and open Submissions. If nothing shows up, check the POST request in your browser's Network tab.

Features

What you no longer have to build

Everything after the submit button: storage, email, spam checks and the apps your team already uses. Your Next.js code stays a plain client component.

No route handler to maintain

Nothing in app/api, no Server Action and no SMTP secrets in your environment. The component posts to one URL.

Spam checks you switch on

Turn on Basic Spam Filter in Settings > Spam & Security. For a fetch form like this one, add Custom reCAPTCHA with your own v2 keys.

File uploads from Starter

Starter takes 5 files of up to 10 MB per submission. Premium and Business take 10 files, up to 25 MB and 50 MB each.

11 apps and webhooks

On Starter and higher, send each entry to Slack, Notion, Google Sheets, HubSpot, Zapier, Make, a webhook and more.

FAQs

What else do Next.js developers ask?

Server Actions, static exports and where the endpoint should live.

No. The browser sends the form to Formbold, so app/api/contact/route.ts never has to exist. If you'd rather keep the URL out of client code, call the same endpoint from a Server Action with fetch. The request is the same.

Still have a question?

The docs cover setup, framework guides, integrations and spam protection, step by step.