Back to Blog
EnglishApril 1, 2026

React or Next.js Contact Form Without API Route (2026 Guide)

reactnextjstutorialcontact form

Quick summary

Build a React or Next.js contact form without API routes, databases, or server code. Includes copy-paste examples and best practices.

You have built a React or Next.js app and now you need a contact form. The traditional approach involves creating an API route, configuring an email service like SendGrid or Nodemailer, handling validation on the server, and managing error states. That is a lot of work for a simple "send me a message" form.

With Flowqen, you skip all of that. You point your form at a Flowqen endpoint, and submissions are stored in your dashboard, emailed to you, and optionally synced to Google Sheets. This tutorial walks you through the complete setup.

Quick take: Keep your app frontend exactly as it is, replace backend complexity with one endpoint, and ship a production-ready contact flow in minutes.

Prerequisites

  • A React or Next.js project (works with both Pages Router and App Router)
  • A free Flowqen account — sign up at flowqen.com/signup

Step 1 — Get Your Flowqen Endpoint

Log into your Flowqen dashboard and click "+ New Form". Copy the endpoint URL:

https://flowqen.com/api/f/YOUR_FORM_ID

Step 2 — Build the Form Component

Here is a complete, production-ready contact form component with loading state, error handling, and success feedback:

import { useState } from "react";

export default function ContactForm() {
const [status, setStatus] = useState("idle"); // idle | loading | success | error

async function handleSubmit(e) {
  e.preventDefault();
  setStatus("loading");

  const formData = new FormData(e.target);

  try {
    const res = await fetch("https://flowqen.com/api/f/YOUR_FORM_ID", {
      method: "POST",
      body: formData,
    });

    if (res.ok) {
      setStatus("success");
      e.target.reset();
    } else {
      setStatus("error");
    }
  } catch (err) {
    setStatus("error");
  }
}

return (
  <form onSubmit={handleSubmit}>
    <input type="text" name="name" placeholder="Your name" required />
    <input type="email" name="email" placeholder="Your email" required />
    <textarea name="message" placeholder="Your message" rows={5} required />

    {/* Honeypot spam protection */}
    <input type="text" name="_gotcha" style={{ display: "none" }} />

    <button type="submit" disabled={status === "loading"}>
      {status === "loading" ? "Sending..." : "Send Message"}
    </button>

    {status === "success" && <p>Message sent successfully!</p>}
    {status === "error" && <p>Something went wrong. Please try again.</p>}
  </form>
);
}

Step 3 — Use It in Your Page

Import the component wherever you need it:

import ContactForm from "@/components/ContactForm";

export default function ContactPage() {
return (
  <main>
    <h1>Get in Touch</h1>
    <ContactForm />
  </main>
);
}

Next.js App Router: Using Server Actions?

If you are using Next.js App Router and prefer server actions, you can still use Flowqen. However, the simplest approach is to keep the form as a client component (add "use client" at the top) and use the fetch pattern shown above. There is no advantage to routing through a server action when Flowqen's endpoint already handles everything server-side.

TypeScript Version

If your project uses TypeScript, here is the typed version of the submit handler:

async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus("loading");

const formData = new FormData(e.currentTarget);

try {
  const res = await fetch("https://flowqen.com/api/f/YOUR_FORM_ID", {
    method: "POST",
    body: formData,
  });
  setStatus(res.ok ? "success" : "error");
  if (res.ok) e.currentTarget.reset();
} catch {
  setStatus("error");
}
}

Styling the Form

Flowqen does not impose any styling. The form is just a standard HTML form, so you can style it with Tailwind, CSS Modules, styled-components, or plain CSS. Here is a quick Tailwind example:

<input
type="text"
name="name"
className="w-full rounded border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Your name"
required
/>

What You Get Without Writing Backend Code

  • All submissions stored in your Flowqen dashboard
  • Email notifications on every submission
  • Spam filtering via honeypot (no CAPTCHA needed)
  • Google Sheets sync (free)
  • Webhook forwarding to Slack, Discord, or any URL

Wrap Up

A contact form in React or Next.js does not need an API route, a database, or an email service. With Flowqen, you write a single client component, point it at your endpoint, and you are done. Create your free account at flowqen.com/signup and have your form running in under two minutes.

Recommended Next Reads

Keyword Variants People Also Search

  • nextjs contact form without api route
  • react contact form backend service
  • submit form in nextjs without server action

FAQ

Can I use this with Next.js App Router?

Yes. Keep the form in a client component and post FormData directly to your Flowqen endpoint.

Do I still need an API route in Next.js?

No. Flowqen handles submission processing, storage, and notifications server-side.

Will this approach work in TypeScript projects?

Yes. The same pattern works with typed form handlers and typed status states.

Read next

Related guides to help you implement better forms and improve conversions.

Ready to add forms to your website?

Get started with Flowqen for free. No credit card required.

Create your free account