Deploy a Web Application on AWS Amplify

GETTING STARTED GUIDE

Module 2: Build the frontend and connect an API

In this module, you will learn to add an API to your Amplify project

Introduction

In this module, you will build the frontend for your web application and connect to an API (application programming interface) using GraphQL API. GraphQL is a query language for APIs and helps you retrieve and update data on your application.

What You Will Learn

  • Create a basic React frontend application
  • Call a GraphQL API from your application
  • Call the API from your application's frontend

 Time to Complete

10 minutes

 Module Prereqs

  • AWS Account with administrator-level access**
  • Recommended browser: The latest version of Chrome or Firefox

[**]Accounts created within the past 24 hours might not yet have access to the services required for this tutorial.

Implementation

Install Amplify libraries

You need to install the Amplify React library @aws-amplify/ui-react (contains the React UI components). 

Run the following command to install them:

npm install @aws-amplify/ui-react

You now need to create the frontend for your application. Open the src/App.js file and replace its entire content with the following code:

import { withAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react';
import Amplify from 'aws-amplify';
import awsExports from './aws-exports';

Amplify.configure(awsExports);

function App() {
  return (
    <div>
      <h1>Notes App</h1>
      <AmplifySignOut />
    </div>
  );
}

export default withAuthenticator(App);

Test your application

Now you can run your app locally to test it:

npm start

This will start a development server on http://localhost:3000 and open the page in your browser. You will be prompted to sign up before you can use the service - this data is stored in your project's Congnito database, and only you have access to it. Once logged in, the app will only display a heading with Notes App, and a Sign In button as you haven't added anything to it yet. Next, you will add an API to the app. You can use ctrl + c to stop the server again.

gsg-build-amplify-2

With just a few CLI commands and lines of code, we have created a working Single-Page Application with login flow. This application is just a skeleton and login will not work yet. Continue adding functionality to your application in the following sections.

Add a GraphQL API with Amplify

You are now going to add an API to the application. Amplify uses AWS AppSync and Amazon DynamoDB to power GraphQL APIs. AppSync is a managed GraphQL service that will take care of our API, and Amazon DynamoDB is a NoSQL database that will store the data our API will use.

To add the API, run amplify add api, and choose the following options to the questions (lines begin with > symbol) - during this step, it will ask questions about the authorization provider, this will be used in a future guide:

A GraphQL schema is a representation of an object and its fields. You need to define your GraphQL schema, and Amplify will create the required DynamoDB table, and configure GraphQL to handle the reads, writes, updates and deletes for you. Open the amplify/backend/api/amplifyapp/schema.graphql file and replace the contents with the following:

amplify add api

? Please select from one of the below mentioned services:
❯ GraphQL
  REST
? Provide API name: amplifyapp
? Choose the default authorization type for the API
  API key
❯ Amazon Cognito User Pool
  IAM
  OpenID Connect
? Do you want to configure advanced settings for the GraphQL API
? Do you want to use the default authentication and security configuration?
❯ Default configuration
  Default configuration with Social Provider (Federation)
  Manual configuration
  I want to learn more.
? How do you want users to be able to sign in?
 ◯ Email
❯◉ Username
 ◯ Phone number
? Do you want to configure advanced settings?
❯ No, I am done.
  Yes, I want to make some additional changes.
? Do you have an annotated GraphQL schema? No
? Choose a schema template:
❯ Single object with fields (e.g., “Todo” with ID, name, description)
  One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”)
  Objects with fine-grained access control (e.g., a project management app with owner-bas
ed authorization)
? Do you want to edit the schema now? Yes
If you entered Yes to edit the schema now, your default editor should open to the file needed for the next section.

Create a GraphQL Schema

A GraphQL schema is a representation of an object and its fields. You need to define your GraphQL schema, and Amplify will create the required DynamoDB table, and configure GraphQL to handle the reads, writes, updates and deletes for you. Open the amplify/backend/api/amplifyapp/schema.graphql file and replace the contents with the following:

type Note @model @auth(rules: [{ allow: owner }]) {
  id: ID!
  text: String!
}

This schema defines a Note type with id and text as required fields. It also contains a directives that are part of the Amplify's GraphQL transform library:

@model: A type annotated with @model is stored in DynamoDB and has CRUDL (create, read, update, delete, list) operations automatically created for it.

@auth: A type annotated with @auth is protected by a set of authorization rules. Here, we are using owner authorization to make sure only the owner of a Note will be able to access and modify it.

