Create a Multiuser GraphQL CRUD(L) App in 10 minutes with the new AWS Amplify CLI (and, in a few extra minutes, add search capabilities with Elasticsearch)

Getting back to my series “Create a <INSERT APP TYPE HERE> App in minutes” (previous articles here and here), we will check now how we can create a secure multiuser Note Taking App with full CRUD capabilities backed by a Serverless GraphQL API (powered by AWS AppSync) and by a Serverless NoSQL Database (powered by Amazon DynamoDB) in less than 10 minutes with full user isolation as each user can only access and edit their own content. Best of all, we only need 150 lines of code!

It used to take hours or days to do something similar in the past. How is it possible to deploy, configure, connect and build the back-end cloud services as well as configure the front-end so quickly with so much less lines of code? The answer: AWS Amplify and the recently released AWS Amplify CLI.

“It is impressive that with less than 200 lines of code in the front-end and only a few minutes to setup the back-end any developer can get so much done”

Let’s see how easily we can do it. We’ll need some essential tools to get started, so execute the following commands from a terminal:

$ npm install -g @aws-amplify/cli
$ npm install -g create-react-app

or

$ yarn global add @aws-amplify/cli
$ yarn global add create-react-app

We start by creating a React App and adding some libraries to our project:

$ create-react-app amplifynotes
$ cd amplifynotes
$ yarn add aws-amplify aws-amplify-react bootstrap

Execute amplify configure to setup the CLI with the appropriate permissions (a handy step by step video tutorial is also available here) . It will prompt the creation of an IAM User in the AWS Console, just copy and paste the credentials and select a profile name:

$ amplify configure
Follow these steps to set up access to your AWS account:
Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue
Specify the AWS Region
? region: <your region of choice here>
Specify the username of the new IAM user:
? user name: amplify-admin
Complete the user creation using the AWS console
https://console.aws.amazon.com/iam/home?region=undefined#/users$new?step=final&accessKey&userNames=amplify-admin&permissionType=policies&policies=arn:aws:iam::aws:policy%2FAdministratorAccess
Press Enter to continue
Enter the access key of the newly created user:
? accessKeyId: AKIAIIxxxx**********
? secretAccessKey: rVP2wfXX+b50Dfmxxxxx********************
This would update/create the AWS Profile in your local machine
? Profile Name: amplify
Successfully set up the new user.

From the project folder /amplifynotes execute amplify init with the following settings, selecting the profile created earlier (i.e. change your editor of choice accordingly and use the defaults):

$ amplify init
Note: It is recommended to run this command from the root of your app directory
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path: src
? Distribution Directory Path: build
? Build Command: npm run-script build
? Start Command: npm run-script start
Using default provider awscloudformation
For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html
? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use amplify
⠦ Initializing project in the cloud...

Next let’s add our GraphQL API:

$ amplify add api
? Please select from one of the below mentioned services GraphQL
? Provide API name: amplifynotes
? Choose an authorization type for the API Amazon Cognito User Pool
Using service: Cognito, provided by: awscloudformation
The current configured provider is Amazon Cognito.
? Do you want to use the default authentication and security configuration? Yes, use the default configuration.
Successfully added auth resource
? Do you have an annotated GraphQL schema? No
? Do you want a guided schema creation? true
? What best describes your project: Objects with fine-grained access control (e.g., a project management app with owner-based authorization)
? Do you want to edit the schema now? Yes
Please edit the file in your editor: /<path>/amplify/backend/api/amplifynotes/schema.graphql
? Press enter to continue

At this point the default editor you configured in the first step will be opened. Delete the provided sample GraphQL schema and replace it with:

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

Back to the terminal, press <ENTER> then execute:

$ amplify push

Behind the scenes the Amplify CLI will use CloudFormation to configure and deploy a Cognito Users Pool for AuthN/Z, an AppSync GraphQL API and schema as well as a DynamoDB NoSQL table and wire up permissions and everything else needed to link the resources. After everything is deployed and setup, the identifiers for each resource are automatically added to a local aws_exports.js file that is used by AWS Amplify to reference the specific Auth and API cloud back-end resources.

In a nutshell, with the new CLI you can customize your own GraphQL data types and don’t need to worry about spending time on the undifferentiated heavy lifting of configuring, linking, securing and deploying multiple different highly available and scalable cloud back-end “lego block” services that will power your application.

Cloud Lego Blocks connected by AWS Amplify

Next open the App.js file from the /src folder and overwrite the content with the following code:

As agreed, only 150 Lines of code

Time to test! Execute amplify serve to test it locally then sign up a couple of users with a valid e-mail (you can use the same e-mail for different users) and mobile number, add some new notes and confirm one user has no access to the notes of the other user:

The App

Thanks to the schema directive @auth: (allow: owner) in the GraphQL schema powered by GraphQL Transformers, AWS AppSync is doing all the authorization hard work and automatically checking the ownership information based on the Cognito Users Pool user with pre-configured Resolver Mapping Templates created by the Amplify CLI to make sure only the authenticated user can perform any type of CRUD operation. Notes are added, updated or removed safely in DynamoDB with complete user content isolation.

