Using Server Actions in the Next.js Supabase SaaS Kit
Learn how to write Server Actions to mutate and revalidate your data
Server Actions help us communicate with the server just by creating normal Javascript functions that Next.js converts to server POST endpoints. They are particularly useful to mutate data and revalidate the data that we fetched from Server Components.
Generally speaking, there is nothing special in Makerkit compared to any other Next.js application in how you will use Server Actions. However, I want to introduce you to a nifty utility to make your life easier while writing Server Actions: enhanceAction
.
Let's first introduce Server Actions.
In the large majority of cases - you will be writing React Server Actions to update data in your DB. Server Actions are used to perform mutations on the server-side - while being called like normal functions.
To create a server action, it's enough to add use server
at the top of the file and export the function.
'use server';// I am now a server action!export const myServerAction = async function () { // ... your code here return { success: true, };};
The above is a plain POST request that basically does nothing. Let's see how we can make it more useful.
Makerkit ships with a utility to help you write these actions. The utility is called enhanceAction
and we import it from @kit/next/actions
.
import { enhanceAction } from '@kit/next/actions';
This utility helps us with three main things:
- 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
- if you configured a monitoring provider, it sends the caught exception to the monitoring provider
Fantastic, let's see how we can use it.
'use server';import { z } from 'zod';import { enhanceAction } from '@kit/next/actions';const ZodSchema = z.object({ email: z.string().email(), password: z.string().min(6),});export const myServerAction = enhanceAction( async function (data, user) { // 1. "data" has been validated against the Zod schema, and it's safe to use // 2. "user" is the authenticated user // ... your code here return { success: true, }; }, { schema: ZodSchema, },);
Using a Captcha token protection
If you want to protect your server actions with a captcha token, you can do so by passing the captcha site token to the enhanceAction
function and setting the captcha
flag to true
.
'use server';import { enhanceAction } from '@kit/next/actions';export const myServerAction = enhanceAction( async function (data, user) { // ... your code here return { success: true, }; }, { captcha: true, schema: ZodSchema, },);
When calling the server action, 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 server action, we can pass the captcha
import { useCaptchaToken } from '@kit/auth/captcha/client';function Component() { const captchaToken = useCaptchaToken(); const onSubmit = async (params: { email: string; password: string; }) => { const response = await myServerAction({ ...params, captchaToken, }); // ... your code here };}
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.
Passing the Captcha Token
NB: you must pass the captcha token in the request body when calling the server action. The function's type checker will ensure that you pass the captcha token as it will error out if the token is not defined in the Zod schema as captchaToken
.
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.
'use server';import { enhanceAction } from '@kit/next/actions';export const myServerAction = enhanceAction( async function (data, user) { // ... your code here return { success: true, }; }, { captcha: true, captureException: false, schema: ZodSchema, },);