Deploy Multi-page Gatsby Site to AWS Lambda Function

Deploying a multi-page Gatsby app to Lambda can be tricky, as you may find that the root URL works fine, while it breaks as soon as you click on some internal link trying to navigate to a different page within your app.

In this article, I will demonstrate how to deploy a multi-page Gatsby app to Lambda with the help of serverless, serverless-http and Express.js.

Create a Gatsby Site

For the demonstration purpose, I’ll use one of the Gatsby official starter — gatsby-starter-blog-theme. You can also use whatever Gatsby project you have at hand.

  1. Breate a Gatsby site with gatsby-starter-blog-theme:
# create a new Gatsby site using the blog theme starter
gatsby new my-themed-blog

2. Build a production version of this site:

# change directory into the newly created site
cd my-themed-blog/
#build a production-ready version of this site
gatsby build

Now you’ll find a public folder, in which it contains all the static files ready to serve.

Create a Node.js Project

Create an empty Node.js project by issuing following command:

# create a folder to hold the Node.js project
mkdir gatsby-lambda
# change current directory to this folder
cd gatsby-lambda
# create an empty Node.js project with default options
npm init -y

Install Express.js Dependency

Express.js is the de facto standard server framework for Node.js. In our case, it will help us to serve all the static files we built in the previous step.

npm i express

Install Serverless-http Dependency

Serverless-http allows us to wrap the express that we’ll create in a minute for serverless use.

npm i serverless-http

Now that we have all the dependencies we need for this project, we’ll work on the content part.

First, copy the public folder we built earlier to this Node.js project folder.

Then, create an index.js file under this Node.js project folder. In this index.js file, we’ll create an Express.js app to serve the static files in public folder and wrap it with serverless-http.

Install & Configure Serverless

Deploying serverless applications through AWS console UI is tedious. Thankfully we can use serverless module to help us do the heavy work.

To install serverless globally:

sudo npm i -g serverless

You may need to enter your password to issue this command.

Then we have to configure serverless to connect to AWS:

serverless config credentials --provider provider --key key --secret secret

If you have already installed AWS cli before and configured, you can probably skip above configuration (serverless will also prompt if ~/.aws/credentials already exists).

The minimum permissions you need to grant to the credential you supplied in configuration are (you can configure them in the user group policy settings through IAM console):

  1. AWSLambdaFullAccess
  2. IAMFullAccess
  3. AmazonAPIGatewayAdministrator
  4. AWSCloudFormationFullAccess

Create Serverless.yml

In order to tell serverless how we want to deploy this project to Lambda, we have to create a serverless.yml configuration file under the root directory of the Node.js project. Following is a working example for this demonstration:

In this configuration, I created two API endpoints: one is REST API endpoint; the other one is HTTP API endpoint. You can choose either or both base on the need of your project.

Deploy to Lambda

Now we can easily deploy the whole project to Lambda by issuing a single command:

serverless deploy

Now you should have a working multi-page Gatsby site deployed to Lambda!

Lesson Learned

The most noteworthy problem I met was mentioned in the beginning of this story: the root page works fine, while the browser returns following error whenever I click on some link that will navigate to another page within the Gatsby site.

"message": "Not Found"

While it works fine locally with express instead of wrapping with serverless, which means all the file structures and Express.js are working.

When inspecting the Network tab in Chrome console, I found all the files other than the index.html under public folder received 404 NOT FOUND error. Then I realized that all the file requests other than the index.html were blocked by API gateway. Hence the solution should be in the routing part of the API endpoint.

After some research and experiment, I finally came to the proxy resource path. As mentioned in the configuration console in API gateway:

You can add path parameters using brackets. For example, the resource path {username} represents a path parameter called ‘username’. Configuring {proxy+} as a proxy resource catches all requests to its sub-resources. For example, it works for a GET request to /foo. To handle requests to /, add a new ANY method on the / resource.

This is exactly what I need to make the multi-page Gatsby site work and it really works!

Read More

Amazon API Gateway — Set up a proxy integration with a proxy resource

Serverless.yml Reference



A lifelong learner who has enthusiasm for sharing knowledge; a developer who loves bringing ideas to life.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Wenhe Qi

A lifelong learner who has enthusiasm for sharing knowledge; a developer who loves bringing ideas to life.