Newsletter Signup Form in React (No Backend Required)

Build a newsletter signup form without writing backend code. Email collection and spam protection included.

What We're Building

A newsletter signup form that:

  • Collects email addresses
  • Validates email format
  • Prevents spam signups
  • Stores subscribers in a dashboard
  • Exports to CSV for your email service
  • Works without backend code

The Quick Version

If you just want the code:

import { useFormFlow } from '@formflow.sh/react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

export function NewsletterForm() {
  const { register, handleSubmit, formState } = useFormFlow({
    apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
    onSuccess: () => alert('Subscribed! Check your email.'),
  });

  return (
    <form onSubmit={handleSubmit} className="flex gap-2 max-w-md">
      <Input
        {...register('email')}
        type="email"
        placeholder="Enter your email"
        className="flex-1"
        required
      />
      <Button type="submit" disabled={formState.isSubmitting}>
        {formState.isSubmitting ? 'Subscribing...' : 'Subscribe'}
      </Button>
    </form>
  );
}

That's it! 10 lines of code for a complete newsletter signup form.

Step-by-Step Tutorial

Step 1: Install FormFlow

npm install @formflow.sh/react

Step 2: Get Your API Key

Create a free account at formflow.sh and get your API key. Free tier includes 50 submissions per month.

Add to .env.local:

NEXT_PUBLIC_FORMFLOW_API_KEY=ff_live_your_key_here

Step 3: Create the Form

Create a new component NewsletterForm.tsx:

import { useFormFlow } from '@formflow.sh/react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

export function NewsletterForm() {
  const { register, handleSubmit, formState } = useFormFlow({
    apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
    onSuccess: () => {
      alert('Thanks for subscribing! Check your email.');
    },
  });

  return (
    <form onSubmit={handleSubmit} className="flex gap-2 max-w-md">
      <Input
        {...register('email')}
        type="email"
        placeholder="Enter your email"
        className="flex-1"
        required
      />
      <Button type="submit" disabled={formState.isSubmitting}>
        {formState.isSubmitting ? 'Subscribing...' : 'Subscribe'}
      </Button>
    </form>
  );
}

Step 4: Use It Anywhere

import { NewsletterForm } from '@/components/NewsletterForm';

export default function HomePage() {
  return (
    <div>
      <h1>Subscribe to our newsletter</h1>
      <NewsletterForm />
    </div>
  );
}

Customization Options

Add Name Field

Collect names for personalized emails:

<form onSubmit={handleSubmit} className="space-y-4 max-w-md">
  <div>
    <Label htmlFor="email">Email *</Label>
    <Input
      {...register('email')}
      id="email"
      type="email"
      placeholder="you@example.com"
      required
    />
  </div>

  <div>
    <Label htmlFor="name">Name (optional)</Label>
    <Input
      {...register('name')}
      id="name"
      placeholder="John Doe"
    />
  </div>

  <Button type="submit" disabled={formState.isSubmitting} className="w-full">
    {formState.isSubmitting ? 'Subscribing...' : 'Subscribe'}
  </Button>
</form>

Add Success Message Component

Instead of alert, show a nice success message:

import { useState } from 'react';

export function NewsletterForm() {
  const [submitted, setSubmitted] = useState(false);

  const { register, handleSubmit, formState } = useFormFlow({
    apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
    onSuccess: () => {
      setSubmitted(true);
    },
  });

  if (submitted) {
    return (
      <div className="bg-green-50 border border-green-200 rounded-lg p-4">
        <h3 className="font-semibold text-green-900">
          Thanks for subscribing!
        </h3>
        <p className="text-green-700 text-sm mt-1">
          Check your email to confirm your subscription.
        </p>
      </div>
    );
  }

  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
    </form>
  );
}

Add Email Validation

Custom email validation with error messages:

<Input
  {...register('email', {
    required: 'Email is required',
    pattern: {
      value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
      message: 'Please enter a valid email address',
    },
  })}
  type="email"
  placeholder="Enter your email"
/>
{formState.errors.email && (
  <p className="text-red-500 text-sm mt-1">
    {formState.errors.email.message}
  </p>
)}

Styling Examples

Inline Form (Header/Footer)

<form onSubmit={handleSubmit} className="flex gap-2">
  <Input
    {...register('email')}
    type="email"
    placeholder="Your email"
    className="max-w-xs"
  />
  <Button type="submit">Subscribe</Button>
</form>

Centered Hero Section

<div className="text-center max-w-2xl mx-auto py-20">
  <h2 className="text-4xl font-bold mb-4">
    Join our newsletter
  </h2>
  <p className="text-gray-600 mb-8">
    Get weekly updates on React, forms, and web development.
  </p>
  <form onSubmit={handleSubmit} className="flex gap-2 justify-center">
    <Input
      {...register('email')}
      type="email"
      placeholder="Enter your email"
      className="max-w-sm"
    />
    <Button type="submit">Subscribe</Button>
  </form>
</div>

Sidebar Widget

<div className="bg-gray-50 rounded-lg p-6">
  <h3 className="font-semibold mb-2">Newsletter</h3>
  <p className="text-sm text-gray-600 mb-4">
    Weekly React tips in your inbox.
  </p>
  <form onSubmit={handleSubmit} className="space-y-2">
    <Input
      {...register('email')}
      type="email"
      placeholder="Your email"
      className="w-full"
    />
    <Button type="submit" className="w-full">
      Subscribe
    </Button>
  </form>
</div>

Managing Subscribers

