Nikolas Burk
Written By
Nikolas Burk
Developer @ Prisma

Nikolas is a developer and head of content at Prisma. He is excited about GraphQL as a new API technology and has a passion for learning and sharing knowledge.

Getting Started

Backend

Since this is a frontend track, we don’t want to spend too much time setting up the backend. This is why we use Graphcool, a service that provides a production-ready GraphQL API out-of-the-box.

The Data Model

You’ll use the Graphcool CLI to generate the server based on the data model that we need for the app. Speaking of the data model, here is what the final version of it looks like written in the GraphQL Schema Definition Language (SDL):

type User {
  name: String!
  links: [Link!] @relation(name: "UsersLinks")
  votes: [Vote!] @relation(name: "UsersVotes")
}

type Link {
  url: String!
  postedBy: User @relation(name: "UsersLinks")
  votes: [Vote!] @relation(name: "VotesOnLink")
}

type Vote {
  user: User @relation(name: "UsersVotes")
  link: Link @relation(name: "VotesOnLink")
}

Creating the GraphQL Server

The first thing you need to do is install the Graphcool CLI with npm.

NOTE: This tutorial uses the legacy version of Graphcool and will be updated soon to use the new Graphcool Framework. The CLI commands mentioned in tutorial are outdated, you can read more about the new CLI here. If you still want to go through this tutorial, you can install the old version of the CLI using npm install -g graphcool@0.4.

Now you can go and create the server.

This will execute the graphcool init command with two arguments:

  • --schema: This option accepts a .graphql-schema that’s either stored locally or at a remote URL. In your case, you’re using the schema stored at https://graphqlbin.com/hn-relay.graphql, we’ll take a look at it in a bit.
  • --name: This is the name of the Graphcool project you’re creating, here you’re simply calling it Hackernews.

Note that this command will open up a browser window first and ask you to authenticate on the Graphcool platform.

The schema that’s stored at https://graphqlbin.com/hn-relay.graphql is identical to the one that you just saw.

Once the project was created, you’ll find the Graphcool Project File (project.graphcool) in the directory where you executed the command. It should look similar to this:

# project: cj4liutcbackk01648jagrepi
# version: 1

type File @model {
  contentType: String!
  createdAt: DateTime!
  id: ID! @isUnique
  name: String!
  secret: String! @isUnique
  size: Int!
  updatedAt: DateTime!
  url: String! @isUnique
}

type Link @model {
  createdAt: DateTime!
  id: ID! @isUnique
  postedBy: User @relation(name: "UsersLinks")
  updatedAt: DateTime!
  url: String!
  votes: [Vote!]! @relation(name: "VotesOnLink")
}

type User @model {
  createdAt: DateTime!
  id: ID! @isUnique
  links: [Link!]! @relation(name: "UsersLinks")
  name: String!
  updatedAt: DateTime!
  votes: [Vote!]! @relation(name: "UsersVotes")
}

type Vote @model {
  createdAt: DateTime!
  id: ID! @isUnique
  link: Link @relation(name: "VotesOnLink")
  updatedAt: DateTime!
  user: User @relation(name: "UsersVotes")
}

The top of the file contains some metadata about the project, namely the project ID and the version number of the schema.

The User and File types are generated by Graphcool and have some special characteristics. User can be used for authentication and File for file management.

Also notice that each type has three fields called id, createdAt and updatedAt. These are managed by the system and read-only for you.

Populate The Database & GraphQL Playgrounds

Before you move on to setup the frontend, go ahead and create some initial data in the project so you’ve got something to see once you start rendering data in the app!

You’ll do this by using a GraphQL Playground which is an interactive environment that allows you to send queries and mutations. It’s a great way to explore the capabilities of an API.

This command will read the project ID from the project file and open up a GraphQL Playground for that project in a browser.

The left pane of the Playground is the editor that you can use to write your queries and mutations (and even subscriptions). Once you click the play button in the middle, the response to the request will be displayed in the results pane on the right.

Since you’re adding two mutations to the editor at once, the mutations need to have operation names. In your case, these are CreateGraphcoolLink and CreateRelayLink.

This creates two new Link records in the database. You can verify that the mutations actually worked by either viewing the currently stored data in the data browser (simply click DATA in the left side-menu) or by sending the following query in the already open Playground:

{
  allLinks {
    id
    description
    url
  }
}

If everything wen well, the query will return the following data:

{
  "data": {
    "allLinks": [
      {
        "id": "cj4jo6xxat8o901420m0yy60i",
        "description": "The coolest GraphQL backend 😎",
        "url": "https://graph.cool"
      },
      {
        "id": "cj4jo6z4it8on0142p7q015hc",
        "description": "Highly performant GraphQL client from Facebook",
        "url": "https://facebook.github.io/relay/"
      }
    ]
  }
}  

Frontend

Creating the App

