8 steps to building your own serverless GraphQL API using AWS Amplify
Follow these steps to create an AWS AppSync API that connects to a React client-side application using the new AWS Amplify CLI. Learn More!
Jun 08, 2023 • 9 Minute Read
8 steps to building your own serverless GraphQL API using AWS Amplify
With the release of the new AWS Amplify CLI, developers now have the ability to scaffold AWS AppSync GraphQL APIs from the command line.
In this post, we’ll learn how to use the CLI to create an AWS AppSync API, as well as how to connect your new API to a client-side web or mobile application.
The CLI can automatically create a fully functional GraphQL API including datasources, resolvers, & additional schema for mutations, subscriptions, & queries. We can also update & delete the schema, datasources, & resolvers in our API directly from our local environment.
Amplify GraphQL Transform
We also have the ability to add powerful features such as Elasticsearch, user authorization, & data relations using the Amplify GraphQL Transform library directly from the CLI in our local environment.
Amplify GraphQL Transform is a library for simplifying the process of developing, deploying, and maintaining GraphQL APIs. With it you define your API using the GraphQL Schema Definition Language (SDL) and then pass it to the library where it is transformed and implements your API’s data model in AWS AppSync.
While the library comes with transformers to do most of the work you would need to build a typical API, you can also even write your own GraphQL Transformer.
For example, if we wanted to scaffold out a GraphQL API that created a data-source, resolvers, schema, & then streamed all data to Elasticsearch we could create the following type & push it up using the AWS Amplify CLI:
type Pet @model @searchable {
id: ID!
name: String!
description: String
}
In the above schema, the annotations @model
& @searchable
will create the datasources & all of the resources automatically for us.
There is also a @connection
annotation that allows you to specify relationships between @model
object types & an @auth
annotation that allows you to specify authorization schemes within your GraphQL API.
Let’s look at how to create a new AWS Appsync API using the Amplify CLI with the Amplify GraphQL Transform library & connect it to a client-side React application.
1. Install & configure the CLI
First, we’ll install the AWS Amplify CLI:
npm i -g @aws-amplify/cli
With the AWS Amplify CLI installed, we now need to configure it with an IAM User:
amplify configure
For a video walkthrough of how to configure the AWS Amplify CLI, click here.
2. Connect the API to a client app
Next, we’ll create a new React app & change into the new directory:
npx create-react-app blog-app
cd blog-app
Now we’ll need to install the AWS Amplify client libraries:
yarn add aws-amplify aws-amplify-react
# or
npm install --save aws-amplify aws-amplify-react
3. Initialize the AWS Amplify project
From within the root directory or the newly created React app, let’s initialize a new AWS Amplify project:
amplify init
When asked if you’d like to use an AWS profile, choose Yes, using the profile we created when we configured the project earlier.
Once the project has been initialized, we’ll add the GraphQL API feature to our Amplify project:
amplify add api
This will walk us through the following steps to create the AWS AppSync GraphQL API:
- Please select from one of the below mentioned services: GraphQL
- Provide API name: blogapp
- Choose an authorization type for the API: API_KEY
- Do you have an annotated GraphQL schema?: N
- Do you want a guided schema creation? Y
- What best describes your project: One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”)
- Do you want to edit the schema now? Y
This will open a pre-populated Schema in your editor of choice & also give you the local file path of the new schema that was created.
Let’s take a look at the Schema. We’ll also make a small update by adding the content
field to the Post
type. Once you’ve updated the Schema, go ahead and save the file:
type Blog @model {
id: ID!
name: String!
posts: [Post] @connection(name: "BlogPosts")
}
type Post @model {
id: ID!
title: String!
content: String!
blog: Blog @connection(name: "BlogPosts")
comments: [Comment] @connection(name: "PostComments")
}
type Comment @model {
id: ID!
content: String
post: Post @connection(name: "PostComments")
}
In the above schema, we see that the Post
& Blog
types have the @model
annotation. Object types that are annotated with @model
are top-level entities in the generated API. When pushed, they will create DynamoDB tables as well as additional Schema & resolvers to hook everything together.
To learn more about the @model annotation, click here.
We also see the @connection
annotation used in the types. The @connection
annotation enables you to specify relationships between @model
object types. Currently, @connection
supports one-to-one, one-to-many, and many-to-one relationships. An error is thrown if you try to configure a many-to-many relationship.
To learn more about the
@connection
type, click here.
With the schema ready to go, we can now push everything to execute the creation of the resources:
amplify push
Once the resources are created, we’re ready to create the app & begin interacting with the API.
We can also now view the API in the AWS AppSync dashboard by clicking on the new API name.
From the AWS AppSync dashboard we can also begin executing queries & mutations by clicking on Queries in the left menu:
Let’s try to create a new blog with posts & comments & then query for the blog data.
In the AWS AppSync dashboard, click on Queries.
First, we’ll create a new blog:
mutation createBlog {
createBlog(input: {
name: "My Programming Blog"
}) {
id
name
}
}
Next, we’ll create a new post in this blog (replace the postBlogId
with the id returned from the above mutation):
mutation createPost {
createPost(input: {
title: "Hello World from my programming blog"
content: "Welcome to my blog!"
postBlogId: "bcb298e6-62ec-4614-9ab7-773fd811948e"
}) {
id
title
}
}
Now, let’s create a comment for this post (replace commentPostId
with the ID returned from the above mutation):
mutation createComment {
createComment(input: {
content: "This post is terrible"
commentPostId: "ce335dce-2c91-4fed-a953-9ca132f129cf"
}) {
id
}
}
Finally, we can query the blog to see all articles & comments (replace the ID with the id of your blog):
query getBlog {
getBlog(id: "bcb298e6-62ec-4614-9ab7-773fd811948e") {
name
posts {
items {
comments {
items {
content
}
}
title
id
content
blog {
name
}
}
}
}
}
4. Connect to the API from React
To connect to the new API, we first need to configure our React project with our Amplify project credentials. You will notice a new file called aws-exports.js
located in the src directory. This file holds all of the information our local project needs to know about our cloud resources.
To configure the project, open src/index.js
& add the following below the last import:
import Amplify from '@aws-amplify/core'
import config from './aws-exports'
Amplify.configure(config)
Now, we can begin performing mutations, queries & searches against the API.
The definitions for the GraphQL mutations that we will be executing will look like the this:
// Create a new blog
const CreateBlog = `mutation($name: String!) {
createBlog(input: {
name: $name
}) {
id
}
}`
// Create a post and associate it with the blog via the "postBlogId" input field
const CreatePost = `mutation($blogId:ID!, $title: String!, $content: String!) {
createPost(input:{
title: $title, postBlogId: $blogId, content: $content
}) {
id
}
}`
// Create a comment and associate it with the post via the "commentPostId" input field
const CommentOnPost = `mutation($commentPostId: ID!, $content: String) {
createComment(input:{
commentPostId: $commentPostId, content: $content
}) {
id
}
}`
The definition for the GraphQL query that we will be executing will look like this:
// Get a blog, its posts, and its posts comments
const GetBlog = `query($blogId:ID!) {
getBlog(id:$blogId) {
id
name
posts {
items {
id
title
content
comments {
items {
id
content
}
}
}
}
}
}`
5. Configure the client application
The first thing to do is configure Amplify with your web application. In the root of your app (in React this will be src/index.js
), below the last import, add the following code:
import Amplify from 'aws-amplify'
import config from './aws-exports'
Amplify.configure(config)
Now, we can begin executing operations agains the API.
6. Perform mutations from the client
Creating a new blog:
// import the API & graphqlOperation helpers as well as the mutation
import { API, graphqlOperation } from 'aws-amplify'
import { CreateBlog } from './your-graphql-definition-location'
// next, we create a function to interact with the API
state = { blogName: '' }
createBlog = async () => {
const blog = { name: this.state.blogName }
await API.graphql(graphqlOperation(CreateBlog, blog))
console.log('blog successfully created')
}
Creating a post for a blog:
// import the API & graphqlOperation helpers as well as the mutation
import { API, graphqlOperation } from 'aws-amplify'
import { CreatePost } from './your-graphql-definition-location'
// next, we create a function to interact with the API
state = { postTitle: '' , postContent: '' }
createBlog = async () => {
const post = {
title: this.state.postTitle,
content: this.state.postContent,
postBlogId: this.props.blogId // Or where your blogId data lives
}
await API.graphql(graphqlOperation(CreatePost, post))
console.log('post successfully created')
}
Commenting on a post:
// import the API & graphqlOperation helpers as well as the mutation
import { API, graphqlOperation } from 'aws-amplify'
import { CommentOnPost } from './your-graphql-definition-location'
// next, we create a function to interact with the API
state = { content: '' }
createBlog = async () => {
const comment = {
content: this.state.content,
commentPostId: this.props.commentPostId // Or where your commentPostId data lives
}
await API.graphql(graphqlOperation(CommentOnPost, comment))
console.log('comment successfully created')
}
7. Perform queries from the client
Listing blog with posts & post comments:
// import the API & graphqlOperation helpers as well as the query
import { API, graphqlOperation } from 'aws-amplify'
import { GetBlog } from './your-graphql-definition-location'
// next, we create a function to interact with the API
getBlog = async () => {
const data = await API.graphql(graphqlOperation(GetBlog, { id: this.props.blogId }))
console.log('blog successfully fetched', data)
}
8. Modify the schema
If at any time you would like to modify the schema to add, update or delete anything, you can open the file where the schema is located, make your edits, & then run amplify push
to update your AWS AppSync API.
Video Walkthrough
In this video walkthrough, we create an AWS AppSync GraphQL API using the Amplify CLI & connect it to a React application.
If you’re interested in learning more about building GraphQL APIs using AWS AppSync, follow Adrian Hall & check out his post Build a GraphQL Service the easy way with AWS Amplify Model Transforms.
My Name is Nader Dabit . I am a Developer Advocate at AWS Mobile working with projects like AWS AppSync and AWS Amplify, the author of React Native in Action, & the editor of React Native Training & OpenGraphQL.