This feature was designed for use with deprecated low-code themes. We recommend using Nodemailer or an API-based transactional email service.

Stackbit supports the ability to accept form submissions and send a summary of the form response content in an email notification.

The process works like this:

  1. Specify an email destination.
  2. Sign the email string with a secret key.
  3. Submit form response to a server-side function.
  4. Post response to Stackbit's API and return the result to the front end.

Specify & Sign Email Destination

The destination is the email address to which Stackbit will deliver the form response summary when a request is submitted.

Configurable Destination

The email destination can be content specified by editors and delivered from your content source, or it can be a hard-coded value that you provide directly.

Signing Email String

Once you have the destination (as a string), you must sign it using a STACKBIT_CONTACT_FORM_SECRET environment variable. This value must be provided by Stackbit. Contact to request your secret value (you'll need to provide your project ID).

Prior to rendering your form, you must sign the email address. Do this on the server-side so as to not expose this key. We recommend using jose-jwt and crypto, like this:

import { SignJWT } from 'jose/jwt/sign'
import crypto from 'crypto'

const secretKey = crypto.createHash('sha256').update(process.env.STACKBIT_CONTACT_FORM_SECRET).digest()
const destination = await new SignJWT({ email: '' })
  .setProtectedHeader({ alg: 'HS256' })

Pass the destination value to your form component. (Note that '' is the string representing the email that should be replaced with the appropriate value for your project.)

Form & Submission Structure

Your form can be structured however you'd like. The only requirement is that you pass a form-destination key-value pair with the signed email destination.

<input type="hidden" name="form-destination" value={props.destination} />

Server-Side Function

Submit the form to some server-side function so that you don't expose Stackbit's submission endpoint. Here is an example of an AWS Lambda function using the axios library

const axios = require('axios')

// Handle the lambda invocation
exports.handler = async function (event, context, callback) {
  try {
    const url = process.env.STACKBIT_CONTACT_FORM_SUBMISSION_URL
    if (!url) throw new Error('No Stackbit URL specified')
    // Submit the form
    const response = await axios({ method: 'post', url, data: JSON.parse(event.body) })
    // Return the response from Stackbit
    callback(null, { statusCode: 200, body: })
  } catch (e) {
    callback(null, {
      statusCode: e?.response?.status ?? 500,
      body: e?.response?.statusText ?? e.message

Notice here that you have another environment variable — STACKBIT_CONTACT_FORM_SUBMISSION_URL. This must also be provided by Stackbit. Contact to request the value for your site (you'll need to provide your project ID).