Submit JSON with Next.js

In this example, we'll use the Submit JSON JS Client to wire up a contact us form submission notification using Next.js

We used react-hook-form and zod here instead of formik and yuplike the React example. Refer to that if you prefer those technolgies.

Set up your Next.js Project

To get started, make sure you have a working Next.js project. If you do not, follow these instructions.

Next, install submitjson and these other packages with your favorite package manager.

pnpm add submitjson zod react-hook-form @hookform/resolvers

Configure a Server Action

First you should create an enviornment variable for your Submit JSON API Key, make sure to not check it into Git!

SUBMIT_JSON_API_KEY = sjk_xxxxxxxxxxxx

Next create a new file pages/api/contact.action.js, import submitjson, then handle the submission.

import SubmitJSON from 'submitjson'

const sj = new SubmitJSON({
  apiKey: process.env.SUBMIT_JSON_API_KEY,
  endpoint: 'XXXXXX'

export async function action({ request }) {
  const formData = await request.formData()
  // 🚛 Deliver your submission with one line of code
  const submission = await sj.submit(formData)

  const response = {
    message: 'Form submitted successfully',

  return new Response(JSON.stringify(response), {
    status: 200,
    headers: {
      'Content-Type': 'application/json',

Create a page with the contact form

Finally, you'll need to create a contact form component or page. We went the page route for example's sake!

// pages/contact.tsx
import React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';

// Zod schema for form validation
const formSchema = z.object({
  name: z.string().min(1, 'Name is required'),
  email: z.string().email('Invalid email address').min(1, 'Email is required'),
  message: z.string().min(1, 'Message is required'),
type FormData = z.infer<typeof formSchema>;

const ContactPage: React.FC = () => {
  const {
    formState: { errors },
  } = useForm<FormData>({
    resolver: zodResolver(formSchema),

  const onSubmit: SubmitHandler<FormData> = async (data) => {
    const response = await fetch('/api/contact', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      body: JSON.stringify(data),

    if (response.ok) {
      // Handle success (e.g., show a success message)
    } else {
      // Handle error

  return (
      <h1>Contact Us</h1>
      <form onSubmit={handleSubmit(onSubmit)}>
          {errors.name && <p>{errors.name.message}</p>}
          {errors.email && <p>{errors.email.message}</p>}

            placeholder="Your message"
          {errors.message && <p>{errors.message.message}</p>}

        <button type="submit">Send Message</button>

export default ContactPage;

🤩✨ Nice job, that was a doozy. You successfully integrated Submit JSON with Next.js!