Paweł Pierzchlewicz
Head of Artificial Intelligence

10 min read

July 7, 2021

Getting Started With AWS Amplify

What will you learn

Our shared need for precision, fair play, and heightened tension during matches shapes a willingness to incorporate new sports technologies.

  1. Moreover, this technological enhancement adds a layer of suspense and anticipation.
  2. Intensifying the drama of each match and contributing to a new dimension in our evolving sporting landscape.
  3. Moreover, this technological enhancement adds a layer of suspense and anticipation.
  4. Intensifying the drama of each match and contributing to a new dimension in our evolving sporting landscape.

At TeaCode.io we really like our tea though at times its stock may run out. This has given us ideas for several impressive web apps. Let me take you on a journey of building and deploying a super simple tea management app with AWS Amplify.

What is AWS Amplify?

AWS Amplify provides developers with a set of tools and services for the rapid development of scalable full-stack applications. Amplify allows one to quickly configure a backend and connect it to your app and then deploy it! Sounds too good to be true? Well, let me show you how quickly you can set up, build and deploy a simple React.js tea management app using AWS services.

By clicking this button you agree to receive information from TeaCode about software development and app marketing, the company and its projects to your email. Your data is processed by TeaCode (Postępu 15, 7th floor, 02-676 Warsaw, Poland) to send you relevant content via newsletter (from which you can unsubscribe at any time). You can read more in our Privacy Policy.

Planning out the app

Let’s first plan out the app so that we know what we are going to need. Firstly, we need a front-end app that we will build using React.js. We also want to store the data – DynamoDB with a GraphQL API will manage this for us. Finally, we want to have an authorization system and we will let AWS Cognito handle it.

Basic Setup

In order to use AWS Amplify you will need to create a free AWS account. Next, install the AWS amplify cli package using npm. You might need to run this with sudo depending on your system policies.

npm install -g @aws-amplify/cli

Once it is installed, run the configuration script.

amplify configure

It will take you through all the necessary steps including setting up an IAM user, which for the tutorial you should create with the AdministratorAccess policy. Remember to store the accessKeyId and the secretAccessKey as they are going to be required in the later steps.

1Specify the AWS Region
2? region:  # Your preferred region
3Specify the username of the new IAM user:
4? user name:  # User name for Amplify IAM user
5Complete the user creation using the AWS console
6
7Enter the access key of the newly created user:
8? accessKeyId:  # YOUR_ACCESS_KEY_ID
9? secretAccessKey:  # YOUR_SECRET_ACCESS_KEY
10This would update/create the AWS Profile in your local machine
11? Profile Name:  # (default)
12
13Successfully set up the new user.

Frontend Setup

With the basics of amplify all done let’s configure our simple React app. Run the following commands:

npx create-react-app tea-management-app
cd tea-management-app

This will create a new React app in the tea-management-app directory. Now, from the root directory, we can initialize the backend using amplify. Simply run:

amplify init

During the initialization, you will be prompted to answer a couple of questions.

1Enter a name for the project (tea-mangement-app)
2
3# All AWS services you provision for your app are grouped into an "environment"
4# A common naming convention is dev, staging, and production
5Enter a name for the environment (dev)
6
7# Sometimes the CLI will prompt you to edit a file, it will use this editor to open those files.
8Choose your default editor
9
10# Amplify supports JavaScript (Web & React Native), iOS, and Android apps
11Choose the type of app that you're building (javascript)
12
13What JavaScript framework are you using (react)
14
15Source directory path (src)
16
17Distribution directory path (build)
18
19Build command (npm run build)
20
21Start command (npm start)
22
23# This is the profile you created with the `amplify configure` command in the introduction step.
24Do you want to use an AWS profile

With Amplify initialized, let’s install the necessary amplify packages by running

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

The aws-amplify package provides you with all the necessary methods to interface with amplify and @aws-amplify/ui-react provides you with some React-specific UI components.

Finally, let’s configure the AWS Amplify client by adding the following code to src/index.js.

1import Amplify from "aws-amplify";
2import awsExports from "./aws-exports";
3Amplify.configure(awsExports);

Adding a GraphQL API

To add an API it is as simple as running the following command in the root directory of your project.

amplify add api

For this tutorial accept the default values. As a result, you should have the following output.

1? Please select from one of the below mentioned services:
2# GraphQL
3? Provide API name:
4# teaapi
5? Choose the default authorization type for the API:
6# API Key
7? Enter a description for the API key:
8# demo
9? After how many days from now the API key should expire:
10# 7 (or your preferred expiration)
11? Do you want to configure advanced settings for the GraphQL API:
12# No
13? Do you have an annotated GraphQL schema?
14# No
15? Choose a schema template:
16# Single object with fields (e.g., “Todo” with ID, name, description)
17? Do you want to edit the schema now?
18# Yes