Deploy Application

You are now ready to deploy your Amplify web application by running amplify push. This will upload your application to your AWS account for you, and Amplify will show you the changes being deployed, and ask to confirm the deployment:

✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev
    
┌──────────┬────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name      │ Operation │ Provider plugin   │
├──────────┼────────────────────┼───────────┼───────────────────┤
│ Auth     │ amplifyapp6177aede │ Create    │ awscloudformation │
├──────────┼────────────────────┼───────────┼───────────────────┤
│ Api      │ amplifyapp         │ Create    │ awscloudformation │
└──────────┴────────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes

After confirming, select the default values to the follow up questions when prompted:

? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2

This will take a few minutes to deploy, and you will see a list of resources being created for you. Amplify took the following actions:

  • Created a GraphQL API, backed by AWS AppSync, with all three types of GraphQL operations (queries, mutations, and subscriptions).
  • Generated code inside the src/graphql/ folder using the GraphQL operations required to create, retrieve and update Notes.
  • Created a DynamoDB table to store any Note created with our application.

Update Front End to Use API

To use the new API you just deployed, update the src/App.js file by replacing the contents with the following code:

import { Component } from 'react';
import Amplify, { API, graphqlOperation } from 'aws-amplify';
import { createNote, deleteNote } from './graphql/mutations';
import { listNotes } from './graphql/queries';

import { withAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react';
import awsExports from './aws-exports';

Amplify.configure(awsExports);

class AddNote extends Component {
  constructor(props) {
    super(props);
    this.state = { text: '' };
  }

  handleChange = (event) => {
    this.setState({ text: event.target.value });
  }

  handleClick = () => {
    this.props.addNote(this.state);
    this.setState({ text: '' });
  }

  render() {
    return (
      <div style={styles.form}>
        <input
          value={this.state.text}
          onChange={this.handleChange}
          placeholder="New Note"
          style={styles.input}
        />
        <button onClick={this.handleClick} style={styles.addButton}>Add Note</button>
      </div>
    );
  }
}

class NotesList extends Component {
  render() {
    return (
      <div>
        {this.props.notes.map(note =>
          <div key={note.id} style={styles.note}>
            <p>{note.text}</p>
            <button onClick={() => { this.props.deleteNote(note) }} style={styles.deleteButton}>x</button>
          </div>
        )}
      </div>
    );
  }
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { notes: [] };
  }

  async componentDidMount() {
    var result = await API.graphql(graphqlOperation(listNotes));
    this.setState({ notes: result.data.listNotes.items });
  }

  deleteNote = async (note) => {
    const id = {
      id: note.id
    };
    await API.graphql(graphqlOperation(deleteNote, { input: id }));
    this.setState({ notes: this.state.notes.filter(item => item.id !== note.id) });
  }

  addNote = async (note) => {
    var result = await API.graphql(graphqlOperation(createNote, { input: note }));
    this.state.notes.push(result.data.createNote);
    this.setState({ notes: this.state.notes });
  }

  render() {
    return (
      <div style={styles.container}>
        <h1>Notes App</h1>
        <AddNote addNote={this.addNote} />
        <NotesList notes={this.state.notes} deleteNote={this.deleteNote} />
        <AmplifySignOut />
      </div>
    );
  }
}

export default withAuthenticator(App);

const styles = {
  container: { width: 480, margin: '0 auto', padding: 20 },
  form: { display: 'flex', marginBottom: 15 },
  input: { flexGrow: 2, border: 'none', backgroundColor: '#ddd', padding: 12, fontSize: 18 },
  addButton: { backgroundColor: 'black', color: 'white', outline: 'none', padding: 12, fontSize: 18 },
  note: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 22, marginBottom: 15 },
  deleteButton: { fontSize: 18, fontWeight: 'bold' }
}

You now have a working application. Login with multi-factor authentication and the application can now communicate with the API to save / update / delete notes. To test it locally, run npm start again to confirm.

gsg-build-amplify-3

Conclusion

In this module, you learned how to create a React frontend application, add an API to it, and deploy the API to your AWS account. In the next module, you will learn how to deploy the front end from a GitHub repository, and set up a CI/CD pipeline to deploy future changes automatically.

Up Next: Automate Deployment

Let us know how we did.

Thank you for your feedback
We're glad this page helped you. Would you like to share additional details to help us continue to improve?
Close
Thank you for your feedback
We're sorry this page didn't help you. Would you like to share additional details to help us continue to improve?
Close