Step-by-step tutorial for creating a Serverless backed React SPA on AWS

Hey guys, I put together a really comprehensive tutorial detailing how to build a CRUD Serverless API and hooking it up to a React SPA entirely on AWS. The API functions are in ES6 and authenticated with Cognito User Pool. It also shows you how to host your app on S3 and serve it out using CloudFront and Route 53. It is an end-to-end tutorial that shows the Serverless architecture in action. Initially, I was putting it together for myself but then I had a few other folks ask for it as well.

So take a look and let me know if I missed something that I should’ve covered -


This looks incredible! I need to set aside some time to go through it, but you’ve got all the right pieces in place. Nicely done!

Thanks Pete! Any advice would be appreciated.

Amazing tutorial!! Extremely useful to have all these technologies in one comprehensive tutorial.

Now that the core tutorial is completed, a couple advanced items that would be useful to add:

  1. federated authentication with Cognito (eg, Facebook, Google)

  2. using RDS (eg, MySQL) and Sequelize as the database (and ORM) as an alternative to DynamoDB. Granted DynamoDB is most appropriate for this simple demo, but RDS/Aurora is also used by many enterprise applications.

1 Like

Yes, definitely. Social login with Cognito has been highly requested. Will release a chapter on that soon.

Got it until the Add a Create Note API part. Tried to invoke, serverless webpack invoke --function create --path event.json but I get 500 error. I reviewed from the start and even used the cloned repository and just updated the details with my own but I can’t still get it working. Is there anywhere we could ask to get this all working?

Dorell, the 500 error most likely results from the DynamoDB call. If you open up dynamodb-lib.js and print out the error object inside the if block.

 if (error) {
    console.log(error); // Add this line

Run the invoke command again and let’s see what error it prints out. Btw, you can always talk to us through the live chat right on the tutorial page.

Frank - Thank you so much man. I’ve identified the error. In the Create a DynamoDB table, the fields userid and noteid are both lowercase, however, the code constructing the data to be inserted uses camelCase such as noteId and userId.

const params = {
    TableName: 'notes',
    Item: {
      userId:, // camelCase key
      noteId: uuid.v1(), // camelCase key
      content: data.content,
      attachment: data.attachment,
      createdAt: new Date().getTime(),

I think the tutorial part on that page should be updated since the code heavily uses the lowercase one.

Thanks once again, I can continue now. And oh, the chat tip might come handy.

Good point. Updated the tutorial.

Thanks Dorell !

Would it be possible to add testing examples in there as well?

This is great, thank you !!

1 Like

Do you mean adding unit tests to the handler functions?

I did indeed, although I guess tests for the React side of things would be nice too :slight_smile:

I’ve used Jest + Enzyme to test my React app, but I can’t get Jest to mock the AWS SDK at all :frowning:

Really amazing tutorial! Very clean and good writing. I ran into a few issues that were all my own doing. I think it would be great if there was a way to capture troubleshooting tips from people as they walk through it. On one of the e-learning sites (udacity, i think), they has a discussion thread for each topic or chapter so the students could leave notes for other students.

For example, one of my problems was bad indentation for the delete api in serverless.yml. I got the super helpful message “Cannot read property ‘handler’ of undefined”. Maybe ‘serverless-stack’ should just be a tag on StackOverflow.

Thanks for putting this all together. Super helpful.

Totally agree. Resources for both unit testing and integration testing are lacking. It’s definitely something we want to cover down the road.

While we figure out a more friendly way to do this, we opened a discussion thread for each chapter on the GitHub page.

Thanks @fanjie
I believe this framework is based on the idea that all routes (other then direct to index.html) will be directed to the index.html as 404 in the HTTP status. So for a logical SPA path like the browser would show the valid page looking very VALID and in all its creative love, but the http status would be 404? If that is correct, I think this would have adverse affects on SEO, no?

Seems like there is no golden bullet though. If you end up going SPA with no true webserver, you end up losing some HTTP status clarity.

I’ve thought about what it might look like to add an API Gateway and Lambda layer that could push all requests thru and let the Lambda handle the simple naked->www and single page redirects. But not sure what that would look like. I’d be willing to invest time to figuring it out if someone thought it would work.

Hi @iDVB, yeah this was a point that one of our readers brought up. The way we deal with this in the tutorial is by creating a custom error response to respond with a 200. You can read about it here - This responds to everything with a 200, so yeah there is no good solution currently.

Hi Frank

Amazing repo, i’m using it as the basis for my app. Would you think about adding social login to it? Would be great to see a clear example of how to integrate with Google and Facebook.

1 Like