Using API Route Handlers in the Next.js Supabase SaaS Kit
Learn how to write Route Handlers in the Next.js Supabase SaaS Kit to fetch and write data
API Route handlers are added using the convention route.ts
and exporting one or many HTTP methods (e.g., GET
, POST
, PUT
, DELETE
).
While you won't be writing too many API route handlers (prefer Server Actions for mutations) - you can use the enhanceRouteHandler
utility to help you with the following:
- checks the user state (if the user is authenticated)
- given a Zod schema, it validates the request body
- given a captcha site key, it validates the captcha token
- report an uncaught exception to the monitoring provider (if configured)
Fantastic, let's see how we can use it.
import { z } from 'zod';import { enhanceRouteHandler } from '@kit/next/routes';import { NextResponse } from 'next/server';const ZodSchema = z.object({ email: z.string().email(), password: z.string().min(6),});export const POST = enhanceRouteHandler( async function({ body, user, request }) { // 1. "body" has been validated against the Zod schema, and it's safe to use // 2. "user" is the authenticated user // 3. "request" is the request object that contains the headers, query, etc. // ... your code here return NextResponse.json({ success: true, }); }, { schema: ZodSchema, },);
Using a Captcha token protection
If you want to protect your API route handlers with a captcha token, you can do so by passing the captcha site token to the enhanceRouteHandler
function and setting the captcha
flag to true
.
import { enhanceRouteHandler } from '@kit/next/routes';export const POST = enhanceRouteHandler( async function({ body, user, request }) { // ... your code here return NextResponse.json({ success: true, }); }, { captcha: true, schema: ZodSchema, },);
When calling the API route handler, we must supply the captcha token in the request body.
The captcha token can be retrieved from the useCaptchaToken
hook in the package @kit/auth/captcha/client
.
import { useCaptchaToken } from '@kit/auth/captcha/client';function Component() { const captchaToken = useCaptchaToken(); // ... your code here}
Now, when calling the API route handler, we can pass the captcha and the CSRF token.
NB: The CSRF token must be added for all API routes making mutations in routes that are outside /api/*
. Routes inside /api/*
are not protected by default as they're meant to be used externally.
import { useCaptchaToken } from '@kit/auth/captcha/client';import { useCsrfToken } from '@kit/shared/hooks';function Component() { const captchaToken = useCaptchaToken(); const csrfToken = useCsrfToken(); const onSubmit = async (params: { email: string; password: string; }) => { const response = await fetch('/my-api-route', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrfToken, 'x-captcha-token': captchaToken, }, body: JSON.stringify(params), }); // ... your code here }; // ... your code here}
You can improve the above using React Query:
import { useMutation } from '@tanstack/react-query';import { useCaptchaToken } from '@kit/auth/captcha/client';function Component() { const captchaToken = useCaptchaToken(); const mutation = useMutateData(); const onSubmit = async (params: { email: string; password: string; }) => { await mutation.mutateAsync(params); }; // ... your code here}function useMutateData() { return useMutation({ mutationKey: 'my-mutation', mutationFn: async (params: { email: string; password: string }) => { const response = await fetch('/my-api-route', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-captcha-token': captchaToken, }, body: JSON.stringify(params), }); if (!response.ok) { throw new Error('An error occurred'); } return response.json(); }, });}
NB: to use Captcha protection, you need to set the captcha token in the environment variables.
CAPTCHA_SECRET_TOKEN=NEXT_PUBLIC_CAPTCHA_SITE_KEY=
As a secret environment variable, please do not add it to the .env
file. Instead, add it to the environment variables of your CI/CD system.
The only captcha provider supported is Cloudflare Turnstile.
Capturing Exceptions
This function automatically reports uncaught exceptions if you configured a monitoring provider. The monitoring provider is set in the environment variable MONITORING_PROVIDER
.
To disable it, pass captureException: false
to the enhanceAction
function.
import { enhanceRouteHandler } from '@kit/next/routes';export const POST = enhanceRouteHandler( async function({ body, user, request }) { // ... your code here return NextResponse.json({ success: true, }); }, { captcha: true, captureException: false, schema: ZodSchema, },);