Enter the Serverless Era: Building Fullstack Web Apps with AWS Amplify and React

Web development has come a long way, and with the advent of serverless architecture, it has become easier and quicker to develop fullstack web applications. In this article, we will explore the power of serverless architecture and learn how to build fullstack web applications with AWS Amplify and React.

Before we dive in, let’s understand what serverless architecture is. Serverless architecture is a cloud computing model in which the cloud provider manages the infrastructure and automatically allocates, configures, and scales the resources needed to run and support applications. With serverless architecture, developers can focus on writing code instead of worrying about servers, operating systems, and deployment.

Why Serverless Architecture is a Game Changer for Fullstack Web Applications

Serverless architecture offers several benefits for developing fullstack web applications:

  • Scalability: Serverless architecture scales automatically in response to changes in demand, ensuring that the application remains performant and highly available.
  • Reduced Infrastructure Costs: With serverless architecture, you only pay for the resources you use, making it cost-effective.
  • Faster Time to Market: Serverless architecture eliminates the need for infrastructure setup and maintenance, enabling developers to focus on coding and deploying their application faster.
  • Increased Agility: Serverless architecture enables developers to experiment and iterate quickly, reducing the time and cost of development.

Building Fullstack Web Applications with AWS Amplify and React

AWS Amplify is a development platform for building secure, scalable, and highly available cloud-powered applications. Amplify makes it easy to develop fullstack web applications with React, providing a rich set of features for authentication, API integration, and storage.

Prerequisites

To follow this tutorial, you will need:

  • AWS Account
  • Node.js and NPM installed
  • Basic knowledge of React, JavaScript, HTML, and CSS

Step 1: Create a New React App

We will start by creating a new React app using the create-react-app CLI:

npx create-react-app my-amplify-app
cd my-amplify-app

Step 2: Set up Amplify CLI

Next, we need to install and configure the Amplify CLI:

npm install -g @aws-amplify/cli
amplify configure

Follow the prompts to set up Amplify CLI with your AWS account.

Step 3: Initialize Amplify Project

Now, let’s initialize our Amplify project:

amplify init

Follow the prompts to set up your Amplify project:

  • Select your default editor
  • Choose the AWS profile you want to use
  • Provide a name for your app
  • Choose a default editor
  • Select the type of app you’re building (JavaScript)
  • Select a framework (React)
  • Leave the source directory as “src”
  • Leave the build directory as “build”
  • Choose whether or not to use AWS CloudFormation

Step 4: Add Authentication

Now, let’s add authentication to our app using the Amplify Auth category:

amplify add auth

Follow the prompts to configure authentication:

  • Do you want to use default authentication and security configuration? (Yes, use the default configuration)
  • How do you want users to be able to sign in when using your Cognito User Pool? (Username)
  • Do you want to configure advanced settings for the authentication provider? (No, I am done)

Next, let’s update our React app to use the Amplify Auth module:

npm install aws-amplify @aws-amplify/ui-react

In your index.js file:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

import Amplify from "aws-amplify";
import awsconfig from "./aws-exports";
Amplify.configure(awsconfig);

import { AmplifyAuthenticator } from '@aws-amplify/ui-react';

ReactDOM.render(
  <React.StrictMode>
    <AmplifyAuthenticator>
      <App />
    </AmplifyAuthenticator>
  </React.StrictMode>,
  document.getElementById('root')
);

Now, let’s add authentication to our App.js file:

import React, { useState, useEffect } from 'react';
import logo from './logo.svg';
import './App.css';
import { withAuthenticator } from '@aws-amplify/ui-react';