The CLI should open the GraphQL schema, however, should it fail to do so you can find it under amplify/backend/api/teaapi/schema.graphql. Replace the contents of the file with:

1type Tea @model {
2  id: ID!
3  name: String!
4  bags: Int!
5}

Deploying the GraphQL API

Now let’s deploy the backend by simply running the push command.

amplify push

When pushing a new API version the CLI will ask you a couple of questions. You should answer them in the following way:

1? Are you sure you want to continue? Y
2
3# You will be walked through the following questions for GraphQL code generation
4? Do you want to generate code for your newly created GraphQL API? Y
5? Choose the code generation language target: javascript
6? Enter the file name pattern of graphql queries, mutations and subscriptions: src/graphql/**/*.js
7? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions? Y
8? Enter maximum statement depth [increase from default if your schema is deeply nested]: 2

GraphQL operations are automatically generated

As a result, AWS Amplify will generate all the necessary CRUD operations for you to interface with the GraphQL API. You can find these under src/graphql/. For example, under src/graphql/mutations.js you will find the mutations for creating, updating and deleting tea objects from the database. Let’s look at the createTea mutation.

1export const createTea = /* GraphQL */ `
2  mutation CreateTea(
3    $input: CreateTeaInput!
4    $condition: ModelTeaConditionInput
5  ) {
6    createTea(input: $input, condition: $condition) {
7      id
8      name
9      bags
10      createdAt
11      updatedAt
12    }
13  }
14`;

It provides an interface for you to call from your frontend app to create a Tea object. It accepts an input of type CreateTeaInput which is automatically generated and defined in the schema.graphql which you can locate under  #current-cloud-backend/api/teaapi/build/schema.graphql. In this file, you should be able to find the CreateTeaInput definition. It should be:

1input CreateTeaInput {
2  id: ID
3  name: String!
4  bags: Int!
5}

This means that the CreateTeaInput requires a name as a string and bags as an int. The id of type ID is optional. You will also find the definitions of the remaining objects in the schema.graphql. Note, however, that these are generated automatically, so any changes that you make to these definitions will be overwritten when you call the amplify push command. At the same time, this means that when you change something in the definition of the model you need to push the changes to get the updated version of your functions.

Adding UI to the App

Now that our backend is setup we can build the frontend of our tea management app. We will create a form for adding new types of tea with the specified number of bags and display a list of the available teas that you can either drink or delete.

Open src/App.js and replace the code with the following code:

