Build a Portfolio Website Using AWS Serverless

Pravash Raj Upreti
4 min readMay 21, 2024

--

Serverless Architecture

Building a portfolio website using AWS serverless services is a powerful way to ensure scalability, reliability, and cost-efficiency. In this blog, we’ll walk through setting up a React application hosted on AWS, using various AWS services to create a robust, full-stack application. We’ll cover everything from hosting the static site to handling contact form submissions, setting up a custom domain, and ensuring our API is secure and scalable.

Step 1: Create a React App and Upload to S3

First, we’ll create a React application using Create React App:

npx create-react-app my-portfolio
cd my-portfolio
npm run build

After building the React app, we’ll upload the build directory to an S3 bucket:

1. Go to the AWS Management Console and navigate to S3.
2. Create a new bucket (e.g., `my-portfolio-bucket`).
3. Enable static website hosting in the bucket properties.
4. Upload the contents of the `build` folder to the bucket.

Step 2: Deploy the Static Website with CloudFront

Next, we’ll use CloudFront to distribute our static website globally for low latency and high availability:

1. In the AWS Management Console, go to CloudFront and create a new distribution.
2. Set the origin to the S3 bucket URL.
3. Configure the default cache behavior to allow GET, HEAD, OPTIONS methods.
4. Once the distribution is created, note the CloudFront domain name.

Step 3: Set Up Route 53 and Purchase a Domain

To associate a custom domain with our CloudFront distribution, we’ll use Route 53:

1. Go to Route 53 in the AWS Management Console and purchase a new domain.
2. Create a new hosted zone for the domain.
3. Add an alias record pointing to the CloudFront distribution.

Step 4: Create an API Gateway

To handle backend requests, we’ll set up an API Gateway:

1. In the AWS Management Console, navigate to API Gateway and create a new REST API.
2. Create a new resource (e.g., `/contact`) and a POST method for handling form submissions.
3. Integrate the POST method with a Lambda function.

Step 5: Define Usage Limits for the API

To prevent unexpected costs and potential attacks, we’ll define usage limits:

1. In the API Gateway, select your API and navigate to Usage Plans.
2. Create a new usage plan, set throttling and quota limits.
3. Associate the usage plan with an API key.

Step 6: Create a Lambda Function

We’ll create a Lambda function to handle requests from our contact form and store the data in DynamoDB:

1. Go to the Lambda console and create a new function.
2. Set up the function with the following code:

const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {
const { name, email, message } = JSON.parse(event.body);
const params = {
TableName: 'ContactMessages',
Item: {
id: Date.now().toString(),
name,
email,
message,
},
};
await dynamoDb.put(params).promise();
return {
statusCode: 200,
body: JSON.stringify({ message: 'Message received' }),
};
};

3. Configure the Lambda function with the necessary permissions to access DynamoDB.

Step 7: Use DynamoDB for Persistence

Create a DynamoDB table to store contact form submissions:

1. In the DynamoDB console, create a new table named `ContactMessages`.
2. Set `id` as the primary key.

Step 8: Set Up SES for Email Notifications

To send email notifications when a contact form is submitted, we’ll use Amazon SES:

1. Verify your domain and email address in SES.
2. Request production access to SES by submitting a request in the SES console.
3. In the Lambda function, integrate SES to send an email upon receiving a new contact form submission.

const ses = new AWS.SES();
const emailParams = {
Source: 'your-email@your-domain.com',
Destination: { ToAddresses: ['recipient@example.com'] },
Message: {
Subject: { Data: 'New Contact Form Submission' },
Body: {
Text: { Data: `Name: ${name}\nEmail: ${email}\nMessage: ${message}` },
},
},
};
await ses.sendEmail(emailParams).promise();

Step 9: Create SQS for Asynchronous Processing

To handle form submissions asynchronously, we’ll use SQS:

1. Create a new SQS queue.
2. Modify the Lambda function to send form data to the SQS queue instead of directly storing it in DynamoDB.
3. Create another Lambda function to process the queue and store data in DynamoDB.

const sqs = new AWS.SQS();
const sqsParams = {
QueueUrl: 'SQS_QUEUE_URL',
MessageBody: JSON.stringify({ name, email, message }),
};
await sqs.sendMessage(sqsParams).promise();

Pricing Calculation

Here’s a basic estimation of costs:

- S3: ~$0.023 per GB stored.
- CloudFront: ~$0.085 per GB transferred.
- Route 53: $0.50 per hosted zone per month + domain registration fee (~$12/year).
- API Gateway: ~$3.50 per million requests.
- Lambda: ~$0.20 per million requests + duration costs.
- DynamoDB: ~$1.25 per million write request units.
- SES: $0.10 per 1,000 emails.
- SQS: ~$0.40 per million requests.

Service Level Objective (SLO)

To calculate the SLO, we’ll consider uptime and response time. AWS services generally offer:

  • S3: 99.99% availability
  • CloudFront: 99.99% availability
  • API Gateway: 99.95% availability
  • Lambda: 99.95% availability
  • DynamoDB: 99.999% availability

Combining these, the overall SLO for the system can be estimated around 99.95%.

Security and Reliability

The architecture is highly secure and reliable due to:

  • Managed services with built-in security features.
  • API Gateway throttling and usage plans to prevent abuse.
  • IAM roles and policies to manage access controls.
  • Encrypted data storage in S3 and DynamoDB.
  • CloudFront and Route 53 ensuring low-latency access and DDoS protection.

Scalability

This architecture is inherently scalable:

  • S3, CloudFront, and DynamoDB automatically scale with demand.
  • Lambda functions scale out to handle increasing loads.
  • API Gateway and SQS handle high throughput.

With AWS serverless services, the infrastructure can seamlessly accommodate traffic spikes, ensuring consistent performance and reliability.

By following these steps, you’ll have a fully functional, serverless portfolio website that’s cost-efficient, scalable, and secure. AWS’s robust ecosystem provides all the tools necessary to build and maintain high-quality web applications.

--

--

Pravash Raj Upreti
Pravash Raj Upreti

No responses yet