DEV Community

Cover image for Contact Form with AWS SES, Amplify Studio, DynamoDB, and NodeJS Lambda
Alfredo Baldoceda
Alfredo Baldoceda

Posted on

Contact Form with AWS SES, Amplify Studio, DynamoDB, and NodeJS Lambda

In this tutorial, we will guide you step by step through the process of creating a contact form using AWS SES (Simple Email Service), AWS Amplify, NodeJS Lambda, DynamoDB, UI components generated by Amplify Studio, and deploying it to a Next.js app hosted on GitHub with fully automated deployment. See video here.


Before we begin, make sure you have the following prerequisites:

  • An AWS account with appropriate permissions to create resources
  • AWS CLI and Amplify CLI installed and configured on your development machine
  • Basic knowledge of AWS services, Next.js, and GitHub

Step 1: Set up AWS SES

1. Login to the AWS Management Console and navigate to the AWS SES service.
2. Follow the instructions to verify your domain and set up email sending and receiving permissions.
3. Once your domain is verified, note down the ARN (Amazon Resource Name) of the verified domain.

Step 2: Host Next.js project with AWS Amplify

1. Create a Next.js project by running the following command:

$ npx create-next-app@latest
Enter fullscreen mode Exit fullscreen mode

2. Create a GitHub repository for your project, commit and push changes to remote.
3. Initialize an Amplify project with the following command:

$ amplify init
Enter fullscreen mode Exit fullscreen mode

4. Add hosting with Amplify CLI and select Continuous deployment (Git-based deployments) when prompted:

$ amplify add hosting
Enter fullscreen mode Exit fullscreen mode

Note: There is a more detailed blog explaining this step here

Step 3: Create Data Model using AWS Amplify Studio

1. Launch Amplify Studio by going to the AWS console and selecting backend environments under the Amplify service, then selecting the Amplify App we set up in the previous step.
2. Once in Amplify Studio, select Data Modeling. Click on Add model and enter ContactForm as the table name. Select the following field names:

  • Field name: id, Type: ID!
  • Field name: Name, Type: String
  • Field name: Email, Type: AWSEmail
  • Field name: Subject, Type: String
  • Field name: Message, Type: String 3. Finally, click on save and deploy.

Contact Data Modeling

Step 4: Create a Lambda Node.js Trigger

1. In the Amplify Studio UI, select Local setup instructions on the top right corner and copy the pull command instruction.
2. Open a command line under the root of your Next.js project and copy and paste the pull command.

Amplify Pull

3. After the pull command has been completed, run the amplify add function command. When prompted, select the following options:

  • Capability: Lambda function (serverless function)
  • Lambda function name: SendContactInfo
  • Runtime: NodeJS
  • Function template: Lambda trigger
  • Event source to associate: Amazon DynamoDB Stream
  • DynamoDB event source: Use API category graphql @model backed DynamoDB table(s)
  • Advanced setting: Environment variables configuration (Add VERIFIED_EMAIL environment key and value)

Lambda Trigger

4. After adding the function with the Amplify CLI, you can edit the NodeJS lambda source file.

const AWS = require('aws-sdk')
const ses = new AWS.SES

const verified_email = process.env.VERIFIED_EMAIL

exports.handler = async (event) => {

  for (const record of event.Records) {

    if (record.eventName === 'INSERT'){

      const contactName = record.dynamodb.NewImage.Name.S
      const contactEmail = record.dynamodb.NewImage.Email.S
      const contactMessage = record.dynamodb.NewImage.Message.S
      const contactSubject = record.dynamodb.NewImage.Subject.S

      const bodyData = '<br/><b>Contact Name</b>: ' + contactName +
        '<br/><b>Contact Email</b>: ' + contactEmail +
        '<br/><b>Message</b>: ' + contactMessage

      await ses.sendEmail({
        Destination: {
          ToAddresses: [verified_email],
        Source: verified_email,
        Message: {
          Subject: { Data: contactSubject },
          Body: {
            Html: {
              Charset: "UTF-8",
              Data: bodyData


    return { status: 'email sent'}

  return Promise.resolve('Successfully processed DynamoDB record');
Enter fullscreen mode Exit fullscreen mode

5. Make sure to add the environment variable verified_email. You can do this by running amplify update function and selecting Environment variable configuration under Available Advance settings. Alternatively, you can hardcode the value in the following code line:

const verified_email = process.env.VERIFIED_EMAIL
Enter fullscreen mode Exit fullscreen mode

6. Change the cloudformation template for the lambda to have the permission to use the AWS SES service to be able to send emails.

         "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
              "Action": [
              "Effect": "Allow",
              "Resource": {
                "Fn::Sub": [
                    "region": {
                      "Ref": "AWS::Region"
                    "account": {
                      "Ref": "AWS::AccountId"
Enter fullscreen mode Exit fullscreen mode

7. To save changes on the cloud, run amplify push.

Step 5: Using generated UI Contact by Amplify Studio

1. The command amplify pull executed in Step 4 has synced the UI components from Amplify Studio and saved them locally. You can run this command again if necessary.

Amplify Pull

2. Let's start by creating a client component that will wrap the Theme provider from Amplify Studio.

'use client';

import React, { ReactNode } from 'react';
import { Amplify } from 'aws-amplify';
import awsconfig from '@/src/aws-exports';
import { ThemeProvider, defaultDarkModeOverride } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

export default function AmplifyUITheme(props: {children: ReactNode}){

  const theme = {
    name: 'my-theme',
    overrides: [defaultDarkModeOverride],

  return (
    <ThemeProvider theme={theme} colorMode="system" >
Enter fullscreen mode Exit fullscreen mode

3. Then create another [client component](

contact.tsx) that will call the ContactFormCreateForm generated by Amplify and wrap it with the AmplifyUITheme component.

import ContactFormCreateForm from '@/src/ui-components/ContactFormCreateForm';
import AmplifyUITheme from './amplifyuitheme';
       onSuccess={() => setShowModal(false)}
Enter fullscreen mode Exit fullscreen mode

4. Optionally, you can also add a Modal component and use useState and useEffect to trigger the modal.

  const [showModal, setShowModal] = useState(false)

  useEffect(() => {
    const onKeyPress = (e: KeyboardEvent) => {
      if (e.key === "Escape") setShowModal(false);

    window.addEventListener("keydown", onKeyPress);
    return () => window.removeEventListener("keydown", onKeyPress);

    <button onClick={() => setShowModal(true)} >
      Contact me
    {showModal ? (

Enter fullscreen mode Exit fullscreen mode

Note: For this, we have used one of the best, but at the same time easy to use, modal components by another author. You can check his blog here.

Congratulations! You have successfully created a contact form using AWS SES, AWS Amplify Studio, and AWS Amplify, and deployed it to a Next.js app hosted on GitHub with fully automated deployment.

The final result will look something like this:

Final Contact


In this tutorial, we walked through the process of creating a contact form using AWS SES, AWS Amplify Studio, and NodeJS Lambda. We started by setting up AWS SES and hosting a Next.js project with AWS Amplify. Then, we created a data model using AWS Amplify Studio and set up a Lambda Node.js trigger to handle the form submissions and send emails using AWS SES.

We also utilized the UI components generated by Amplify Studio to create a user-friendly contact form interface. Finally, we deployed the Next.js app to GitHub with automated deployment.

Feel free to customize and enhance the contact form and the overall application according to your specific requirements. Happy coding!

Happy coding!


Top comments (0)