In this tutorial, We will build a book library in nextjs and dynamodb as the database which will be connected with aws lambda and api gateway. You can see the demo of the in the video below the title in this page.
We will have three pages in the app
home page which shows all the books we have in the database.
add page to add a new book in the database.
and a id page where we can view, edit and delete the book we have selected.
Workflow of the App:
First lets look at data flow in our app:
A request will be made from server action in nextjs to the api gateway.
The api gateway will trigger the Lambda function.
Based on the type of request the Lambda function will do the crud operation in the dynamodb.
The way we will build the app:
First we will create a nextjs app and build our ui.
Then we will create our table NextjsBookTable in the dynamodb
Then we will create the Lambda function and add the required the code to do the crud operations.
And we will create the API Gateway. then, create the routes we need and attach them to the Lambda function.
And Finally we will write the server actions in Nextjs to communicate with the API Gateway.
Step 1: Setting up Nextjs:
First create a basic nextjs app using the following command.
npx create-next-app@latest dynamo-booklib
Use the following options.
Once created, open the project in vs code and we need to change the default code provided by nextjs.
Remove all the code in global.css except the first three tailwind css.
Now we need to add our colors in the tailwind.config.ts .
In layout.tsx lets add the background color and the text color of the app.
In page.tsx of app directory lets remove the default template.
Now lets create a add page which we will use to create a book, Create a add folder in app directory and create a page.tsx.
lets create a id page which we will use to view, edit and delete a book, Create a folder named [id] in the app directory.
Step 2: Creating a Header Component:
Lets create a components folder in the parent directory. First lets create a Header Component that we can use in all the pages. It is a simple header with a title and two nav links, one is for the home page and another is for the add page.
Step 3: Creating a BookCard Component:
Now lets create a BookCard component which showcase a single book.
Step 4: Creating Table in DynamoDB
Once you go login into your aws console click on create table.
Enter your table and enter id in the Partition Key field with Number as its datatype, scroll down and click create table.
After few seconds your table will be created and we can move on to the lambda function.
Step 5: Creating Lambda Function
Once you go into your lambda dashboard, click create function.
Give a name to your lambda function and toggle the change default execution role and select "create a new role from AWS policy templates" as below.
Give a Role name and make sure to select "Simple microservice permissions" in policy templates, this give the lambda function permission to access the table in dynamodb and click create function.
In your lambda function you can see the code editor below, In that add the code given below and change the tablename to your table's name and make sure that you have clicked 'deploy' once you pasted the code.
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
DynamoDBDocumentClient,
ScanCommand,
PutCommand,
GetCommand,
DeleteCommand,
} from "@aws-sdk/lib-dynamodb";
const client = new DynamoDBClient({});
const dynamo = DynamoDBDocumentClient.from(client);
const tablename = "booksLibrary";
const getBook = async (id) => {
const result = await dynamo.send(
new GetCommand({
TableName: tablename,
Key: { id: Number(id) },
})
);
return result.Item || { message: "not found" };
};
const getAllBooks = async () => {
const result = await dynamo.send(
new ScanCommand({
TableName: tablename,
})
);
return result.Items;
};
const putBook = async (book) => {
await dynamo.send(
new PutCommand({
TableName: tablename,
Item: {
id: Number(book.id),
price: book.price,
author: book.author,
description: book.description,
title: book.title,
},
})
);
return `PUT book ${book.id}`;
};
const deleteBook = async (id) => {
await dynamo.send(
new DeleteCommand({
TableName: tablename,
Key: { id: Number(id) },
})
);
return `Deleted Book ${id}`;
};
export const handler = async (event) => {
let body;
let statusCode = 200;
const headers = {
"Content-Type": "application/json",
};
try {
switch (event.routeKey) {
case "GET /books/{id}":
body = await getBook(event.pathParameters.id);
break;
case "GET /books":
body = await getAllBooks();
break;
case "PUT /books":
const data = JSON.parse(event.body);
body = await putBook(data);
break;
case "DELETE /books/{id}":
body = await deleteBook(event.pathParameters.id);
break;
default:
throw new Error(
`unSupported route: ${event.routeKey}`
);
}
} catch (error) {
statusCode = 400;
body = error.message;
} finally {
body = JSON.stringify(body);
}
return {
statusCode,
body,
headers,
};
};
The handler function you see at the last part of the code is the entry point in our lambda function. Then it will call the required function based on the request we have made using switch statement and returns the data.
We have four functions, getBook function will get id as a parameter and fetches the book in our table and returns that book.
getAllBooks function will return all the books present in our table.
putBook is used to create a new book inside table .i.e database.
deleteBook will delete the book based on the provided id.
If you want to test lambda function, you can see how in my video that i have given at the top of the post.
Again, if you modify any part of the code, make sure that you have deployed it by clicking the deploy button. Now, we can move on to creating the api gateway.
Step 6: Creating Http API Gateway
Open api gateway in aws and click on create API.
Click Build in HTTP API.
Give an API name and click next.
click next in the configure routes since we will add it later and click next in define stages as well. the ui will look something like below and click create.
Once created click on create in the routes page to create a new route.
Now select get and add books after the '/' and click create.
In the same create three more routes as below
GET /books/{id}
PUT /books
DELETE /books/{id}
Once you added the routes it will look like this.
Now we need to add an integration to these routes, For that go to integration. You can see it in the sidebar and go to manage integrations and click create.
Now select the route in the drop down and select "Lambda function" in the integration type and select the lambda function you have created in the Lambda function and scoll down and click Create.
Now if you go to integrations again, you can see "AWS Lambda" to the route we have added.
Now that we have created the integration we can just attach it to the other routes. Just click on a route and select your integration in the "Choose an existing integration" and click attack integration.
Now, repeat the above step again and attach integration to the other two routes as well.
Now we have created our api gateway completely. Click on the API: in the sidebar and copy the Default endpoint which will be the url of your api.
Now to check paste your url in the browser with /books at the end like API_URL/books. You will be able to see an empty array []. which means our api gateways works and since we dont have any data in dynamodb we are receiving an empty array.
Keep this url secret, dont share it online or anywhere public. since we have not added any authentication anyone can access the data. so as long as you dont share the api url you are safe.
you can add authentication with iam or roles or many other options,But i am going to stick with basics and not add authentication, so that we can learn the functionality first.
Step 7: Creating a type for Book:
lets create a type.ts page within the parent directory and add our type.
Step 8: Adding env variable:
create a .env.local file in the parent directory and add your api url in it.
Step 9: Creating Server Actions:
Let's create a folder named actions.
We will have two actions file one with "server-only" which can be called only in the server components. and another file with "use server" which calls the function in the "server-only" action file.
lets create a data.ts in the actions directory.
Now, lets create a actions.ts page in the actions directory
Step 10: Creating the home page
Step 12: Creating add page
Step 12: Creating the [id] page:
Summary:
Building this Book Library app with Next.js 14, AWS DynamoDB, AWS Lambda and AWS API Gateway has given us a solid foundation for creating full-stack apps. Using Next.js server actions and AWS, we can manage data smoothly and scale our app easily. I hope this guide helps you understand the basics and encourages you to try out your own projects!