Previous page: How to build a real-time chat app
Create the GraphQL API
Setup GraphQL with Apollo Server
We will setup Apollo Server that will manage communication for our GraphQL service. This will also be configured with an Express server as middleware that will allow us to add more endpoints such as a healthcheck endpoint.
In your terminal or command prompt, change to your project directory. If you're already in the wep-app directory, use the following:
cd ../
Run the following command to clone a boilerplate project. This repo has minimal setup needed for this tutorial from github:
git clone https://github.com/saedwards/messaging-web-api-boilerplate
A folder called web-api will be created in your project folder. The project sets up some key dependencies such as Apollo Server, Express and GraphQL aswell as the Slack client to communicate with the messaging service.
Next, run npm install
to install project dependencies.
It's worth taking some time to look at the index.js
file created. Inside
there lives the configuration for our server. It includes the GraphQL Schema
where we will define the shapes of data that our GraphQL endpoint accepts. It
also sets up the Apollo Server, Express middleware with registration of our
GraphQL Schema to the Apollo Server.
A short introduction to GraphQL schemas
Defining queries within our GraphQL schema
Next we will define a query for retrieving a list of messages in the GraphQL
schema. From your project folder, open the file web-api/index.js
in your
favourite IDE.
Below our import statements, we will change our type definitions to define a query that will describe retrieving a list of all messages.
Change from:

const typeDefs = gql`
type Query {
test: string
}
}`;
Change to:

const typeDefs = gql`
type Query {
messages(max: Int): [Message]
}
}`;
Here we've defined a query that will resolve to a list of Message objects.
This is denoted by [Message]
surrounded by square brackets to indicate a
collection returned. We also specify a variable for the query called max
,
which is typed as an integer. As you might have guessed, we will use this
variable to limit the amount of messages returned in the query.
Next we need to define our Message model. Create the following folder structure
and file within the web-api directory: api/messages/message.model.js
. Within
this file add the following code.

const { gql } = require('apollo-server-express');
const messageGQL = gql`
type Message {
id: ID
userId: String
text: String
timestamp: String
fromYou: Boolean
#user: User
}
`;
module.exports = { messageGQL };
This will be the shape of our Message
object returned from our GraphQL API.
It includes a userId
, which will be used to fetch the user before the model
is constructed, a text
property to store the actual message that was sent,
a timestamp
to know when the message was sent, which will help in ordering
messages. It includes a fromYou
flag to indicate whether the message was
sent from the anonymous user, which will help to customise the UI for the person
using our app. And a user
property to store details of the user associated
with the message.
Note the user
property of our Message model is commented out for now. Back
in our index.js
file, we need to import the new file and add the Message
model to our GraphQL Schema.

//Existing code...
const { messageGQL } = require('./api/messages/message.model');
const typeDefs = gql`
#...
${messageGQL}
`;
We need to define a user model for each message so we can associate a message to an individual.
Create the following folder structure and file within the web-api directory:
api/messages/user.model.js
Within this file add the following code.

const { gql } = require('apollo-server-express');
const userGQL = gql`
type User {
id: ID
name: String
colour: String
avatarUrl: String
}
`;
module.exports = { userGQL };
The User
object will store information about the user that we'll use to
format individual messages. Again, we need to add the User
model to our
main schema by using the userGQL
export:

//Existing code...
const { messageGQL } = require('./api/messages/message.model');
const { userGQL } = require('./api/users/user.model');
const typeDefs = gql`
#...
${messageGQL}
${userGQL}
`;
Our Message
model can now reference our new User
type in file
api/messages/message.model.js
by removing the line comment #
before the user
property (to leave user: User
):

const messageGQL = gql`
type Message {
#...
user: User
}
`;
These are all the GraphQL models that we will need to build our messaging application.
Apollo Server gives us some useful tools to test requests
against our schema and view responses. From the web-api root in your terminal or
console, run node index.js
to start the GraphQL server.
Open the GraphQL playground at
http://localhost:4123/graphql.
Click the SCHEMA tab on the right-hand side. In here you'll see all the model
types that we've defined. These are the shapes of our requests and responses.
Click the top-level messages
query to view what a type of Message
looks
like. Most properties are primitives such as strings or booleans. Click the
user property to see our custom User
type that is to be associated with each
message.
This tool is very useful for developing and understanding GraphQL schemas without the need of running your application to test data requests/responses.
Collapse the SCHEMA tab. You'll see a play button with two panels either side. The left panel is where we can structure our requests, the right panel is where we view the server response after we send our request.
Copy and paste the following code into the left panel:
query Messages {
messages(max: $max) {
userId
text,
timestamp
user {
id
name
colour,
avatarUrl
}
}
}
This is an example of a GraphQL query that we can send from our application as a string in a request body to retrieve a list of messages. The properties specified correspond to the data we would expect to receive in each message of the response. To build the response, GraphQL will need to make a request to a data source for message data and in separate requests fetch the user for each message.
The great thing about this is, if the application doesn't need properties such as the user when displaying a message and doesn't include this in the request, the GraphQL API will not do anything to fetch any user data associated with each message even though we called the same endpoint. This will increase user-perceived performance and response-times, whilest also reducing server load.
Below the request panel under 'Query Variables' insert the following code:
{
"max": 10
}
Variables can be used to populate different values for the same query. We are
going to restrict the amount of messages we send back in the response by
specifying a max
variable of 10
, which we will use to limit the response
to sending 10 messages of data.
Next we will create a query to retrieve a list of messages
Previous page: How to build a real-time chat app