Next, you are going to create the React project! As mentioned in the beginning, you’ll use create-react-app for that.

This will create a new directory called hackernews-react-relay that has all the basic configuration setup.

Make sure everything works by navigating into the directory and starting the app:

cd hackernews-react-relay
yarn start

This will open a browser and navigate to http://localhost:3000 where the app is running. If everything went well, you’ll see the following:

Your project structure should now look as follows:

.
├── README.md
├── node_modules
├── project.graphcool
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.test.js
│   ├── components
│   │   └── App.js
│   ├── index.js
│   ├── logo.svg
│   ├── registerServiceWorker.js
│   └── styles
│       ├── App.css
│       └── index.css
└── yarn.lock

Prepare Styling

This tutorial is about the concepts of GraphQL and how you can use it from within a React application with Relay, so we want to spend the least time on styling issues. To ease up usage of CSS in this project, you’ll use the Tachyons library which provides a number of CSS classes.

Since we still want to have a bit more custom styling here and there, we also prepared some styles for you that you need to include in the project.

Installing Relay Dependencies

Next, you need to pull in the functionality of Relay into your project. In particular, there are three dependencies you need to install:

  1. react-relay: Contains major functionality of the Relay runtime and is responsible for all networking and caching tasks.
  2. relay-compiler: The Relay Compiler is a tool you’ll use at build time to validate and optimize the GraphQL code you’re writing in the project. Read more about it in the official docs.
  3. babel-plugin-relay: Relay leverages a Babel plugin to transform the GraphQL code you write in a project and bring it into the right format for the Relay Compiler. Read more about it in the official docs.

Here is high-level overview on the architecture used for Relay Modern.

Eject from create-react-app to configure Babel

create-react-app hides all the build tooling configurations from you and provides a comfortable spot for starting out. However, in your case you actually need to do some custom Babel configurations to get Relay to work. So you need to eject from create-react-app.

This command essentially opens up the blackbox that was handed to you by create-react-app and let’s you do the build configuration yourself. In this case, you need to add the babel-plugin-relay that you installed in the previous step to the build process.

That’s it already for the Babel configuration. Set up the Relay Environment in the app next!

Creating the Relay Environment

The Relay Environment provides the core of the Relay functionality at runtime by ”[bundling] together the configuration, cache storage, and network-handling that Relay needs in order to operate.”

A Relay Environment needs to be instantiated with two major components:

  1. A Network that knows which GraphQL server it can talk to
  2. A Store that takes care of the caching

This code has been taken from the example in the docs and was only slightly customised.

Let’s quickly discuss the commented sections to understand better what’s going on:

  1. You first import the required JS modules that you need to instantiate and configure the Environment.
  2. Here you instantiate the required Store that will store the cached data.
  3. Now you create a Network that knows your GraphQL server from before, it’s instantiated with a function that returns a Promise of a networking call to the GraphQL API - here that’s done using fetch.
  4. The Network needs to know the server endpoint for your API. In the next step, you’ll replace the placeholder __RELAY_API_ENDPOINT__ with your actual endpoint.
  5. With the store and network available you can instantiate the actual Environment.
  6. Lastly you need to export the environment from this module.

There are two ways for you to get your endpoint. You can either open the Graphcool Console and click the Endoints-button in the bottom-left corner. The second option is to use the CLI which is what you’ll do now.

This command will display four different endpoints that each have a specific purpose. Since you’re using Relay in this tutorial, you need to use the endpoint for the Relay API.

Note: All endpoints follow a similar structure in that there is a fixed portion of the URL and the last part is the ID of your project. For the Relay API, the structure looks as follows: https://api.graph.cool/relay/v1/<project-id>

Downloading the Schema

Before you can start using Relay, you’ll need to download the full GraphQL schema into your project and make it available to the Relay Compiler.

Note: There is a difference between the GraphQL schema that you saw above and a full GraphQL schema. The full schema is required for every GraphQL server since it defines all capabilities of the API by spelling out the Query and Mutation types. However, when using Graphcool, you only define a subset of this schema, namely the types of your data model. The rest of the schema that represents the actual API will then be generated for you.

You’ll download the schema using a tool called get-graphql-schema.

Next, you need to use the endpoint for the Relay API again since that’s where get-graphql-schema will download the schema from.

Notice that the > in the this command means that the output of get-graphql-schema __RELAY_API_ENDPOINT__ will be written to a new file called schema.graphql. This file needs to be placed into the root directory of your project, so the project structure should now look as follows:

.
├── README.md
├── config
├── node_modules
├── project.graphcool
├── schema.graphql
├── package.json
├── public
├── src
└── yarn.lock

That’s it, you’re all set to start loading some data into your app! 🚀

Unlock the next chapter
Which are the two types that you find in every Graphcool project file?
File & User
File & System
Query & Mutation
User & Group