DEV Community

Cover image for Simple Lightweight CAPTCHA Alternative for React & Next.js
Tino
Tino

Posted on AI-assisted

Simple Lightweight CAPTCHA Alternative for React & Next.js

i try built a lightweight alternative captcha for react/nextjs πŸ’…

i recently wanted to add a bit of friction to my forms just to slow down automated bots. i didn't need anything massiveβ€”just a simple hurdle to make it a little more "expensive" or annoying for bots to spam.

so i built react-math-captcha. it's just a lightweight, self-hosted tool that does exactly that without overcomplicating things.


the simple goal

this isn't trying to be the most "advanced" security layer on the planet. the goal is just to make it more tedious for basic automated scripts to bypass your forms.

  • simple integration: easy to drop into existing React/Next.js projects.
  • no database needed: uses encrypted JWE sessions (via jose), so you don't need Redis or a DB to store captcha state.
  • ssr ready: uses SVGs, so it works perfectly with Next.js and other SSR frameworks.

how to use it

it's a quick setup if you're already in a React environment.

  1. set the secret add this to your .env. this secret is used to encrypt the JWE session, keeping all captcha states secure without needing a database or Redis.
CAPTCHA_SECRET=at-least-16-characters-please
Enter fullscreen mode Exit fullscreen mode

2. install

npm install react-math-captcha
Enter fullscreen mode Exit fullscreen mode

3. add the route (Next.js)

create an API route to act as the "brain" of the captcha. this handler manages the gatekeeper (slider) and generates the SVG math challenges to keep things lightweight on the client.

// app/api/captcha/route.ts
import { createCaptchaHandler } from 'react-math-captcha/server'
export const { POST } = createCaptchaHandler()
Enter fullscreen mode Exit fullscreen mode

4. use the component

mount the widget in your form. users will be prompted to slide a slider (gatekeeper) before receiving the math challenge.

'use client'
import { MathCaptcha } from 'react-math-captcha/react'
import { register } from './actions'

export default function Page() {
  return (
    <form action={register}>
      <input name="email" placeholder="email" />
      <MathCaptcha />
      <button>submit</button>
    </form>
  )
}
Enter fullscreen mode Exit fullscreen mode

5. verify on the server

finally, verify the token on the server. if the answer is correct, the system provides a verificationToken. once verifyCaptchaToken is called, the token is consumed immediately (one-time use) to prevent replay attacks by bots.

// actions.ts
'use server'
import { verifyCaptchaToken } from 'react-math-captcha/server'

export async function register(formData: FormData) {
  try {
    await verifyCaptchaToken(formData)
    // captcha is valid & token consumed (secure from replay attacks)
  } catch (err) {
    // invalid captcha
    return { error: 'invalid captcha' }
  }
}
Enter fullscreen mode Exit fullscreen mode

keeping it simple

at the end of the day, sometimes you just need a small barrier to keep things clean. if you're looking for a simple way to add some bot friction, feel free to check out the repo.

GitHub: tinoimammp/react-math-captcha

hope this helps someone!

WebDev #ReactJS #NextJS #OpenSource #GenZTech

Top comments (0)