“Configuring, linking, securing and deploying multiple different highly available and scalable cloud back-end ‘lego block’ services that will power your application.”

In this article we have sample code that will allow you to get started quickly with a simple CRUD application behind a managed GraphQL API backend. This is just a sample, so it’s not one size fits all and you’ll need to adapt and change for your specific use cases. For instance, in order to retrieve all notes from a specific user we’re using a query that performs a scan in the backend DynamoDB table. By default the Amplify CLI configured resources on AWS AppSync will limit the scan operation to 10 items, that means DynamoDB will read 10 items from the table. The default limit is 10 to be as conservative as possible with billed operations. In case you have more than 10 notes from different users in the DynamoDB table, some of them might not be displayed in the frontend. This limit can be easily increased by updating the first line of the listNotes query resolver at the AppSync console (#set( $limit = $util.defaultIfNull($context.args.limit,10))), by passing the limit in the GraphQL query itself (e.g. “limit:50”) or you could just implement pagination in the application (see below) instead. For the sake of simplicity, we’re using the defaults.

You could improve the current list capabilities (L in CRUDL) by implementing the built-in pagination powers GraphQL and AppSync provide. For instance, using the query bellow to retrieve 4 notes at a time and passing a token to retrieve the next 4 notes (it’s not implemented in the code above which is retrieving all notes with the listNotes query on line 20, feel like a challenge?):

Built-in Pagination

Moving forward if you want to make the app available publicly, you just need 2 extra commands:

$ amplify add hosting
$ amplify publish

By selecting PROD, a S3 bucket and a CloudFront distribution will be created and the React build artifacts will be uploaded automatically. CloudFront provides SSL encryption as well as built-in DDoS protection to the App out of the box. Great thing, due to Bootstrap’s responsive design support anyone can access the app’s mobile friendly UI using the CloudFront distribution address and test the app in multiple devices.

All the services (Cognito, AppSync, DynamoDB, S3, CloudFront) have a very generous free tier. It’s very likely you’ll be running your multiuser secure CRUD application for free for quite some time (don’t take my word for it, check the free tier allowance in each service to confirm). Best of all, there are absolutely no back-end servers to manage!


How about adding some Search goodness powered by Elasticsearch in a few more minutes?

As the users start adding more notes, they’ll need a proper keyword search feature to search through their data and find the right notes at the right time.

How can I add such important feature to my app in a few extra minutes? AWS Amplify CLI and some extra GraphQL Transformer capabilities to the rescue!

Open the GraphQL schema you edited before on:

/<path>/amplifynotes/amplify/backend/api/amplifynotes/schema.graphql

And add the schema directive @searchable to the existing Note type:

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

Then execute amplify push to commit the changes. The @searchable directive will get the CloudFormation stack updated and automatically create an Elasticsearch cluster in a few minutes, handling streaming the data of an @model object type to the Amazon Elasticsearch Service and configuring search resolvers to search the data. In addition to that, the existing DynamoDB table will be enhanced with DynamoDB streams sending data to an automatically created Lambda function that will update Elasticsearch as soon as new notes are added or deleted to keep everything in sync.

NoSQL and Elasticsearch Data Sources setup by @model and @searchable GraphQL Transformers

With a few CLI commands and a couple of schema directives based on GraphQL Transformers, AWS Amplify CLI created a very powerful, secure, highly available, flexible, resilient and scalable back-end in minutes where users can be authenticated and authorized (@auth) then create, read, update, delete and list data (@model) as well as perform full text search (@searchable) on that same data very easily and very fast. Best of all, the whole backend is managed by AWS and you don’t have to worry about any maintenance or operational tasks.

The Cloud Back-End with AWS AppSync GraphQL powered “brains”

To take advantage of the newly implemented search capability deployed in the back-end, update the App.js file and overwrite the content with the following code. We just need 35 extra lines of code to implement the search feature in our front-end:

Adding Search with extra 35 lines of code
“Notes are added, updated or removed safely in DynamoDB and searched in Elasticsearch with complete user content isolation”

Execute amplify serve or amplify publish to either test the new search capability locally or publish the changes to CloudFront/S3. After that, delete any old notes and create some new ones then start searching your Elasticsearch cluster with GraphQL:

The App with (Elastic)Search

Finally, one single command to delete and remove all the back-end cloud services you just created in a couple more minutes. Time to clean up in case you don’t want to keep everything up and running:

$ amplify delete

It is impressive that with less than 200 lines of code in the front-end and only a few minutes to setup the back-end any developer can get so much done. In the past this whole setup would take me hours or days to develop, wire up, secure, configure and deploy. It makes so much easier to test and experiment or implement new app ideas!

AWS Amplify gives us a declarative and easy-to-use API for cloud operations in the front-end. Now with the AWS Amplify CLI, it becomes even easier to deploy and configure your back-end as well as link all the resources within your application in a secure, streamlined and nimble way. It’s a very powerful tool that allows developers to make use of only few commands and few lines of code to create scalable and secure cloud applications and solutions in a matter of minutes. To simply put:

Go build with the AWSome Amplify CLI and create you next CRUDL experiment or project with search capabilities in minutes!

You can find more information on the new AWS Amplify toolchain in the official announcement here or this other great article at Hackernoon.