Back to all posts

How to Implement Altcha CAPTCHA in Next.js: Privacy-First Form Protection

3 min read
Static Forms Team

Adding CAPTCHA protection to your Next.js forms doesn't have to be complicated. Altcha provides a privacy-focused solution that's easy to implement and doesn't track your users. Let's add it to a simple contact form.

What You Need

Before starting, make sure you have:

  1. Next.js application
  2. Pro subscription - Altcha needs Static Forms Pro
  3. API key - From your Static Forms account

Step 1: Install Altcha

npm install altcha

Step 2: Add Your API Key

Create a .env.local file:

NEXT_PUBLIC_STATIC_FORMS_API_KEY=your_api_key_here

Step 3: Create a Simple Contact Form

Here's a basic contact form with Altcha verification:

'use client';

import { useState, useEffect } from 'react';

export default function ContactForm() {
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [status, setStatus] = useState('');

  // Load ALTCHA package
  useEffect(() => {
    import('altcha');
  }, []);

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    
    const form = e.currentTarget;
    setIsSubmitting(true);
    
    try {
      const formData = new FormData(form);
      formData.append('apiKey', process.env.NEXT_PUBLIC_STATIC_FORMS_API_KEY || '');
      
      const response = await fetch('https://api.staticforms.xyz/submit', {
        method: 'POST',
        body: formData,
      });
      
      if (response.ok) {
        setStatus('Message sent successfully!');
        form.reset();
        // Reset ALTCHA widget
        const altchaWidget = document.querySelector('altcha-widget') as any;
        if (altchaWidget?.reset) {
          altchaWidget.reset();
        }
      } else {
        setStatus('Failed to send message. Please try again.');
      }
    } catch (error) {
      setStatus('An error occurred. Please try again.');
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return (
    <div className="max-w-md mx-auto p-6">
      {status && (
        <div className="mb-4 p-3 rounded bg-blue-50 text-blue-800">
          {status}
        </div>
      )}
    
      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <label className="block mb-2 font-medium">Name</label>
          <input
            type="text"
            name="name"
            required
            className="w-full p-3 border rounded-md"
          />
        </div>
        
        <div>
          <label className="block mb-2 font-medium">Email</label>
          <input
            type="email"
            name="email"
            required
            className="w-full p-3 border rounded-md"
          />
        </div>
        
        <div>
          <label className="block mb-2 font-medium">Message</label>
          <textarea
            name="message"
            required
            rows={4}
            className="w-full p-3 border rounded-md"
          />
        </div>
        
        <div>
          <label className="block mb-2 font-medium">Verify you're human</label>
          <altcha-widget
            challengeurl={`https://www.staticforms.xyz/api/altcha/challenge?apiKey=${process.env.NEXT_PUBLIC_STATIC_FORMS_API_KEY || ''}`}
            name="altchaToken"
          />
        </div>
        
        <button
          type="submit"
          disabled={isSubmitting}
          className="w-full py-3 bg-blue-600 text-white rounded-md disabled:bg-gray-400"
        >
          {isSubmitting ? 'Sending...' : 'Send Message'}
        </button>
      </form>
    </div>
  );
}

Step 4: Use the Component

Create a page to use your form:

// app/contact/page.tsx
import ContactForm from './ContactForm';

export default function ContactPage() {
  return (
    <div className="container mx-auto py-12">
      <h1 className="text-3xl font-bold text-center mb-8">Contact Us</h1>
      <ContactForm />
    </div>
  );
}

Step 5: Enable Altcha

  1. Go to your CAPTCHA settings
  2. Switch to "Altcha" tab
  3. Generate your keys
  4. Save settings

That's It!

Your form now has privacy-focused CAPTCHA protection. The widget automatically:

  • ✅ Loads and verifies challenges
  • ✅ Works without tracking users
  • ✅ Protects against spam
  • ✅ No puzzles for users to solve

Need Help?

Related Articles