View Subscribers

All newsletter signups appear in your FormFlow dashboard at formflow.sh/submissions.

Export to CSV

Click "Export CSV" to download all subscribers. Import this into:

  • Mailchimp
  • ConvertKit
  • SendGrid
  • Any email service that accepts CSV

Email Notifications

Get notified when someone subscribes:

  1. Go to your FormFlow dashboard
  2. Click on "Settings"
  3. Enable email notifications
  4. Enter your email

Spam Protection

FormFlow automatically protects against spam with:

  • Honeypot fields - Invisible fields that catch bots
  • Rate limiting - Prevents automated signups
  • Email validation - Ensures valid email format

Advanced: Double Opt-In

For compliance with GDPR and best practices, you can implement double opt-in by integrating with your email service (Mailchimp, SendGrid, etc.). FormFlow captures the initial submission, then your email service handles the confirmation flow:

const { register, handleSubmit } = useFormFlow({
  apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
  onSuccess: () => {
    // Show message to check email
    alert('Please check your email to confirm your subscription.');
  },
});

// Then in your email service (Mailchimp, etc.):
// 1. Send confirmation email
// 2. User clicks link
// 3. Subscription confirmed

Common Use Cases

Blog Newsletter

Add to blog posts:

<div className="border-2 border-black rounded-lg p-6 my-8">
  <h3 className="font-bold text-xl mb-2">
    Enjoyed this post?
  </h3>
  <p className="text-gray-600 mb-4">
    Get more content like this in your inbox every week.
  </p>
  <NewsletterForm />
</div>

Product Waitlist

Collect emails before launch:

<div className="text-center py-20">
  <h1 className="text-5xl font-bold mb-4">
    Coming Soon
  </h1>
  <p className="text-xl text-gray-600 mb-8">
    Be the first to know when we launch.
  </p>
  <NewsletterForm />
  <p className="text-sm text-gray-500 mt-4">
    {subscriberCount} people already signed up
  </p>
</div>

Footer Signup

Add to footer on every page:

<footer className="bg-black text-white py-12">
  <div className="max-w-6xl mx-auto px-6">
    <div className="grid md:grid-cols-2 gap-8 items-center">
      <div>
        <h3 className="text-2xl font-bold mb-2">
          Stay Updated
        </h3>
        <p className="text-gray-400">
          Join 10,000+ developers getting weekly tips.
        </p>
      </div>
      <NewsletterForm />
    </div>
  </div>
</footer>

Best Practices

1. Be Clear About What You're Sending

Tell users what to expect:

"Get weekly React tutorials. Unsubscribe anytime."

2. Show Social Proof

"Join 10,000+ developers"

3. Make Unsubscribe Easy

Include unsubscribe link in every email (most email services do this automatically).

4. Confirm Subscription

Show success message after signup:

"Thanks! Check your inbox for a confirmation email."

Complete Example: Premium Newsletter Form

import { useState } from 'react';
import { useFormFlow } from '@formflow.sh/react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';

export function PremiumNewsletterForm() {
  const [submitted, setSubmitted] = useState(false);

  const { register, handleSubmit, formState, reset } = useFormFlow({
    apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
    onSuccess: () => {
      setSubmitted(true);
      reset(); // Clear form
    },
  });

  if (submitted) {
    return (
      <div className="bg-green-50 border border-green-200 rounded-lg p-6 text-center">
        <div className="text-green-600 text-5xl mb-3">āœ“</div>
        <h3 className="font-bold text-xl text-green-900 mb-2">
          You're all set!
        </h3>
        <p className="text-green-700">
          Check your email to confirm your subscription.
        </p>
        <button
          onClick={() => setSubmitted(false)}
          className="text-green-800 underline text-sm mt-3"
        >
          Subscribe another email
        </button>
      </div>
    );
  }

  return (
    <div className="bg-white border-2 border-black rounded-lg p-6 max-w-md">
      <h3 className="text-2xl font-bold mb-2">
        Join 10,000+ Developers
      </h3>
      <p className="text-gray-600 mb-6">
        Weekly React tips, tutorials, and news. Unsubscribe anytime.
      </p>

      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <Label htmlFor="email">Email Address *</Label>
          <Input
            {...register('email', {
              required: 'Email is required',
              pattern: {
                value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                message: 'Please enter a valid email',
              },
            })}
            id="email"
            type="email"
            placeholder="you@example.com"
          />
          {formState.errors.email && (
            <p className="text-red-500 text-sm mt-1">
              {formState.errors.email.message}
            </p>
          )}
        </div>

        <div>
          <Label htmlFor="name">Name (optional)</Label>
          <Input
            {...register('name')}
            id="name"
            placeholder="John Doe"
          />
        </div>

        <Button
          type="submit"
          disabled={formState.isSubmitting}
          className="w-full"
        >
          {formState.isSubmitting
            ? 'Subscribing...'
            : 'Subscribe for Free'}
        </Button>

        <p className="text-xs text-gray-500 text-center">
          No spam. Only high-quality content. Unsubscribe with one click.
        </p>
      </form>
    </div>
  );
}

Conclusion

Building a newsletter signup form in React is simple with FormFlow:

  • No backend code required
  • Built-in spam protection
  • Easy CSV export for email services
  • Works with any UI library
  • Free tier: 50 submissions/month

Related Resources

Start growing your email list today

Free tier includes 50 subscribers per month. No credit card required.

Newsletter Signup Form in React (No Backend Required) | FormFlow Blog | FormFlow