1/* src/App.js */
2import React, { useEffect, useState } from 'react'
3import Amplify, { API, graphqlOperation } from 'aws-amplify'
4import { createTea, deleteTea, updateTea } from './graphql/mutations'
5import { listTeas } from './graphql/queries'
6
7import awsExports from "./aws-exports";
8Amplify.configure(awsExports);
9
10const initialState = { name: '', bags: '' }
11
12const App = () => {
13  const [formState, setFormState] = useState(initialState)
14  const [teas, setTeas] = useState([])
15
16  useEffect(() => {
17    fetchTeas()
18  }, [])
19
20  function setInput(key, value) {
21    setFormState({ ...formState, [key]: value })
22  }
23
24  async function fetchTeas() {
25    try {
26      const teaData = await API.graphql(graphqlOperation(listTeas))
27      const teas = teaData.data.listTeas.items
28      
29      setTeas(teas)
30    } catch (err) { console.log('error fetching teas') }
31  }
32
33  async function addTea() {
34    try {
35      if (!formState.name || !formState.bags) return
36      
37      const tea = { ...formState }
38      
39      setTeas([...teas, tea])
40      setFormState(initialState)
41      
42      await API.graphql(graphqlOperation(createTea, {input: tea}))
43      
44      fetchTeas()
45    } catch (err) {
46      console.log('error creating tea:', err)
47    }
48  }
49
50  async function removeTea(index) {
51    try {
52      if (teas.length > index) {
53        const teaId = {id: teas[index].id}
54        
55        teas.splice(index, 1)
56        setTeas([...teas])
57        
58        await API.graphql(graphqlOperation(deleteTea, {input: teaId}))
59      }
60    } catch (err) {
61      console.log('error deleting tea:', err)
62    }
63  }
64
65  async function drinkTea(index) {
66    try {
67      if (teas.length > index) {
68        let tea = teas[index]
69        const newCount = parseInt(tea.bags) - 1
70
71        if (newCount <= 0) {
72          teas.splice(index, 1)
73          setTeas([...teas])
74
75          await API.graphql(graphqlOperation(deleteTea, {input: {id: tea.id}}))
76        } else {
77          tea.bags = newCount
78          teas.splice(index, 1, tea)
79
80          tea = {
81            id: tea.id,
82            name: tea.name,
83            bags: tea.bags
84          }
85
86          setTeas([...teas])
87            
88          await API.graphql(graphqlOperation(updateTea, {input: tea}))
89        }
90      }
91    } catch (err) {
92      console.log('error drinking tea:', err)
93    }
94  }
95
96  return (
97    <div style={styles.container}>
98      <h2>Tea Management App 🌿</h2>
99      <div style={styles.inputContainer}>
100      <input
101        onChange={event => setInput('name', event.target.value)}
102        style={styles.input}
103        value={formState.name}
104        placeholder="Name"
105      />
106      <input
107        type="number"
108        onChange={event => setInput('bags', event.target.value)}
109        style={styles.input}
110        value={formState.bags}
111        placeholder="# of bags"
112      />
113      </div>
114      <button style={styles.button} onClick={addTea}>+ Add Tea</button>
115      <div style={styles.teaContainer}>
116        <h4>Currently Available Tea</h4>
117        {
118          teas.map((tea, index) => (
119            <div key={tea.id ? tea.id : index} style={styles.tea}>
120              <div>
121                <p style={styles.teaName}>{tea.name}</p>
122                <p style={styles.teaBags}>{tea.bags} Bags</p>
123              </div>
124              <div>
125                <button style={styles.drinkButton} onClick={() => drinkTea(index)}>Drink</button>
126                <button style={styles.deleteButton} onClick={() => removeTea(index)}>Delete</button>
127              </div>
128            </div>
129          ))
130        }
131      </div>
132    </div>
133  )
134}
135
136const styles = {
137  container: { width: 400, margin: '0 auto', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 20 },
138  inputContainer: {display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexDirection: 'row', width: '100%'},
139  input: { boxSizing: 'border-box', borderRadius: 5, maxWidth: 195, border: 'none', backgroundColor: '#efefef', marginBottom: 10, padding: 8, fontSize: 18 },
140  teaContainer: {marginTop: 25},
141  tea: {  marginBottom: 10, marginTop: 10, padding: 10, backgroundColor: '#eee', borderRadius: 5, display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'},
142  teaName: { fontSize: 20, fontWeight: 'bold', marginTop: 0, marginBottom: 10 },
143  teaBags: { marginBottom: 0, marginTop: 0, color: '#666', fontStyle: 'italic' },
144  button: { backgroundColor: '#27ae60', border: 'none', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px', borderRadius: 5, cursor: 'pointer'},
145  drinkButton: { backgroundColor: '#27ae60', color: 'white', border: 'none', borderRadius: 5, fontSize: 14, height: 30, cursor: 'pointer', marginRight: 5},
146  deleteButton: { backgroundColor: '#e76558', color: 'white', border: 'none', borderRadius: 5, fontSize: 14, height: 30, cursor: 'pointer'},
147}
148
149export default App

Let’s break down some of the functions that we have here.

  • fetchTeas – it fetches a list of teas using the aws-amplify API module and the listTeas query function.
  • addTea – it calls the createTea mutation using the aws-amplify API module based on the data provided in the form.
  • removeTea – it calls the deleteTea mutation using the aws-amplify API module using the id of the tea object. It is called when the delete button is clicked.
  • drinkTea – it updates the tea object by removing one bag. If the number of bags reaches 0, the tea object is removed.

All of these functions integrate with the API and the database making it straightforward for frontend developers to build some functionalities without diving deep into the matters of the backend.

Run it locally

To check if everything works as intended run the app locally by calling:

npm start

You should see the form for adding tea. Once you add a couple of teas, your app should look something like this:

Adding authentication

Now let’s see how easy it is to add authentication to your app. AWS provides the Amazon Cognito service which Amplify uses as its main authentication provider. It allows you to manage all user-related business without the need of setting up the whole system by hand! Just like with the API it is a simple as running:

amplify add auth

and answering the questions

? Do you want to use the default authentication and security configuration? Default configuration
? How do you want users to be able to sign in? Username
? Do you want to configure advanced settings?  No, I am done.

and finally you need to push the new service

amplify push

Authentication UI works out of the box

The @aws-amplify/ui-react package provides you with a ready solution for the authentication UI all you need to do is import the higher-order component

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

and wrap the main App component

export default withAuthenticator(App)

Now start your app and you should now see a login and registration UI.

Once you create an account you can log in and have access to the tea management app!

Deploy the App!

Now that the app is all setup let’s deploy it to be available remotely. For this, we need to add a hosting

amplify add hosting

and answer the questions

? Select the plugin module to execute: # Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment)
? Choose a type: # Manual Deployment

finally, we can publish the app

amplify publish

The App is now online!

Table of Contents:

Similar articles:

Subscribe to our newsletter