Create a cloud-enabled GraphQL API with AWS Amplify and Vue
Tags: aws, amplify, vue, graphql
Published: 2020-09-28 20:49:56

![Image for post](https://miro.medium.com/max/2048/1*Z0LTXNIhY0CIzhEa-wDVsQ.png)

In this tutorial, we will learn how to build a GraphQL data-driven serverless app using **Vue**, **AWS Amplify** and **AWS AppSync**. We will create a new project with Vue, generate a serverless GraphQL API using **AWS AppSync** and build a client to consume it including real-time. We will cover:

*   Introduction to **AWS AppSync**
*   Setting up a new project with the **Vue CLI**
*   Creating a new **GraphQL API** and using your first **GraphQL transform**
*   Pushing your **GraphQL API** to the cloud
*   Building the **client**: adding queries, mutations and real-time
*   Publishing your app via the **AWS Amplify Console**
*   Cleaning up **cloud services**

> _In order to follow this post you will need a basic knowledge of GraphQL. You can learn the basics following this tutorial at_ [_graphql.org_](https://graphql.org/learn/)_._

\> Final solution and step by step tutorial in [GitHub](https://github.com/gsans/fullstack-serverless-amplify-ui-vue).

Please let me know if you have any questions or want to learn more at [@gerardsans](https://twitter.com/intent/user?screen_name=gerardsans).

Introduction to AWS AppSync
===========================

**AWS AppSync** allows you to create highly scalable serverless GraphQL data-driven mobile and web apps by providing an open source **Amplify** **Framework** (consisting of AWS AppSync Clients, GraphQL transforms and the CLI), integrations with multiple **data sources**, and the **AWS AppSync console**.

*   **GraphQL client**: client-side library to securely access data from your GraphQL API. Built-in support for real-time and offline/delta client synchronisation.
*   **Amplify CLI**: set of commands, via the`api` category, to automate the setup and provision of resources for AWS AppSync and Amazon API Gateway cloud services. Support for REST and GraphQL APIs.
*   **GraphQL Transforms**: custom GraphQL schema directives that can be used in your GraphQL schema to enable custom workflows.
*   **Data sources**: databases (Amazon DynamoDB for NoSQL, Amazon Aurora for RDBMS), searches (Amazon Elasticsearch Service), and AWS Lambda functions.

By using AWS AppSync, teams can quickly create highly scalable serverless GraphQL data-driven apps for mobile and web while leaving the heavy lifting to the Amplify CLI.

![Image for post](https://miro.medium.com/max/3900/0*VZZC4W0cAnNKaMP3.png)

AWS AppSync data-driven apps architecture overview

Setting up a new project with the Vue CLI
=========================================

Before moving to the next section, please complete the steps described in “[Build your first full-stack serverless app with Vue](https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-14k4)”.

Creating a new GraphQL API
==========================

For this post we are going to create a GraphQL API to list our favourite restaurants. To create it, we will use the following command:

```
amplify add api
```

Answer the following questions

*   Please select from one of the below mentioned services **GraphQL**
*   Provide API name: **RestaurantAPI**
*   Choose the default authorization type for the API **API key**
*   Enter a description for the API key: **(empty)**
*   After how many days from now the API key should expire (1–365): **7**
*   Do you want to configure advanced settings for the GraphQL API **No, I am done.**
*   Do you have an annotated GraphQL schema? **No**
*   Choose a schema template: **Single object with fields (e.g., “Todo” with ID, name, description)**
*   Do you want to edit the schema now? **Yes**

When prompted, replace the default schema with the following:

```
type Restaurant @model {  
  id: ID!  
  name: String!  
  description: String!  
  city: String!  
}
```

You should be familiar with everything in the GraphQL schema above but for the `@model` directive. This is a GraphQL transform provided by AppSync.

Using your first GraphQL transform
==================================

GraphQL transforms allow AppSync to provide further customisation and support for common scenarios, so you don’t have to.

By adding`@model` to the`Restaurant`type we are telling the Amplify CLI runtime to create the resolvers to support queries, mutations and subscriptions in DynamoDB. Besides the regular CRUD operations, we are also getting some more advanced features like pagination and filtering that we are going to cover later.

Once we apply`@model` to a type we get access to these other transforms:

*   `@key` to configure custom index structures in **DynamoDB**
*   `@searchable` to enable searches using **Amazon Elasticsearch** Service
*   `@connection` to add relationships between types
*   `@lambda` to generate **AWS Lambda** resolvers
*   `@auth` to add fine grained multi-authorisation support
*   `@versioned` to add conflict resolution for offline scenarios

Learn how to use each transform in detail from the [official docs](https://docs.amplify.aws/cli/graphql-transformer/directives).

> _GraphQL Transforms are implemented using custom GraphQL schema directives as defined in the_ [_GraphQL specification_](https://graphql.github.io/graphql-spec/draft/#sec-Language.Directives)_._

Pushing your GraphQL API to the cloud
=====================================

Let’s run the push command to create the GraphQL API and see the results of using the `@model` transform:

```
amplify push
```

*   Are you sure you want to continue? **Yes**
*   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**

Write down your **GraphQL endpoint** and **API KEY**.

Run the command below to access the **AWS AppSync console**.

```
amplify console api
```

*   Please select from one of the below mentioned services **GraphQL**

Testing your new GraphQL API
============================

Once in the AWS AppSync console, click on **Queries** on the left side. This will open an editor that we can use to edit and test GraphQL queries.

Execute the following mutation to create a new restaurant:

```
mutation createRestaurant {  
  createRestaurant(input: {  
    name: "Nobu"  
    description: "Great Sushi"  
    city: "New York"  
  }) {  
    id name description city  
  }  
}
```

Now, run this query to list the restaurant we just added:

```
query listRestaurants {  
  listRestaurants {  
    items {  
      id  
      name  
      description  
      city  
    }  
  }  
}
```

Besides creating all common CRUD operations for your types, AWS AppSync also creates extra utility features like filters. Run this query to try using filters:

```
query searchRestaurants {  
  listRestaurants(filter: {  
    city: {  
      contains: "New York"  
    }  
  }) {  
    items {  
      id  
      name  
      description  
      city  
    }  
  }  
}
```

AWS AppSync creates filters on GraphQL scalar types (ID, String, Int, Float, Boolean) for list operations like listRestaurants.

Querying data with queries
==========================

In the earlier sections, we made sure we had a working GraphQL API. On the client, we will start by displaying a list.

```
<template>  
  <div v-for="restaurant of restaurants" :key="restaurant.id">  
    {{restaurant.name}}  
  </div>  
</template>  
<script>  
import { API, graphqlOperation } from 'aws-amplify';  
import { listRestaurants } from './graphql/queries';  
  
export default {  
  name: 'app',  
  data() {  
    return {  
      restaurants: [],  
    }  
  },  
  created() {  
    this.getData();  
  },  
  methods: {  
    async getData() {  
      try {  
        const response = await API.graphql(graphqlOperation(listRestaurants));  
        this.restaurants = response.data.listRestaurants.items;  
      }  
      catch (error) {  
        console.log('Error loading restaurants...', error);  
      }  
    },  
  }  
}  
</script>
```

From the code above, we are using `API.graphql`to run the `listRestaurants`query within `getData`. Queries were created by the Amplify CLI during the push command. This call returns a promise that we handle by using async/await and render the result using `v-for`.

You might be wondering why we used `listRestaurants.items`. This is because AWS AppSync created an intermediate type `ModelRestaurantConnection`. This is so we can handle pagination scenarios together with`limit` and `nextToken`parameters.

```
listRestaurants(filter: ModelRestaurantFilterInput, limit: Int, nextToken: String): ModelRestaurantConnection 
type ModelRestaurantConnection {  
 items: [Restaurant]  
 nextToken: String  
}
```

Creating data with mutations
============================

In order to add new restaurants, we are going to create a data entry using `form` to take the required user input and pass it forward to the **createRestaurant** mutation.

```
<template>  
  <div>  
    <form v-on:submit.prevent>  
      <div>  
        <label>Name: </label>  
        <input v-model='form.name' class='input' />  
      </div>  
      ...  
      <button @click='createRestaurant' class='button'>Create</button>  
    </form>  
  </div>  
</template>  
<script>  
import { createRestaurant } from './graphql/mutations';  
  
export default {  
  name: 'app',  
  data() {  
    return {  
      form: { },  
    }  
  },  
  methods: {  
    async createRestaurant() {  
      const { name, description, city } = this.form  
      if (!name || !description || !city) return;  
      
      const restaurant = { name, description, city };  
      try {  
        const response = await API.graphql(graphqlOperation(createRestaurant, { input: restaurant }))  
        console.log('Item created!')  
        this.restaurants = [...this.restaurants, response.data.createRestaurant];  
        this.form = { name: '', description: '', city: '' };  
      } catch (error) {  
        console.log('Error creating restaurant...', error)  
      }  
    },  
  }  
}  
</script>
```

Note how AWS AppSync instead of passing each field as an argument created an input type `CreateRestaurantInput` which makes our client code simpler and convenient.

```
type Mutation {  
 createRestaurant(input: CreateRestaurantInput!): Restaurant  
}input CreateRestaurantInput {  
 id: ID  
 name: String!  
 description: String!  
 city: String!  
}
```

As we did before with queries, we are using async/await to run our mutation as we submit the form via `onCreate`. Once we get the result, we use the form data to update the list and clear the form inputs.

Adding real-time with subscriptions
===================================

To demonstrate real-time, we are going to use a subscription to update AppSync clients when new restaurants are added. AppSync clients will subscribe to listen for changes going through our GraphQL API. More specifically, restaurant creation mutations.

```
import { onCreateRestaurant } from './graphql/subscriptions';  
  
export default {  
  name: 'app',  
  created() {  
    //Subscribe to changes  
    API.graphql(graphqlOperation(onCreateRestaurant))  
    .subscribe((sourceData) => {  
      const newRestaurant = sourceData.value.data.onCreateRestaurant  
      if (newRestaurant) {  
        // skip our own mutations and duplicates  
        if (this.restaurants.some(r => r.id == newRestaurant.id)) return;  
        this.restaurants = [newRestaurant, ...this.restaurants];  
      }   
    });  
  },  
}
```

We use `created`to setup the subscription and immediately `subscribe` to start listening for notifications. Then for each notification, we will update our list of restaurants with changes.

Publishing your app via the AWS Amplify Console
===============================================

The first thing you need to do is **create a new repo** for this project. Once you’ve created the repo, copy the URL for the project to the clipboard and initialise git in your local project:

```
git init  
git remote add origin [repo@repoofyourchoice.com](mailto:repo@repoofyourchoice.com):username/project-name.git  
git add .git commit -m 'initial commit'git push origin master
```

Next visit the [**AWS Amplify Console**](https://aws.amazon.com/amplify/console/) in your **AWS account**. Click **Get Started** to create a new deployment. Next, authorise your repository provider as the repository service. Next, choose the new repository and branch for the project you just created and click **Next**. In the next screen, create a new role and use this role to allow the **AWS Amplify Console** to deploy these resources and click **Next**. Finally, click **Save** and **Deploy** to deploy your application!

![Image for post](https://miro.medium.com/max/2048/0*fDb9ioULhBGsn-IW.png)

AWS Amplify Console deployment steps.

Cleaning up cloud services
==========================

If at any time, you would like to delete a service from your project and your **AWS Account**, you can do this by running:

```
amplify delete
```

Conclusion
==========

Congratulations! You successfully built your first **GraphQL API** using **Vue** and **AWS AppSync**. Thanks for following this tutorial.

If you prefer, you can follow the instructions in this video to build the same app but deploying to **Amazon Cloudfront** and **Amazon S3**.

{% youtube CAueVfEYn6s %}

Thanks for reading!
===================

Have you got any questions regarding this tutorial or **AWS Amplify**? Feel free to reach out to me anytime at [@gerardsans](https://twitter.com/intent/user?screen_name=gerardsans).

![Image for post](https://miro.medium.com/max/720/1*J9DNmPDsRts_0lMUliXwBw.jpeg)

> My Name is [Gerard Sans](https://twitter.com/gerardsans). I am a Developer Advocate at [AWS Mobile](https://aws.amazon.com/products/mobile) working with [AWS Amplify](https://aws-amplify.github.io/) and [AWS AppSync](https://aws.amazon.com/appsync/) teams.
> GraphQL is an open source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.