Being able to run server-side tasks without having to manage servers allows you to worry less about infrastructure and scalability, and focus more on the application itself. But how can you run server-side tasks without a server? Well, there is a server that runs these tasks. But you don’t manage that server! Cloud providers like AWS, GCP, Azure etc. take care of the allocation and provisioning of the servers dynamically. Additionally, Function as a Service (FaaS) is a concept that allows developers to make use of server-less computing via functions. Interestingly, server-side code is run inside containers that are triggered using events. Basically, all you have to do is deploy a function on the cloud that can be run independently by a request from your application/client without having to maintain a complete REST server and worry about scalability. These functions are often referred to as Lambda Functions. It is important to note, however, that everything with a server-less architecture is stateless.

Why Netlify?

Many FaaS like AWS Lambda are very complicated to set up and are well suited for large scale applications. Netlify uses Lambda functions powered by AWS, but simplifies and automates most of the process for us. The ease in setting up Lambda functions, provided by Netlify, opens a world of possibilities for us.

Overview

We will a build a server-less web application that will allow users to send custom emails using the Sendgrid API. Exposing our API Key to the client is a security concern. However, instead of having to setup and manage a full fledge backend server to hide the application logic from the client, we will use Lambda functions to make requests to the Sendgrid API to send emails. We will use Vanilla Javascript with HTML and CSS to setup our client and use NodeJS to setup our Lambda functions. After testing our Lambda functions locally, we will deploy them with our client on Netlify. We will also setup a custom domain for our server-less application with a free SSL certificate.

Create Sendgrid Account and Create an API Key

Note that if you already have a Sendgrid Account and an API Key, feel free to skip to Git setup.

You can create your free Sendgrid Account here.

Create API Key

After successfully logging in, go to the API Keys section under the settings option on the sidebar. Choose the Create API Key option on the top right.

Create Sendgrid API Key

Give your API Key a name and allow Full Access. Then choose Create & View.

Your API Key will then be displayed. Don’t forget to copy and save it somewhere. We will use it later when we configure our lambda functions to send emails.

Create Local Git Repo and Remote Git Repo on Github

After creating a repository on Github, run the following commands on your terminal in a separate folder,

git init

touch README.md

touch .gitignore

echo node_modules > .gitignore

git add README.md .gitignore

git commit -m "first commit"

git remote add origin YOUR_GITHUB_REPO_HTTPS_URL

git push -u origin master

We create a local repo, create a README.md file, create a .gitignore file to ignore the node modules folder that we will create after we setup our NodeJS project, add and commit our changes, and then push to our remote repository on Github.

NodeJS Setup

In the same folder, run npm init to setup your NodeJS project.

Project Dependencies

We will use a set of dependencies with NodeJS to configure our Lambda functions. Run the following command in the terminal from your directory,

npm i netlify-lambda @sendgrid/mail

netlify-lambda is a command line tool that will help us build and serve our lambda functions. You can checkout its documentation here. Moreover, @sendgrid/mail package will allow us to use the Sendgrid API to send emails.

Setup serve and build scripts in package.json

Replace the existing scripts in package.json with the following scripts so that we can serve and build our lambda functions,

"lambda-serve": "netlify-lambda serve functions"

"lambda-build": "netlify-lambda build functions"

package.json

Note that ‘functions’ is the name of the folder in our root folder that will contain the lambda functions.

Setup Lambda Functions

Run the following command in the root directory of your project from your terminal,

mkdir functions

As mentioned earlier, functions is the folder that will contain our lambda functions and each file inside the folder will contain code for an independent stateless lambda function.

Setup netlify.toml file

We also need the netlify.toml file in the root directory of our project.

netlify.toml

Note that this is done according to the Netlify Documentation. The functions variable value is set to the name of the build folder which in our case is named as lambda.

Quick Overview of how Netlify Lambda Functions Work

The following is how each function is formatted,

exports.handler = function(event, context, callback) {

// your server-side code....



//return successful (no error) response with body "Hello, World"

callback(null, {

statusCode: 200,

body: "Hello, World"

});

}

Each JS file that holds the lambda function must export a handler as above. Netlify provides the event and context parameters when the serverless function is invoked. However, we provide the optional callback parameter.

The event object is received by the function when the server-less endpoint is invoked. Information about the context of the application when the call was invoked, for instance a JSON Web Token (JWT) containing user data, is contained in the context parameter.

The callback is used to return a response to the event triggered, which can either be an error or a successful response object. The callback contains two parameters. The first parameter contains the error object if any otherwise null, and the second parameter contains the response object.

To learn more, I recommend you to look at the Netlify Documentation.

Setup Lambda Function to send emails

We will make a file sendEmail.js inside the functions folder which configures our lambda function that will send emails by communicating with the Sendgrid API when triggered by the client.

touch ./functions/sendEmail.js

We will then use same structure to define our lambda function as explained in the overview above. Since we will be sending an email using the email address and text provided by the user in the body of the event, we know that it will be a POST request.

Error Checking to only serve POST requests

First of all, we need to add some error checking to make sure our function only serves events with POST requests. The following is what our function will look like,

You can test this lambda function by running the following command from your project directory on your terminal,

npm run lambda-serve

This will create a build folder named lambda in the project’s root directory which will contain the build version of our lambda function. Also, this command allows us to serve our lambda functions on port 9000. Therefore, if we make a POST request to localhost:9000/sendEmail we will get a successful response. Also, due to our added error checking, our function will only be triggered by a POST request. You can use PostMan to test the function as follows,

Successful POST request

Unsuccessful GET request

Integrate Sendgrid API with Lambda Function

We will now import the sendgrid npm package we installed earlier. We will also configure our function to accept an event with the following body,

