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

Since this is a frontend track, you’re not going to spend any time implementing the backend. Instead, you’ll use the server from the Node tutorial.

Once you created your React application, you’ll pull in the required code for the backend.

Note: The final project for this tutorial can be found on GitHub. You can always use it as a reference whenever you get lost throughout the course of the following chapters. Also note that each code block is annotated with a filename. These annotations directly link to the corresponding file on GitHub so you can clearly see where to put the code and what the end result will look like.

Frontend

Creating the app

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

Note: This tutorial uses Yarn for dependency management. Find instructions for how you can install it here. If you prefer using npm, you can just run the equivalent commands.

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

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

cd hackernews-react-apollo
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:

.../hackernews-react-apollo/src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import './styles/index.css'
import App from './components/App'

Your project structure should now look as follows:

.
├── README.md
├── node_modules
├── 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, so we want to spend the least time possible on styling. To reduce the 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.

Install Apollo Client

Here’s an overview of the packages you just installed:

  • apollo-boost offers some convenience by bundling several packages you need when working with Apollo Client:

    • apollo-client: Where all the magic happens
    • apollo-cache-inmemory: Our recommended cache
    • apollo-link-http: An Apollo Link for remote data fetching
    • apollo-link-error: An Apollo Link for error handling
    • apollo-link-state: An Apollo Link for local state management
    • graphql-tag: Exports the gql function for your queries & mutations
  • react-apollo contains the bindings to use Apollo Client with React.
  • graphql contains Facebook’s reference implementation of GraphQL - Apollo Client uses some of its functionality as well.

That’s it, you’re ready to write some code! 🚀

Configure ApolloClient

Apollo abstracts away all lower-level networking logic and provides a nice interface to the GraphQL server. In contrast to working with REST APIs, you don’t have to deal with constructing your own HTTP requests any more - instead you can simply write queries and mutations and send them using an ApolloClient instance.

The first thing you have to do when using Apollo is configure your ApolloClient instance. It needs to know the endpoint of your GraphQL API so it can deal with the network connections.

Note: The project that was generated by create-react-app uses semicolons and double quotes for strings. All the code that you’re going to add will use no semicolons and mostly single quotes. You’re also free to delete any existing semicolons and replace double with single quotes 🔥

Let’s try to understand what’s going on in that code snippet:

  1. You’re importing the required dependencies from the installed packages.
  2. Here you create the httpLink that will connect your ApolloClient instance with the GraphQL API, your GraphQL server will be running on http://localhost:4000.
  3. Now you instantiate ApolloClient by passing in the httpLink and a new instance of an InMemoryCache.
  4. Finally you render the root component of your React app. The App is wrapped with the higher-order component ApolloProvider that gets passed the client as a prop.

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

Backend

Downloading the server code

As mentioned above, for the backend in this tutorial you’ll simply use the final project from the Node tutorial.

Note: If you are on Windows, you may want to install Git CLI to avoid potential problems with commands such as curl.

You now have a new directory called server inside your project that contains all the code you need for your backend.

Before we start the server, let’s quickly understand the main components:

  • database: This directory holds all the files that relate to your Prisma database service.

    • prisma.yml is the root configuration file for the service.
    • datamodel.graphql defines your data model in the GraphQL Schema Definition Language (SDL). The data model is the foundation for the GraphQL API generated by Prisma which provides powerful CRUD operations for the types in the data model.
  • src: This directory holds the source files for your GraphQL server.

    • schema.graphql contains your application schema. The application schema defines the GraphQL operations you can send from the frontend. We’ll take a closer look at this file in just a bit.
    • generated/prisma.graphql contains the auto-generated Prisma database schema. The Prisma schema defines powerful CRUD operations for the types in your data model. Note that you should never edit this file manually since it gets automatically updated when the data model changes.
    • resolvers contains the resolver functions for the operations defined in the application schema.
    • index.js is the entry point for your GraphQL server.

From the mentioned files, only the application schema defined in server/src/schema.graphql is relevant for you as a frontend developer. This file contains the GraphQL schema which defines all the operations (queries, mutations and subscriptions) you can send from your frontend app.

Here is what it looks like:

.../hackernews-react-apollo/server/src/schema.graphql
# import Link, Vote, LinkSubscriptionPayload, VoteSubscriptionPayload from "./generated/prisma.graphql"

type Query {
  feed(filter: String, skip: Int, first: Int, orderBy: LinkOrderByInput): Feed!
}

type Feed {
  links: [Link!]!
  count: Int!
}

type Mutation {
  post(url: String!, description: String!): Link!
  signup(email: String!, password: String!, name: String!): AuthPayload
  login(email: String!, password: String!): AuthPayload
  vote(linkId: ID!): Vote
}

type AuthPayload {
  token: String
  user: User
}

type User {
  id: ID!
  name: String!
  email: String!
}

type Subscription {
  newLink: LinkSubscriptionPayload
  newVote: VoteSubscriptionPayload
}

