Module Middleware/Honeypot

This depends on react, @oslojs/crypto, and @oslojs/encoding.

The Honeypot middleware allows you to add a honeypot mechanism to your routes, providing a simple yet effective way to protect public forms from spam bots.

To use the Honeypot middleware, first import and configure it:

import { unstable_createHoneypotMiddleware } from "remix-utils/middleware/honeypot";

export const [honeypotMiddleware, getHoneypotInputProps] =
unstable_createHoneypotMiddleware({
// Randomize the honeypot field name
randomizeNameFieldName: false,
// Default honeypot field name
nameFieldName: "name__confirm",
// Optional timestamp field for validation
validFromFieldName: "from__confirm",
// Unique seed for encryption (recommended for extra security)
encryptionSeed: undefined,

onSpam(error) {
// Handle SpamError here and return a Response
return new Response("Spam detected", { status: 400 });
},
});

Add the honeypotMiddleware to the unstable_middleware array in the route where you want to enable spam protection, use it in your app/root.tsx file to apply it globally:

import { honeypotMiddleware } from "~/middleware/honeypot";

export const unstable_middleware = [honeypotMiddleware];

Use the getHoneypotInputProps function in your root loader to retrieve the honeypot input properties:

import { getHoneypotInputProps } from "~/middleware/honeypot";

export async function loader({ request }: LoaderFunctionArgs) {
let honeypotInputProps = await getHoneypotInputProps();
return json({ honeypotInputProps });
}

Wrap your application in the HoneypotProvider component to make the honeypot input properties available throughout your app:

import { HoneypotProvider } from "remix-utils/honeypot/react";

export default function RootComponent() {
return (
<HoneypotProvider {...honeypotInputProps}>
<Outlet />
</HoneypotProvider>
);
}

In any public form, include the HoneypotInputs component to add the honeypot fields:

import { HoneypotInputs } from "remix-utils/honeypot/react";

function PublicForm() {
return (
<Form method="post">
<HoneypotInputs label="Please leave this field blank" />
<input type="text" name="name" placeholder="Your Name" />
<input type="email" name="email" placeholder="Your Email" />
<button type="submit">Submit</button>
</Form>
);
}

For requests with a body (e.g., POST, PUT, DELETE) and a content type of application/x-www-form-urlencoded or multipart/form-data, the middleware validates the honeypot fields. If the request passes the honeypot check, it proceeds to the action handler. If the honeypot check fails, the onSpam handler is invoked, allowing you to handle spam requests appropriately.

In your action handlers, you can process the form data as usual, without worrying about spam checks—they are already handled by the middleware:

export async function action({ request }: ActionFunctionArgs) {
// If this code runs, the honeypot check passed
let formData = await request.formData();
let name = formData.get("name");
let email = formData.get("email");
// Process the form data
}

The honeypot middleware is designed to be lightweight and effective against basic spam bots. For advanced spam protection, consider combining this with other techniques like CAPTCHA or rate limiting.

Namespaces

unstable_createHoneypotMiddleware

Functions

unstable_createHoneypotMiddleware