Skip to main content

Clean Minimalist Contact Form

A clean, responsive minimalist contact form built with Tailwind CSS and pre-configured for Backforms. Includes an invisible honeypot spam trap, AJAX submission with loading state, and instant webhook notifications to your email, Telegram, Discord, and Google Sheets.

Zero backend server or API routes needed
Invisible honeypot (_gotcha) spam trap
Full React / Next.js client component with state handling
Lightweight Tailwind CSS styling with yellow accent
Instant submission alerts to Email, Slack & Webhooks
Live Form PreviewComponent Sandbox

Contact Us

Fill out the form below. Zero client-side dependencies or backend code required.

Pre-configured for Backforms endpoint
Honeypot anti-spam active
Zero backend needed
style="color:#9ece6a;">"use client";

import { useState } from style="color:#9ece6a;">"react";

export default function ContactForm() {
  const [status, setStatus] = useState<style="color:#9ece6a;">"idle" | style="color:#9ece6a;">"loading" | style="color:#9ece6a;">"success" | style="color:#9ece6a;">"error">(style="color:#9ece6a;">"idle");
  const [errorMessage, setErrorMessage] = useState(style="color:#9ece6a;">"");

  async function handleSubmit(e: React.FormEvent<style="color:#f7768e;font-weight:600;">HTMLFormElement>) {
    e.preventDefault();
    setStatus(style="color:#9ece6a;">"loading");
    setErrorMessage(style="color:#9ece6a;">"");

    const form = e.currentTarget;
    const formData = new FormData(form);

    try {
      style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">// Replace YOUR_FORM_ID with your Backforms endpoint ID from app.backforms.com
      const response = await fetch(style="color:#9ece6a;">"https:style="color:#565f89;font-style:italic;style="color:#9ece6a;">">//backforms.com/f/YOUR_FORM_ID", {
        method: style="color:#9ece6a;">"POST",
        headers: {
          Accept: style="color:#9ece6a;">"application/json",
        },
        body: formData,
      });

      if (response.ok) {
        setStatus(style="color:#9ece6a;">"success");
        form.reset();
      } else {
        const data = await response.json().catch(() => null);
        setErrorMessage(data?.error || style="color:#9ece6a;">"Submission failed. Please try again.");
        setStatus(style="color:#9ece6a;">"error");
      }
    } catch {
      setErrorMessage(style="color:#9ece6a;">"Network error. Please check your internet connection.");
      setStatus(style="color:#9ece6a;">"error");
    }
  }

  return (
    <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"container px-4 mx-auto">
      <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mx-auto">
        <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"max-w-md mx-auto px-8 py-6 bg-gray-100 rounded-lg shadow-lg">
          <style="color:#f7768e;font-weight:600;">h2 className=style="color:#9ece6a;">"text-2xl font-semibold text-gray-800 mb-4">Contact Us</style="color:#f7768e;font-weight:600;">h2>

          {status === style="color:#9ece6a;">"success" ? (
            <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"p-4 bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg text-center space-y-2">
              <style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"font-semibold">Message sent successfully!</style="color:#f7768e;font-weight:600;">p>
              <style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-emerald-600">
                Thank you for reaching out. We will get back to you shortly.
              </style="color:#f7768e;font-weight:600;">p>
              <style="color:#f7768e;font-weight:600;">button
                type=style="color:#9ece6a;">"button"
                onClick={() => setStatus(style="color:#9ece6a;">"idle")}
                className=style="color:#9ece6a;">"mt-2 px-4 py-1.5 bg-emerald-600 text-white rounded-lg text-xs font-medium hover:bg-emerald-700 transition"
              >
                Send Another Message
              </style="color:#f7768e;font-weight:600;">button>
            </style="color:#f7768e;font-weight:600;">div>
          ) : (
            <style="color:#f7768e;font-weight:600;">form onSubmit={handleSubmit}>
              {style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">/* Invisible Honeypot Spam Trap (Kept hidden from real humans) */}
              <style="color:#f7768e;font-weight:600;">input
                type=style="color:#9ece6a;">"text"
                name=style="color:#9ece6a;">"_gotcha"
                style={{ display: style="color:#9ece6a;">"none" }}
                tabIndex={-1}
                autoComplete=style="color:#9ece6a;">"off"
              />

              {status === style="color:#9ece6a;">"error" && (
                <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mb-4 p-3 bg-red-50 border border-red-200 text-red-700 text-xs rounded-lg">
                  {errorMessage}
                </style="color:#f7768e;font-weight:600;">div>
              )}

              <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mb-4">
                <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-gray-800 mb-1 text-sm font-medium" htmlFor=style="color:#9ece6a;">"name">
                  Your Name
                </style="color:#f7768e;font-weight:600;">label>
                <style="color:#f7768e;font-weight:600;">input
                  id=style="color:#9ece6a;">"name"
                  name=style="color:#9ece6a;">"name"
                  type=style="color:#9ece6a;">"text"
                  required
                  placeholder=style="color:#9ece6a;">"Enter your name"
                  className=style="color:#9ece6a;">"w-full px-4 py-2 bg-gray-200 text-gray-900 rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-300 transition duration-300"
                />
              </style="color:#f7768e;font-weight:600;">div>

              <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mb-4">
                <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-gray-800 mb-1 text-sm font-medium" htmlFor=style="color:#9ece6a;">"email">
                  Your Email
                </style="color:#f7768e;font-weight:600;">label>
                <style="color:#f7768e;font-weight:600;">input
                  id=style="color:#9ece6a;">"email"
                  name=style="color:#9ece6a;">"email"
                  type=style="color:#9ece6a;">"email"
                  required
                  placeholder=style="color:#9ece6a;">"Enter your email"
                  className=style="color:#9ece6a;">"w-full px-4 py-2 bg-gray-200 text-gray-900 rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-300 transition duration-300"
                />
              </style="color:#f7768e;font-weight:600;">div>

              <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mb-4">
                <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-gray-800 mb-1 text-sm font-medium" htmlFor=style="color:#9ece6a;">"message">
                  Your Message
                </style="color:#f7768e;font-weight:600;">label>
                <style="color:#f7768e;font-weight:600;">textarea
                  id=style="color:#9ece6a;">"message"
                  name=style="color:#9ece6a;">"message"
                  rows={4}
                  required
                  placeholder=style="color:#9ece6a;">"Enter your message"
                  className=style="color:#9ece6a;">"w-full px-4 py-2 bg-gray-200 text-gray-900 rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-300 transition duration-300 resize-none"
                />
              </style="color:#f7768e;font-weight:600;">div>

              <style="color:#f7768e;font-weight:600;">button
                type=style="color:#9ece6a;">"submit"
                disabled={status === style="color:#9ece6a;">"loading"}
                className=style="color:#9ece6a;">"w-full bg-yellow-300 text-gray-800 font-medium py-2 px-4 rounded-lg hover:bg-yellow-400 transition duration-300 disabled:opacity-60 disabled:cursor-not-allowed cursor-pointer"
              >
                {status === style="color:#9ece6a;">"loading" ? style="color:#9ece6a;">"Sending..." : style="color:#9ece6a;">"Send Message"}
              </style="color:#f7768e;font-weight:600;">button>
            </style="color:#f7768e;font-weight:600;">form>
          )}
        </style="color:#f7768e;font-weight:600;">div>
      </style="color:#f7768e;font-weight:600;">div>
    </style="color:#f7768e;font-weight:600;">div>
  );
}
Replace YOUR_FORM_ID with your Backforms key

Connect this component to your Backforms endpoint

Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.

Get Free Endpoint Key

Frequently Asked Questions & Technical Integration

Where do I find my Form ID to replace YOUR_FORM_ID?

Create a free form in your Backforms dashboard (app.backforms.com). You will receive an endpoint URL formatted as https://backforms.com/f/{FORM_ID}. Simply paste that ID in place of YOUR_FORM_ID.

How does the invisible honeypot (_gotcha) spam trap work?

The input name='_gotcha' is hidden via inline CSS and marked with tabIndex={-1}. Legitimate human users will never see or interact with it. Automated spam bots automatically populate all form fields they find. If Backforms detects data in _gotcha, it silently rejects the submission without notifying the bot.

Can I receive submissions directly in Telegram, Discord, or Google Sheets?

Yes! In your Backforms settings, you can toggle instant email notifications, add a Telegram bot chat ID, connect Discord channel webhooks, or enable one-click Google Sheets synchronization without any backend code.