Create AWS Serverless App
» Important Links
» What are we building?
In this, blog we will build a serverless web app using several AWS services.
We’ll be using a variety of AWS services to create a seamless, scalable, and highly available system.
To look at the demo, please visit the youtube video and look at the demo sectiion.
» Overview
Let me just give you a quick overview of what will happen when users access our contact form.
So user will interacts with our application through a web browser or a mobile app.
Amazon S3 - Then the user’s requests will first get directed to Amazon S3, where our static website or client-side code is hosted. S3 serves as a highly durable and scalable storage solution.
Amazon API Gateway - Next, the request is routed to the API Gateway. API Gateway manages the requests and triggers Lambda functions.
AWS Lambda- The API Gateway will trigger our AWS Lambda functions. Lambda executes our backend logic, storing and retrieving data from DynamoDB.
Amazon DynamoDB - For data storage, like storing user info, our Lambda function interacts with Amazon DynamoDB, it’s a fast and flexible NoSQL database service. It ensures low latency and scalability, making it ideal for our application’s needs.
AWS IAM (Identity and Access Management) - Then we have IAM plays a crucial role in securing our application. It manages access to AWS resources, ensuring that each service can only access what it needs to perform its function. This minimises security risks.
Amazon CloudWatch - Throughout this process, Amazon CloudWatch is monitoring our application. It provides actionable insights, collects and tracks metrics, and logs all activities, allowing us to maintain and optimise the system effectively.
» Folder Structure
Refer to GitHub Repository if you get confused somewhere. Link is provided above.
- /aws-serverless-app
- s3-static-site/
- index.html
- style.css
- script.js
- lambda-function/
- index.js
- package.json
» Create Static website
Let’s start by creating a static website. Create a new project directory and name it (aws-serverless-app) or call it whatever you want and inside it create a folder named: s3-static-site and navigate to this folder and then create five files: index.html, script.js, style.css, success.html, fail.html.
mkdir aws-serverless-app
cd aws-serverless-app
mkdir s3-static-site
cd s3-static-site
touch index.html
touch script.js
touch style.css
touch success.html
touch fail.html
Create another folder inside the main project and name it lambda-function and inside it create a file named index.js
mkdir lambda-function
cd lambda-function
touch index.js
Open this project in VS code and let’ s start by brining in the code for our static site.
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Contact Form for AWS</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<h1>Contact Form</h1>
<form id="contact-form">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="subject">Subject:</label>
<input type="text" id="subject" name="subject" required>
<label for="message">Message:</label>
<textarea id="message" name="message" rows="5" required></textarea>
<button type="submit">Submit</button>
</form>
</div>
<script src="script.js"></script>
</body>
</html>
We’ll start by creating our contact form in the index.html file.
Copy Paste the css code in style.css file.
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background-size: cover;
background-position: center;
background-color: rgb(46, 46, 46);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
width: 500px;
margin: 0 auto;
padding: 20px;
background-color: rgba(255, 255, 255, 0.932);
box-shadow: 0 0 20px rgba(255, 255, 255, 0.5);
border-radius: 10px;
}
h1,
p {
text-align: center;
}
.error {
color: red;
}
form label {
display: block;
margin-bottom: 8px;
}
form input,
form textarea {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
form button {
width: 100%;
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
form button:hover {
background-color: #0069d9;
}
Copy script.js: JavaScript for Form Handling.
document
.getElementById("contact-form")
.addEventListener("submit", function (event) {
event.preventDefault();
var name = document.getElementById("name").value.trim();
var email = document.getElementById("email").value.trim();
var subject = document.getElementById("subject").value.trim();
var message = document.getElementById("message").value.trim();
var emailRegex = /^\S+@\S+\.\S+$/;
if (!name || !email || !subject || !message || !emailRegex.test(email)) {
alert("Please fill in all fields with valid inputs.");
return;
}
var formData = {
name: name,
email: email,
subject: subject,
message: message,
};
submitForm(formData);
});
function submitForm(formData) {
fetch("https://kn2h2qbh8i.execute-api.ap-southeast-2.amazonaws.com/dev/submit", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
})
.then(function (response) {
if (response.ok) {
window.location.href = "success.html";
} else {
window.location.href = "fail.html";
}
})
.catch(function (error) {
console.error(error);
window.location.href = "fail.html";
});
}
Here’s how our backend processes the form submission:
The API Gateway receives the form data and triggers a Lambda function which we will create now.
The Lambda function will contain the logic to process the form data. And it will include storing the data in DynamoDB.
Create success.html file:
<!DOCTYPE html>
<html>
<head>
<title>Thank You</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<h1>Thank You!</h1>
<p>Your message has been submitted successfully.</p>
</div>
</body>
</html>
Create fail.html file:
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<h1 class="error">Error!</h1>
<p>Your message was not sent. Please Try Again.</p>
</div>
</body>
</html>
» AWS Lambda Function
Now we will focus on an AWS Lambda function that processes form submissions and stores the data in DynamoDB.
Open index.js file present in lambda-function directory:
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
const { v4: uuidv4 } = require('uuid');
exports.handler = async (event) => {
try {
console.log('Raw input data:', event);
const formData = {
name: event.name,
email: event.email,
subject: event.subject,
message: event.message,
};
const item = {
SubmissionId: generateUUID(),
...formData,
};
await storeFormData(item);
return {
statusCode: 200,
body: JSON.stringify({ message: 'Form submitted successfully' }),
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: JSON.stringify({ message: 'Error submitting the form' }),
};
}
};
async function storeFormData(item) {
const params = {
TableName: 'ContactFormEnteries',
Item: item,
};
await dynamodb.put(params).promise();
}
function generateUUID() {
return uuidv4();
}
Next open the terminal and navigate to the lambda directory and run the command: npm init -y and then install the aws-sdk package as a dependency.
npm init -y
npm i aws-sdk
This will allo Lambda function for interacting with DynamoDB and other services.
Okay, now once we are done with the code let’s work with AWS services.
» Create S3 bucket
Now let’s create a S3 bucket for static site: This bucket will be publicly accessible so that users can access our web application. Let’s get started!
Open your web browser and Navigate to the AWS Management Console and log in with your credentials.
In the AWS Management Console search bar, type “S3” and select “S3” from the dropdown list.
Click on “Create bucket”.
And Enter a unique name for your bucket so choose something specific to your project, I’ll go with s3-static-site-2.
And leave rest to default.
Create the Bucket: Next, Click the “Create bucket” button at the bottom of the page to finalize the creation of your S3 bucket.
Next we have to Upload our Website Files.
Click on our Bucket that we just created to open it.
Then Click on the “Upload” button.
Click “Add files” and select the HTML, CSS, and JavaScript files from our project. And then click on “Upload” to start the upload process.
Next we have to Set Bucket Policy for Public Access: By default, S3 buckets are private. Go to the “Permissions” tab of your bucket.
Scroll down to the “Bucket policy” section and click on “Edit” and uncheck “Block all public access”. Confirm the changes by checking the acknowledgment box.
And then we have to Add Bucket Policy:
Copy and paste the following policy, and replace YOUR_BUCKET_NAME
with the name of your bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<your-bucket>/*"
}
]
}
Then let’s Configure Bucket for Static Website Hosting:
Bucket Properties:
Go to the “Properties” tab of your bucket.
Scroll down to the “Static website hosting” section and click on it.
We have to Enable Static Website Hosting: So scroll down till Static website hosting section and click on edit
Select Enable and
Specify the index document that is our index.html
.
Specify an error document as fail.html
. This is optional you can just leave it as it is
Click “Save” to apply the settings.
Then we will have the url created for our static site.
Click and open the url and there we will have our static website up and running. But it wouldn’t take our data.
» Create Dynamo Table
Let’s start by Creating the DynamoDB Table
In the AWS Management Console search bar, type “DynamoDB” and select it from the dropdown list.
Then Create a New DynamoDB Table
Go to the tables section and Click on “Create table.
And Enter a unique name for your table. For example, ContactFormEnteries
.
Set the Partition key to SubmissionId
with the type String
. This will uniquely identify each form submission.
Leave rest to default.
Last, Click the “Create table” button to finalize the creation of your DynamoDB table.
» Create Lambda Function
Let’s now create lambda function. In console search for lambda and create a function, name it whatever you’d like to call it. I Will give it as lambda-function
Then we have to upload our lambda code.
So before that let’s open the index.js file present in lambda-function folder and replace its dynamodb table name with the name that we gave to our DB.
Open your terminal: Navigate to the directory where your Lambda function code is located. And run:
zip -r lambda.zip .
This command will create a deployment package called lambda.zip that contains all the files and directories needed for our Lambda function.
» S3 bucket for Lambda
Now we will have to create another S3 bucket to upload our lambda code.
So in serach type S3 and Create a new bucket and name it whatever you want and then let’s upload the zip file of our lambda code here.
Copy the S3 URI.
» Upload Lambda code
Next open lambda and click on upload from and select Amazon S3.
And then it will ask you to Paste the S3 uri link and click save.
» Test Lambda Code
Now let’s test our backend code. So for that we will create a test event. Open the lambda function you created.
Navigate to the test tab and click on create a new event and name anything for your event name.
And have a name, email, subject and a message json object.
And click on test button and you should get a successful message.
But it also says: an access error to DynamoDB since you haven’t created any role for the Lambda function to associate it with the database yet.
» Modify Permission for Lambda role
So let’s modify the permissions for lambda role.
Head back to the lambda service and open your function and then Go to the configuration tab and then click on this permission tab and click on role name.
It will open up another window.
And in there you will have this Add Permissions button click on it. Then from dropdown select Attach Policies
And Search for AmazonDynamoDBFullAccess
and select it. This policy allows full access to DynamoDB.
After that open lambda again and create another test to check if the data is saved in dynamodb. And I assure you that this time the data will be saved.
Paste this code and click on the test.
{
"name": "name",
"email": "[email protected]",
"subject": "test-for-lamda",
"message": "Should work"
}
» Set up API Gateway and deploy the endpoint URL
Now, we’re going to set up API Gateway to expose our Lambda function via a RESTful endpoint. This will allow our front-end application to submit form data to our Lambda function. We’ll go through the process of creating an API, configuring it, and deploying it to get a public endpoint URL.
We will create an API in API Gateway. So search for API gateway. Click on create API.
Select “Build” under the REST API option.
Then click on new api and Enter a name for your API, such as ContactFormAPI
.
Finally Click on “Create API” to finalize.
» Create Resource
Next go back to your API and click on Create a Resource
For Resource Name Enter submit
.
Click “Create Resource.”
Now next thing we have to do is Create a POST Method:

Select the /submit
resource.
Click on Create Method.
Choose POST
from the (/) dropdown list.
Select your “Lambda Function.”
Click Create Method Button.
» Enable CORS for API
Select the Enable CORS option. Check every boxes and provide our s3 static website URL.
» Deploy the API
Click on “Deploy API.”
Choose “[New Stage]” to create a new deployment stage.
Enter a name for your stage, such as dev
.
Click “Deploy.”
Now let’s Get the Endpoint URL that we will use it to make the request to it from the static website.
fter deploying, you will see a “Stage Editor” view.
Note the “Invoke URL” at the top. This is the URL endpoint for our API.
Grab this invoked url and let’s make a change in our script.js file present in our static site folder.
Remove the invoke url and replace with the url that we got and go back to s3 bucket and upload the file again.
Now we will enable cors on our S3 bucket. Enabling CORS allows our web application hosted in one domain to interact with resources in our S3 bucket that might be hosted in another domain, which is essential for accessing our static assets like JavaScript, CSS, and HTML files.
» CORS for Satic Site.
Find the bucket you created earlier for hosting your static website and click on its name to open the bucket details.
Click on the “Permissions” tab within your S3 bucket.
Scroll down to the “Cross-origin resource sharing (CORS)” section.
Click on “Edit” to modify the CORS settings.
Copy and paste the following CORS configuration into the editor:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"POST"
],
"AllowedOrigins": [
"http://your-static-site-url.amazonaws.com"
],
"ExposeHeaders": []
}
]
Click “Save changes” to apply the new CORS configuration.
» Test
Now test the app again.
Fill in the form and there you will be redirected to the success page.
And when you go to dynamodb and check for data. You will find the user data in there.
And that’s all for this blog. I hope you enjoyed it and found it useful. Also if you have any doubts please drop a message on our discord server. The link can be found below.
👉 And I’ll see you in next one, till then bye-bye and take care.