Introduction
This project involves building a full-stack web application using AWS Amplify. It features a simple React frontend with user authentication, a serverless function to handle user sign-ups, and a DynamoDB database for storing user emails. The application leverages AWS’s robust and scalable cloud services to deliver a seamless user experience, allowing users to sign up, log in, and store information securely.
Why Use AWS Amplify for This Project?
AWS Amplify simplifies the process of deploying full-stack web applications by providing ready-to-use backend services, including hosting, authentication, API management, and data storage. By using Amplify, you can focus on building the application’s functionality rather than managing infrastructure.
What You Will Learn
- Host: Build and deploy a React application on the AWS global content delivery network (CDN).
- Authenticate: Add authentication to your app to enable sign-in and sign-out functionality.
- Database: Integrate a real-time API, database, and a serverless function.
- Function: Implement a lambda function that is triggered when a user signs up to the App.
Tech Stack
This project uses the following services and technologies:
- AWS Amplify: Provides end-to-end services for hosting and managing the web application.
- AWS AppSync: Facilitates real-time API creation and management.
- AWS Lambda: Runs serverless functions for handling user data.
- Amazon DynamoDB: A NoSQL database for storing user emails.
- React: The frontend framework used to build the web application.
- Node.js & npm: For managing dependencies and running the React app.
- Git & GitHub: Version control and repository hosting.
Prerequisites
Before starting the project, ensure you have the following:
- Basic AWS Knowledge: Familiarity with services such as Amplify, Lambda, and DynamoDB.
- AWS CLI configured: With appropriate IAM permissions for managing AWS Amplify, Lambda, and DynamoDB.
- Node.js and npm: Installed locally for running and managing the React application.
- Git: For version control and integration with AWS Amplify.
Problem Statement or Use Case
Web applications today require features like user authentication, data storage, and API integration. Setting up and managing these services can be challenging, especially for scalability and real-time capabilities. Using AWS Amplify simplifies this by offering a fully managed backend that integrates seamlessly with the frontend.
Solution: This project provides a user sign-up and sign-in system with a backend that captures and stores user data. This setup is applicable to various real-world scenarios, from building social media platforms to e-commerce websites, where user management and data storage are essential.
Architecture Diagram
Step-by-Step Implementation
Tasks
This tutorial is divided into six tasks. You must complete each task in order before moving on to the next one:
- Create Web App: Deploy static resources for your web application using the AWS Amplify Console.
- Build Serverless Function: Build a serverless function using AWS Lambda.
- Create Data Table: Persist data in an Amazon DynamoDB table.
- Link Serverless Function to Web App: Deploy your serverless function with API Gateway.
- Add Interactivity to Web App: Modify your web app to invoke your API.
- Clean Up Resources: Clean up resources used in this tutorial.
You will be building this web application using the AWS Management Console accessible directly from your browser.
Task 1: Create a Web App
Overview
AWS Amplify offers a Git-based CI/CD workflow for building, deploying, and hosting single-page web applications or static sites with backends. When connected to a Git repository, Amplify determines the build settings for both the frontend framework and any configured backend resources and automatically deploys updates with every code commit.
In this task, you will start by creating a new React application and pushing it to a GitHub repository. You will then connect the repository to AWS Amplify web hosting and deploy it to a globally available content delivery network (CDN) hosted on an amplifyapp.com
domain.
Key Concepts
- React Application: React is a JavaScript library that enables developers to quickly build performant single-page applications.
- Git: Git is a version control system that allows developers to store files, maintain and update relationships between files and directories, and track versions and changes to the files.
Implementation
Step 1: Create a new React application
In a new terminal or command line window, run the following command to use Vite to create a React application:
npm create vite@latest profilesapp -- --template react
cd profilesapp
npm install
npm run dev
- In the terminal window, select and open the Local link to view the Vite + React application.
Step 2: Initialize a GitHub repository
In this step, you will create a GitHub repository and commit your code to the repository. You will need a GitHub account to complete this step; if you do not have an account, sign up here.
Note: If you have never used GitHub on your computer, follow these steps before continuing to allow connection to your account.
Sign in to GitHub at https://github.com/.
-
In the "Start a new repository" section, make the following selections:
- For Repository name, enter
profilesapp
, and choose the Public radio button. - Then select Create a new repository.
- For Repository name, enter
- Open a new terminal window, navigate to your project's root folder (
profilesapp
), and run the following commands to initialize Git and push the application to the new GitHub repository:
git init
git add .
git commit -m "first commit"
git remote add origin git@github.com:<your-username>/profilesapp.git
git branch -M main
git push -u origin main
Step 3: Install the Amplify packages
Open a new terminal window, navigate to your app's root folder (profilesapp
), and run the following command:
npm create amplify@latest -y
- Running the previous command will scaffold a lightweight Amplify project in the app’s directory.
- In your terminal window, run the following command to push the changes to GitHub:
git add .
git commit -m 'installing amplify'
git push origin main
Step 4: Deploy your app with AWS Amplify
Sign in to the AWS Management console in a new browser window and open the AWS Amplify console at https://console.aws.amazon.com/amplify/apps.
Choose Create new app.
- On the Start building with Amplify page, for Deploy your app, select GitHub, and select Next.
- When prompted, authenticate with GitHub. You will be automatically redirected back to the Amplify console. Choose the repository and main branch you created earlier. Then select Next.
- Leave the default build settings, and select Next.
- Review the inputs selected, and choose Save and deploy.
AWS Amplify will now build your source code and deploy your app at https://...amplifyapp.com
, and on every git push, your deployment instance will update. It may take up to 5 minutes to deploy your app.
- Once the build completes, select the Visit deployed URL button to see your web app up and running live.
Conclusion
You have deployed a React application in the AWS Cloud by integrating with GitHub and using AWS Amplify. With AWS Amplify, you can continuously deploy your application in the Cloud and host it on a globally available CDN.
Task 2: Build a Serverless Function
Overview
Now that you have a React web app, you will use AWS Amplify and AWS Lambda to configure a serverless function. This function is invoked after a signed-up user confirms their user account. AWS Lambda is a compute service that runs your code in response to events and automatically manages the compute resources, making it the fastest way to turn an idea into modern, production, serverless applications.
Key Concepts
- Serverless function: A piece of code that will be executed by a compute service, on demand.
Implementation
Step 1: Setup an Amplify Function
- On your local machine, navigate to the
profilesapp/amplify/auth
folder and create a new folder inside theamplify/auth
folder, naming itpost-confirmation
, and then create the files namedresource.ts
andhandler.ts
inside the folder.
- Update the
amplify/auth/post-confirmation/resource.ts
file with the following code to define thepostConfirmation
function:
import { defineFunction } from '@aws-amplify/backend';
export const postConfirmation = defineFunction({
name: 'post-confirmation',
});
- Update the
amplify/auth/post-confirmation/handler.ts
file with the following code to define the function’s handler:
import type { PostConfirmationTriggerHandler } from "aws-lambda";
export const handler: PostConfirmationTriggerHandler = async (event) => {
return event;
};
Conclusion
You have defined a Lambda function using Amplify.
Task 3: Create a Data Table
Overview
In this task, you will create a data model to persist data using a GraphQL API and Amazon DynamoDB. Additionally, you will use AWS Identity and Access Management (IAM) authorization to securely give our services the required permissions to interact with each other. You will also allow the Lambda function you created in the previous task to use the GraphQL API to write to your newly created DynamoDB table using an IAM policy.
Key Concepts
- Amplify backend: Amplify Gen 2 uses a full-stack TypeScript developer experience (DX) for defining backends. Simply author app requirements like data models, business logic, and auth rules in TypeScript. Amplify automatically configures the correct cloud resources and deploys them to per-developer cloud sandbox environments for fast, local iteration.
Implementation
Step 1: Setup Amplify Data
- On your local machine, navigate to the
amplify/data/resource.ts
file and update it with the following code:
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
import { postConfirmation } from "../auth/post-confirmation/resource";
const schema = a
.schema({
UserProfile: a
.model({
email: a.string(),
profileOwner: a.string(),
})
.authorization((allow) => [
allow.ownerDefinedIn("profileOwner"),
]),
})
.authorization((allow) => [allow.resource(postConfirmation)]);
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: "apiKey",
apiKeyAuthorizationMode: {
expiresInDays: 30,
},
},
});
- Open a new terminal window, navigate to your app's root folder (
profilesapp
), and run the following command to deploy cloud resources into an isolated development space:
npx ampx sandbox
- Once the cloud sandbox has been fully deployed, your terminal will display a confirmation message, and the
amplify_outputs.json
file will be generated and added to your project.
- Open a new terminal window, navigate to your app's root folder (
profilesapp
), and run the following command to generate the GraphQL client code to call your data backend:
npx ampx generate graphql-client-code --out <path-to-post-confirmation-handler-dir>/graphql
Amplify will create the folder amplify/auth/post-confirmation/graphql
, where you will find the client code to connect to the GraphQL API.
Step 2: Modify Lambda Function to Connect to the API
- On your local machine, navigate to the
amplify/auth/post-confirmation/handler.ts
file and replace the code with the following:
import type { PostConfirmationTriggerHandler } from "aws-lambda";
import { type Schema } from "../../data/resource";
import { Amplify } from "aws-amplify";
import { generateClient } from "aws-amplify/data";
import { env } from "$amplify/env/post-confirmation";
import { createUserProfile } from "./graphql/mutations";
Amplify.configure(
{
API: {
GraphQL: {
endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT,
region: env.AWS_REGION,
defaultAuthMode: "iam",
},
},
},
{
Auth: {
credentialsProvider: {
getCredentialsAndIdentityId: async () => ({
credentials: {
accessKeyId: env.AWS_ACCESS_KEY_ID,
secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
sessionToken: env.AWS_SESSION_TOKEN,
},
}),
clearCredentialsAndIdentityId: () => {
/* noop */
},
},
},
}
);
const client = generateClient<Schema>({
authMode: "iam",
});
export const handler: PostConfirmationTriggerHandler = async (event) => {
await client.graphql({
query: createUserProfile,
variables: {
input: {
email: event.request.userAttributes.email,
profileOwner: `${event.request.userAttributes.sub}::${event.userName}`,
},
},
});
return event;
};
Conclusion
You have created a data table and configured a GraphQL API to persist data in an Amazon DynamoDB database. Then, you updated the Lambda function to use the API.
Task 4: Link a Serverless Function to a Web App
Overview
In this task, you will update the Amplify Auth resources to use the Lambda function created in the previous module as an Amazon Cognito post-confirmation invocation. When the user completes the sign-up, the function will use the GraphQL API and capture the user’s email into the DynamoDB table.
Key Concepts
- Lambda invocation: The type of event that will make a Lambda (serverless) function run. This can be another AWS service or an external input.
Implementation
Step 1: Setup Amplify Auth
- On your local machine, navigate to the
amplify/auth/resource.ts
file and update it with the following code:
import { defineAuth } from '@aws-amplify/backend';
import { postConfirmation } from './post-confirmation/resource';
export const auth = defineAuth({
loginWith: {
email: true,
},
triggers: {
postConfirmation
}
});
- The sandbox will automatically get updated and redeployed once the file is updated. If the sandbox is not running, you can run the following command in a new terminal window:
npx ampx sandbox
- Once the cloud sandbox has been fully deployed, your terminal will display a confirmation message, and the
amplify_outputs.json
file will be generated/updated and added to yourprofilesapp
project.
Conclusion
You used Amplify to configure authentication and set up the Lambda function to be invoked when the user signs in to the app.
Task 5: Add Interactivity to Your Web App
Overview
In this task, you will create a frontend for your app and connect it to the cloud backend you have already built. You will update the website to use the Amplify UI component library to scaffold out an entire user authentication flow, allowing users to sign up, sign in, reset their password, and invoke the GraphQL API.
Key Concepts
- Amplify libraries: The Amplify libraries allow you to interact with AWS services from a web or mobile application.
Implementation
Step 1: Install the Amplify libraries
In a new terminal window, in your project's root folder (profilesapp
), run the following command:
npm install aws-amplify @aws-amplify/ui-react
Step 2: Style the app UI
On your local machine, navigate to the profilesapp/src/index.css
file and update it with the following code:
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color: rgba(255, 255, 255, 0.87);
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}
.box:nth-child(3n + 1) {
grid-column: 1;
}
.box:nth-child(3n + 2) {
grid-column: 2;
}
.box:nth-child(3n + 3) {
grid-column: 3;
}
Step 3: Implement the UI
On your local machine, navigate to the profilesapp/src/main.jsx
file and update it with the following code:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { Authenticator } from "@aws-amplify/ui-react";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<Authenticator>
<App />
</Authenticator>
</React.StrictMode>
);
- Open the
profilesapp/src/App.jsx
file and update it with the following code:
import { useState, useEffect } from "react";
import {
Button,
Heading,
Flex,
View,
Grid,
Divider,
} from "@aws-amplify/ui-react";
import { useAuthenticator } from "@aws-amplify
/ui-react";
import { Amplify } from "aws-amplify";
import "@aws-amplify/ui-react/styles.css";
import { generateClient } from "aws-amplify/data";
import outputs from "../amplify_outputs.json";
Amplify.configure(outputs);
const client = generateClient({
authMode: "userPool",
});
export default function App() {
const [userprofiles, setUserProfiles] = useState([]);
const { signOut } = useAuthenticator((context) => [context.user]);
useEffect(() => {
fetchUserProfile();
}, []);
async function fetchUserProfile() {
const { data: profiles } = await client.models.UserProfile.list();
setUserProfiles(profiles);
}
return (
<Flex
className="App"
justifyContent="center"
alignItems="center"
direction="column"
width="70%"
margin="0 auto"
>
<Heading level={1}>My Profile</Heading>
<Divider />
<Grid
margin="3rem 0"
autoFlow="column"
justifyContent="center"
gap="2rem"
alignContent="center"
>
{userprofiles.map((userprofile) => (
<Flex
key={userprofile.id || userprofile.email}
direction="column"
justifyContent="center"
alignItems="center"
gap="2rem"
border="1px solid #ccc"
padding="2rem"
borderRadius="5%"
className="box"
>
<View>
<Heading level="3">{userprofile.email}</Heading>
</View>
</Flex>
))}
</Grid>
<Button onClick={signOut}>Sign Out</Button>
</Flex>
);
}
Step 4: Run the Application
- Open a new terminal window, navigate to your project's root directory (
profilesapp
), and run the following command to launch the app:
npm run dev
- Select the Local host link to open the Vite + React application.
Choose the Create Account tab and use the authentication flow to create a new user by entering your email address and a password. Then, choose Create Account.
You will receive a verification code sent to your email. Enter the verification code to log in to the app. When signed in, the app will display your email address.
- In the open terminal window, run the following command to push the changes to GitHub:
git add .
git commit -m 'displaying user profile'
git push origin main
Sign in to the AWS Management console in a new browser window, and open the AWS Amplify console at https://console.aws.amazon.com/amplify/apps.
AWS Amplify automatically builds your source code and deploys your app at
https://...amplifyapp.com
. Select the Visit deployed URL button to see your web app up and running live.
Conclusion
You have successfully added interactivity to your web app, allowing users to sign up, log in, and view their profiles using AWS Amplify’s powerful UI components.
Task 6: Clean Up Resources
Overview
To finish this tutorial, you will clean up the resources created throughout. It is a best practice to delete resources you are no longer using to avoid unwanted charges.
Implementation
- In the Amplify console, in the left-hand navigation for the
profilesapp
, choose App settings and select General settings. - In the General settings section, choose Delete app.
Congratulations!
You have successfully created a React web app and used AWS Amplify to configure authentication and data resources. Additionally, you created a function to update the data model with user details upon sign-up. Then, you built a frontend to display the captured data. Finally, you used AWS Amplify to host the app!
Feel free to explore further and expand on this project as needed. The sky's the limit with AWS Amplify!
Challenges Faced and Solutions
Challenge 1: Configuring User Authentication
AWS Amplify simplifies authentication setup, but customization may require configuration adjustments in the Amplify Console.Challenge 2: Data Consistency
DynamoDB may not immediately reflect changes, especially with concurrent requests. Using AppSync’s real-time updates ensures data synchronization across all instances.Challenge 3: Lambda Function Limits
AWS imposes limits on Lambda’s execution time and memory. Optimize the function code and adjust settings in the Amplify Console if needed.
Conclusion
In this project, I learned how to build and deploy a simple web application with user authentication and data storage on AWS using Amplify. The setup demonstrates a full-stack serverless application, ideal for rapid development and easy scaling. AWS Amplify offers an efficient way to manage web applications and their backend services, perfect for various use cases, from prototyping to production.
Explore my GitHub repository.
Asif Khan — Aspiring Cloud Architect | Weekly Cloud Learning Chronicler
Top comments (0)