Having a contact form always works better than just displaying an email address on our website. A contact form gives our visitors an easy way to get in touch with us. In this post, we will go through a simple way to set up our own in using and API. This post will also walk us through deploying it serverless with Now. React Nodemailer Express Zeit What this app will do By the end of this tutorial, you will have a contact form on your website that will bring the message straight to your inbox. GIFs from Gip hy Tools this app will use — (for hosting code. It is also required to deploy with Zeit later) GitHub — (for using JS packages like create-react-app) Npm and (as our API will be built in Express) Node JS Express JS ( for bootstrapping a standard React application and setting up our form) React JS create-react-app (for submission of form data to our remote API) Axios (to deploy our app serverless) Zeit Now Steps 1. Getting things ready We start by creating two repos, one to host our React form and another for Node API. We could also do it in a single repo, but we are using two for better maintainability. GitHub repos — GitHub Download the latest version of node.js from the . In this post we are using version 11.7.0. Node comes with npm. To make sure node and npm are installed, check their versions using the following commands on the terminal: Node & npm — link node -v v11 npm -v // For node version .7 .0 //For npm version 6.4 .1 We’re using for our React application where we will build our form. Install create-react-app globally and generate our React app using the following commands: React — create-react-app npm install create-react-app -g create-react-app my-app && cd my-app && npm start //Install create-react-app globally //Generate a new react app called my-app 2. The Form Let’s get started with setting up a component that returns an HTML form. We’re using classes for style in the code below, so they are optional You can use your own CSS classes as well. Bootstrap < =" " ={ (e) => this.formSubmit(e)}> < =" " =" "> </ > < ={e => this.setState({ : e.target.value})} =" " =" " =" " =" " ={this.state.message} /> < =" " =" "> </ > < ={e => this.setState({ : e.target.value})} =" " =" " =" " =" " ={this.state.name}/> < =" " =" "> </ > < ={(e) => this.setState({ : e.target.value})} =" " =" " =" " =" @ . " required value={ } /> < =" "> < =" " =" ">{ this.state.buttonText }</ > </ > </ > form className contact-form onSubmit label class message htmlFor message-input Your Message label textarea onChange message name message class message-input type text placeholder Please write your message here value required label class message-name htmlFor message-name Your Name label input onChange name name name class message-name type text placeholder Your Name value label class message-email htmlFor message-email Your Email label input onChange email name email class message-email type email placeholder your email com this .state .email div className button--container button type submit className button button-primary button div form Here, each input has an handler corresponding to a specific variable in our component’s state. So, when the input changes, the state gets updated as well. The form itself has an handler that calls the function which handles our API calls. onChange onSubmit formSubmit We will have a look at the function, but before that, let’s install axios (which we will be using in the function) to make HTTP request to the API. npm install axios --save //Install axios Setting up our component src/App.js: , { } from t'; axios from s'; { state = { name: '', message: '', email: '', sent: , buttonText: ' } render() { ( ); } } export ; import React Component 'reac import 'axio class Contact extends Component false 'Send Message return //Our form goes here default Contact Now, we add the functions to handle form submission in our component. formSubmit = { e.preventDefault() .setState({ : }) data = { : .state.name, : .state.email, : .state.message } axios.post( , data) .then( { .setState({ : }, .resetForm()) }) .catch( { .log( ) }) } ( ) => e this buttonText '...sending' let name this email this message this 'API_URI' => res this sent true this => () console 'Message not sent' The as the name suggests prevents the default action of the form, which would’ve caused a page reload. While the message is being sent, the button text changes to “…Sending”, and makes the API call. preventDefault() function (on line 2), , axios Note: “API_URI”(line 14) is the uri of the endpoint of our API which will be discussed in the deployment section of this post(Step 4). If everything goes right, the is called, which we haven’t defined yet. So let’s define the reset function that will reset our form fields and update our button label: resetForm resetForm = { .setState({ : , : , : , : }) } => () this name '' message '' email '' buttonText 'Message Sent' 3. API Now, we need something to transport our form inputs to the API, so we set up the nodemailer, config file and route. But before that, we need to setup in our Node API repo: Express.js //Initialize npm init //Install other npm install body-parser nodemailer cors -- express and dependencies express save Now we need to make a small change in our package.json file. Find “scripts” and add the following “start” line to it: : { : } "scripts" "start" "node ." Now, in our directory we create an index.js file with the following code: express = ( ); bodyParser = ( ); nodemailer = ( ); cors = ( ); app = express(); port = ; app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: })); app.use(cors()); app.listen(port, { .log( ); }); app.get( , { res.send( ); }) app.post( , { data = req.body; smtpTransport = nodemailer.createTransport({ service: , port: , auth: { user: , pass: } }); mailOptions = { : data.email, to: , subject: , html: }; smtpTransport.sendMail(mailOptions, { (error) { res.send(error) } { res.send( ) } smtpTransport.close(); }); }) const require 'express' const require 'body-parser' const require 'nodemailer' const require 'cors' const const 4444 true => () console 'We are live on port 4444' '/' ( ) => req, res 'Welcome to my api' '/api/v1' ( ) => req,res var var 'Gmail' 465 'USERNAME' 'PASSWORD' var from 'ENTER_YOUR_EMAIL' 'ENTER_YOUR_SUBJECT' `<p> </p> <p> </p> <p> </p>` ${data.name} ${data.email} ${data.message} ( ) => error, response if else 'Success' Important Note : Since we are working on the development version, the credentials will be exposed on GitHub , so make sure your repo is private or use a test email address for development version. Later in production, you can make use of the Zeit environment variables to store credentials safely. We have installed body-parser to process the form data, and CORS to allow cross-origin requests. We have setup a Nodemailer SMTP Transport and our route that will receive the data from our React form and send an email to the destination email address that we specify. 4. Deploy Finally! with all that done it’s time to deploy our app. We’re using Zeit Now for deployment, you can choose any other service that you like. (GIF from ) Giphy Start by creating an account on . Login and head over to “Now” from the top navigation. Connect your GitHub account and add the two repos that we just created. Now, we go back to our code and add an empty now.json file in both the repos. Zeit It’s now time to push our codes to the respective github repos. Now we create a new branch in both repos and work with those because we will need to create Pull Request for Zeit now to run deployment. // branch git checkout -b -branch create and change to new new Now we add some content to the now.json files. For our React repo we will use the following content on our now.json: { : , : , : [ { : , : } ], : [ { : , : }, { : , : }, { : , : }, { : , : }, { : , : { : }, : }, { : , : }, { : , : } ] } "version" 2 "name" "create-react-app" "builds" "src" "package.json" "use" "@now/static-build" "routes" "src" "^/static/(.*)" "dest" "/static/$1" "src" "^/favicon.ico" "dest" "/favicon.ico" "src" "^/asset-manifest.json" "dest" "/asset-manifest.json" "src" "^/manifest.json" "dest" "/manifest.json" "src" "^/service-worker.js" "headers" "cache-control" "s-maxage=0" "dest" "/service-worker.js" "src" "^/precache-manifest.(.*)" "dest" "/precache-manifest.$1" "src" "^/(.*)" "dest" "/index.html" For our Node repo, we will use the following content on now.json: { : , : , : [ { : , : } ], : [ { : , : } ] } "version" 2 "name" "nodejs-express" "builds" "src" "index.js" "use" "@now/node-server" "routes" "src" "/(.*)" "dest" "app.js" Note: More examples for Zeit Now configurations can be found here . Finally, we make a small change in our package.json in our React repo. Find “scripts” and add the “now-build” line to it: { : { ... : } } "scripts" "now-build" "react-scripts build && mv build dist" Now, we push the codes to their respective Github repos(new-branch) and then create a Pull Request in each. Zeit Now will immediately deploy the app recognizing the now.json files. You can view the app URL by clicking “Show all checks” and then “details” in the Pull Request summary. Lastly, . Now our form should successfully deliver emails. be sure to copy the link and replace API_URI in the App.js file in React app Thanks for reading! Happy Coding! Illustration by 🥳 Akriti Bhusal