This schema allows for the following operations:

  • Queries:

    • feed: Retrieves all links from the backend, note that this query also allows for filter, sorting and pagination arguments
  • Mutations:

    • post: Allows authenticated users to create a new link
    • signup: Create an account for a new user
    • login: Login an existing user
    • vote: Allows authenticated users to vote for an existing link
  • Subscriptions:

    • newLink: Receive realtime updates when a new link is created
    • newVote: Receive realtime updates when a vote was submitted

For example, you can send the following feed query to retrieve the first 10 links from the server:

{
  feed(skip: 0, first: 10) {
    links {
      description
      url
      postedBy {
        name
      }
    }
  }
}

Or the signup mutation to create a new user:

mutation {
  signup(
    name: "Sarah",
    email: "sarah@graph.cool",
    password: "graphql"
  ) {
    token
    user {
      id
    }
  }
}

Deploying the Prisma database service

There is one thing left to do before you can start your server and begin sending queries and mutations to it. The Prisma database service needs to be deployed so the server can access it.

To deploy the service all you need to do is install the server’s dependencies and invoke the prisma deploy command inside the server directory.

Note that you can also omit yarn prisma in the above command if you have the prisma CLI installed globally on your machine (which you can do with yarn global add prisma). In that case, you can simply run prisma deploy.

Note: If you ever lose the endpoint, you can get access to it again by running yarn prisma info.

Exploring the server

With the proper Prisma endpoint in place, you can now explore the server!

The yarn dev executes the dev script defined in package.json. The script first starts the server (which is then running on http://localhost:4000) and then opens up a GraphQL Playground for you to explore and work with the API. Note that if you only want to start the server without opening a Playground, you can do so by running yarn start.

A Playground is a “GraphQL IDE”, providing an interactive environment that allows to send queries, mutations and subscriptions to your GraphQL API. It is similar to a tool like Postman which you might know from working with REST APIs, but comes with a lot of additional benefits.

The first thing to note about the Playground is that it has built-in documentation for its GraphQL API. This documentation is generated based on the GraphQL schema and can be openend by clicking the green SCHEMA-button on the right edge of the Playground. Consequently, it shows you the same information you saw in the application schema above:

Another important thing to note about the Playground is that it actually allows you to interact with two(!) GraphQL APIs.

The first one is defined by your application schema, this is the one your React application will interact with. It can be opened by selecting the default Playground in the app project in the left side-menu.

There also is the Prisma database API which provides full access to the data stored in the database. This one you can open by selecting the dev Playground in the database project in the left side-menu. This API is defined by the Prisma schema (in server/src/generated/prisma.graphql).

Note: The Playground receives the information about the two GraphQL APIs from the .graphqlconfig.yml file which lists the two projects app and database. That’s why it can provide you access to both.

Why do you need two GraphQL APIs at all? The answer is pretty straightforward, you can actually think of the two APIs as two layers.

The application schema defines the first layer, also called application layer. It defines the operations your client applications will be able to send to your API. This includes business logic as well as other common features and workflows (such as signup and login).

The second layer is the database layer defined by the Prisma schema. It provides powerful CRUD operations that allow you to perform any kind of operation against the data in your database.

Here is an overview of the architecture of the app:

Note: It is of course possible to only use the database API from the frontend. However, in most real-world applications you’ll need at least a little bit of business logic which the API can not provide. If your app really only needs to perform CRUD operations and access a database, then it’s totally fine to run against the Prisma database API directly.

The left pane of the Playground is the editor that you can use to write your queries, mutations and subscriptions. Once you click the play button in the middle, your request is sent and the server’s response 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 CreatePrismaLink and CreateApolloLink.

This creates two new Link records in the database. You can verify that the mutations actually worked by sending the following query in the already open Playground:

{
  feed {
    links {
      id
      description
      url
    }
  }
}

Note: You can also send the feed query in the default Playground in the app section.

If everything went well, the query will return the following data (the ids will of course be different in your case since they were generated by Prisma and are globally unique):

{
  "data": {
    "feed": {
      "links": [
        {
          "id": "cjcnfwjeif1rx012483nh6utk",
          "description": "The best GraphQL client",
          "url": "https://www.apollographql.com/docs/react/"
        },
        {
          "id": "cjcnfznzff1w601247iili50x",
          "description": "Prisma turns your database into a GraphQL API 😎",
          "url": "https://www.prismagraphql.com"
        }
      ]
    }
  }
}

Fantastic, your server works! 👏

Unlock the next chapter
Why are there two GraphQL API layers in a backend architecture with Prisma?
To increase robustness and stability of the GraphQL server (if one layer fails, the server is backed by the second one).
To increase performance of the GraphQL server (requests are accelerated by going through multiple layers).
Prisma provides the database layer which offers CRUD operations. The second layer is the application layer for business logic and common workflows (like authentication).
Having two GraphQL layers is a hard requirement by the GraphQL specification.