{

"to": TO_EMAIL_ADDRESS,

"subject": SUBJECT_OF_EMAIL,

"message": EMAIL_BODY

}

Note that error checking and input validation is beyond the scope of this tutorial so we will assume that the event is always triggered with a valid body input.

Also note that for the sake of this tutorial, we will use test@example.com as the from email address. The email object that we create in our lambda function will contain the to email address, the from email address, the subject and the message. Don’t forget to parse the incoming data from the event body using JSON.parse() and convert JS objects in the response to JSON strings using JSON.stringify().

Additionally, we need to add the following header to our function callback calls to make sure we do not face problems with CORS when we test our lambda function with our client,

//to enable cors on local development when we test our client headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept" }

The following is what our lambda function will look like,

Testing with PostMan

As discussed earlier we will send a POST request to localhost:9000/sendEmail

However, now we will pass a body to the request which the event will contain when the function is triggered. We will pass in raw JSON data to our request from PostMan as follows,

We receive the following JSON response on success,

{"result": "success"}

And if your inputs are valid, you should see the email in your inbox with the correct sender email address, subject and message body.

Client Side

As mentioned earlier we will use Vanilla Javascript to build our client. Also, we will use Twitter Bootstrap 4 to style our markup.

Setup HTML File

Create an HTML file in your project’s root directory and name it index.html.

Don’t forget to add the Bootstrap 4 CDN in your HTML file’s header.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />

The complete markup below should look very straight forward to you. Everything inside the body is wrapped in a bootstrap container component. Inside the container there are two rows each with a full size 12 width column. The first column contains an h1 tag and the second column contains the form. I have also added a few bootstrap classes to do some styling on the form. Feel free to style it your own way. After the form is a p tag which will contain the form submission feedback returned by our lambda function upon submission. Some elements have been assigned an id which will be useful in the JS file. Don’t forget to add a script tag at the end of the body to link the Javascript with the Markup.

<script src=”./js/main.js”></script>

The final index.html file looks as follows,

Setup Javascript File

Create a new folder in the root directory and name it js. Also, create a new Javascript file inside the js folder and name it main.js.

The JS file should also look very straight forward.

First of all, our JS file contains a URL constant assigned as http://localhost:9000/sendEmail . Note that we will change this URL before we deploy our server-less application on Netlify.

We also have an asynchronous function sendEmail(url, data) which uses the fetch API to make a POST request to the given URL and returns a promise.

Furthermore, we also select our form element and other relevant elements to submit our data and show relevant server-side feedback.

Test the Client

After testing the client with various valid inputs, I am convinced that our client and the lambda function are working and the emails are getting delivered. Time to Deploy!

Deploy Serverless Application on Netlify

Create Netlify Account

If you haven’t done so yet, you can create a free account here. Note that we will use our Github repository to deploy on Netlify.

Add functions folder to .gitignore

Since we will only deploy our build folder which is named lambda, we can also add the functions folder to the .gitignore file. This is what our .gitignore file should look like,

node_modules functions

Remove API Keys from the functions folder

We want to be able to access our API keys from the environment variables that we will configure from our Netlify Dashboard. Change the line where you set your API Keys to the following,

sgMail.setApiKey(process.env.API_KEY);

Change Client Side URL/Endpoint

In the file main.js, we used http://localhost:9000/sendEmail as our URL. This was only to test our lambda function locally. We must change it to the following before deployment,

/.netlify/functions/sendEmail

Push to Github

git add . git commit -m "Ready to Deploy" git push -u origin master

Netlify Dashboard

Choose the New site from Git option from your dashboard.

Choose Github as your Git provider.

Search and select your repository.

Branch to deploy: master

Under Advanced Build Settings, add your Sendgrid API Key and choose Deploy Site.

Netlify will also generate a subdomain under netlify.com for our application after deployment.

Netlify will manage the servers that run our lambda functions and we will not have to worry about scalability. Oh Yeah!

Custom Domain and SSL

I personally prefer using NameCheap as my domain registrar. You can also use this link to get Exclusive: up to 80% off on top domains with free Whois privacy!

However, you can use any registrar to follow along this guide.

Add Custom Domain to Netlify App

Choose Domain Settings from your deployed application’s dashboard.

Choose Add Custom Domain.

Type your custom domain name and choose Verify.

Choose Check DNS configuration.

To Verify our DNS, we will need to add records to our domain DNS.

CName Record: pointing www to distracted-shaw-9335f7.netlify.com.

to A Record : pointing @ to 104.198.14.52

Note that the values where www and @ (root domain) point towards might be different for your domain.

Configure Domain Registrar

As mentioned earlier, I personally prefer using NameCheap as my domain registrar. If you are using Namecheap, you can use this link to access their latest promotional offers. However, you can use any registrar to follow along this guide.

Now we need to add the CName and A records to our domain.

On your NameCheap dashboard, choose Manage for the appropriate domain.

Choose Advanced DNS.

Add your CName and A records and save changes.

Note that changes might take up to 48 Hours to propogate. However, this usually takes up to 5–10 minutes.

You should now be able to see on your Netlify’s domain settings that the DNS configuration has been verified and should be able to access your application using your custom domain name!

However, we still need to configure our free SSL certificate provided by Netlify.

On the domain settings page, scroll down and choose Verify DNS configuration under the HTTPS section.

Conclusion

It is important to note that we have only scratched the surface in this tutorial and there is a lot more that server-less architecture has to offer! This is the link to the Github repository with the complete code of our application.

If you have any questions, feel free to leave a comment. Also, if this helped you, please like and share it with others. I publish articles related to web development regularly. Consider entering your email here to stay up to date with articles and tutorials related to web development. You can also find out more about what I do at abdullahsumsum.com