function App() {
  const [user, updateUser] = useState(null);

  useEffect(() => {
    updateUser(localStorage.getItem('authToken'));
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <p>User: {JSON.stringify(user)}</p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default withAuthenticator(App);

Step 5: Add API Integration

Now, let’s add API integration to our app using the Amplify API category:

amplify add api

Follow the prompts to configure the API:

  • Select the type of API (GraphQL)
  • Select an authorization type (API key)
  • Provide a name for your API
  • Choose whether or not to configure advanced settings (No, I am done)

Next, let’s update our React app to use the Amplify API module:

npm install graphql @aws-amplify/api

In your App.js file:

import { API } from '@aws-amplify/api';
import { graphqlOperation } from '@aws-amplify/graphql';

const listPosts = `query ListPosts {
  listPosts {
    items {
      id
      title
      content
    }
  }
}`

function App() {
  const [user, updateUser] = useState(null);
  const [posts, updatePosts] = useState([]);

  useEffect(() => {
    updateUser(localStorage.getItem('authToken'));
    getPosts();
  }, []);

  async function getPosts() {
    const postData = await API.graphql(graphqlOperation(listPosts));
    updatePosts(postData.data.listPosts.items);
  }

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <p>User: {JSON.stringify(user)}</p>
        <ul>
          {posts.map(post => (
            <li key={post.id}>
              <strong>{post.title}:</strong> {post.content}
            </li>
          ))}
        </ul>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

Step 6: Add Storage

Finally, let’s add storage to our app using the Amplify Storage category:

amplify add storage

Follow the prompts to configure storage:

  • Select the service (Content)
  • Select the type of storage backend for file uploads (Amazon S3)
  • Please provide a bucket name (my-amplify-app-123456789)
  • Who should have access? (Auth users only)
  • What kind of access do you want for Authenticated users? (create/update, read/delete)
  • Do you want to add a Lambda Trigger for your S3 Bucket? (No)

Next, let’s update our React app to use the Amplify Storage module:

npm install @aws-amplify/storage

In your App.js file:

import { Storage } from '@aws-amplify/storage';

async function getSignedUrl(key) {
  const signedUrl = await Storage.get(key);
  return signedUrl;
}

function App() {
  const [user, updateUser] = useState(null);
  const [posts, updatePosts] = useState([]);
  const [imageUrl, updateImageUrl] = useState(null);

  useEffect(() => {
    updateUser(localStorage.getItem('authToken'));
    getPosts();
    getSignedUrl();
  }, []);

  async function getPosts() {
    const postData = await API.graphql(graphqlOperation(listPosts));
    updatePosts(postData.data.listPosts.items);
  }

  async function getSignedUrl() {
    const signedUrl = await Storage.get('my-image.jpg');
    updateImageUrl(signedUrl);
  }

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <p>User: {JSON.stringify(user)}</p>
        <ul>
          {posts.map(post => (
            <li key={post.id}>
              <strong>{post.title}:</strong> {post.content}
            </li>
          ))}
        </ul>
        {imageUrl &&
          <img src={imageUrl} alt="sample" style={{ maxWidth: 250 }} />
        }
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

Styling with Tailwind CSS

Now that we’ve built the core functionalities of our fullstack web app, let’s make it look beautiful using Tailwind CSS. Tailwind CSS is a utility-first CSS framework that makes it easy to style web applications using pre-defined classes.

Step 1: Install Tailwind CSS

npm install tailwindcss postcss-cli autoprefixer

Step 2: Create Tailwind Config

npx tailwindcss init -p

This will create a tailwind.config.js file in your project root directory.

Step 3: Configure PostCSS

Create a postcss.config.js file in your project root directory:

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
  ]
}

Step 4: Import Tailwind CSS in your App.js file

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

Now, you can use Tailwind CSS classes to style your React components.

Conclusion

Serverless architecture has revolutionized the way we develop fullstack web applications, making it faster, easier, and more cost-effective. In this article, we explored how to build fullstack web applications with AWS Amplify and React, covering everything from authentication to API integration. We also learned how to style our app using Tailwind CSS. With the power of AWS Amplify and serverless architecture, you can build secure, scalable, and highly available cloud-powered applications with ease.