Captcha
Protect your forms and API call with captcha validation.
Support
VitNode supports multiple captcha providers. You can choose the one that fits your needs. Currently, we support:
If you need more providers, feel free to open a Feature Request on our GitHub repository :)
Usage
In this example, we will show you how to use captcha in your forms. We will use the AutoForm
component to render the form and handle the captcha validation.
Activate captcha in route
Add withCaptcha
to your route config to enable captcha validation for this route.
import { buildRoute } from '@vitnode/core/api/lib/route';
export const exampleRoute = buildRoute({
...CONFIG_PLUGIN,
route: {
method: 'post',
description: 'Create a new user',
path: '/sign_up',
withCaptcha: true,
},
handler: async c => {},
});
Get config from middleware API
Get captcha config from middleware API in your view and pass it to your 'use client';
component.
import { getMiddlewareApi } from '@vitnode/core/lib/api/get-middleware-api';
export const SignUpView = async () => {
const { captcha } = await getMiddlewareApi();
return <FormSignUp captcha={captcha} />;
};
Use in form
Get the captcha
config from the props and pass it to the AutoForm
component. This will render the captcha widget in your form.
'use client';
import { AutoForm } from '@vitnode/core/components/form/auto-form';
export const FormSignUp = ({
captcha,
}: {
captcha: z.infer<typeof routeMiddlewareSchema>['captcha'];
}) => {
return (
<AutoForm<typeof formSchema>
captcha={captcha}
fields={[]}
formSchema={formSchema}
/>
);
};
AutoForm
Lear more about the AutoForm component and how to use it.
Submit form with captcha
In your form submission handler, you can get the captchaToken
from the form submission context and pass it to your mutation API.
'use client';
import {
AutoForm,
type AutoFormOnSubmit,
} from '@vitnode/core/components/form/auto-form';
export const FormSignUp = ({
captcha,
}: {
captcha: z.infer<typeof routeMiddlewareSchema>['captcha'];
}) => {
const onSubmit: AutoFormOnSubmit<typeof formSchema> = async (
values,
form,
{ captchaToken },
) => {
// Call your mutation API with captcha token
await mutationApi({
...values,
captchaToken,
});
// Handle success or error
};
return (
<AutoForm<typeof formSchema>
captcha={captcha}
fields={[]}
onSubmit={onSubmit}
formSchema={formSchema}
/>
);
};
Next, you need to set captchaToken
in your mutation API call. This token is provided by the AutoForm
component when the form is submitted.
'use server';
import type { z } from 'zod';
import { fetcher } from '@vitnode/core/lib/fetcher';
export const mutationApi = async ({
captchaToken,
...input
}: z.infer<typeof zodSignUpSchema> & { captchaToken }) => {
const res = await fetcher(usersModule, {
path: '/sign_up',
method: 'post',
module: 'users',
captchaToken,
args: {
body: input,
},
});
if (res.status !== 201) {
return { error: await res.text() };
}
const data = await res.json();
return { data };
};
Custom Usage
If you want to use captcha in your custom form or somewhere else, follow these steps.
Activate captcha in route
import { buildRoute } from '@vitnode/core/api/lib/route';
export const exampleRoute = buildRoute({
...CONFIG_PLUGIN,
route: {
method: 'post',
description: 'Create a new user',
path: '/sign_up',
withCaptcha: true,
},
handler: async c => {},
});
Get config from middleware API
import { getMiddlewareApi } from '@vitnode/core/lib/api/get-middleware-api';
export const SignUpView = async () => {
const { captcha } = await getMiddlewareApi();
return <FormSignUp captcha={captcha} />;
};
Use useCaptcha
hook
Inside your client component, use the useCaptcha
hook to handle captcha rendering and validation. Remember to add div
with id="vitnode_captcha"
where you want the captcha widget to appear.
'use client';
import { AutoForm } from '@vitnode/core/components/form/auto-form';
export const FormSignUp = ({
captcha,
}: {
captcha: z.infer<typeof routeMiddlewareSchema>['captcha'];
}) => {
const { isReady, getToken, onReset } = useCaptcha(captcha);
const onSubmit = async () => {
await mutationApi({
// ...other values,
captchaToken: await getToken(),
});
// Handle success or error
onReset(); // Reset captcha after submission
};
return (
<form onSubmit={onSubmit}>
{/* Render captcha widget */}
<div id="vitnode_captcha" />
<Button disabled={!isReady}>Submit</Button>
</form>
);
};
Submit form with captcha
'use server';
import type { z } from 'zod';
import { fetcher } from '@vitnode/core/lib/fetcher';
export const mutationApi = async ({
captchaToken,
}: {
captchaToken;
}) => {
await fetcher(usersModule, {
path: '/test',
method: 'post',
module: 'blog',
captchaToken,
});
};