DEV Community

Cover image for An introduction to GraphQL and how to use GraphQL APIs
Salma Alam-Naylor
Salma Alam-Naylor

Posted on • Originally published at contentful.com

An introduction to GraphQL and how to use GraphQL APIs

I’ve been using the Contentful GraphQL API pretty extensively for the past year to build a variety of projects on the Jamstack, and I got sucked in pretty quickly without really knowing much about the inner workings of GraphQL. While it’s easy to start making your first query with GraphQL with very little research, I thought it would be useful to consolidate all I’ve learned throughout the year and provide a high-level introduction to GraphQL for anyone interested in getting started.

What is an API?

API stands for Application Programming Interface, which is a way to communicate between different software services. Different types of APIs are used in programming hardware and software, including Web APIs — like the APIs that Contentful provides. If you’re new to development, I recommend you check out this blog post — What is an API? — to get a good grounding on APIs and the role they play in web development.

A brief history of GraphQL

GraphQL is a language used to communicate with backend systems, allowing you to fetch and manipulate your data. It was developed by Facebook in 2012, and released to the public in 2015. In 2019, the project was moved to the non-profit GraphQL Foundation, with a mission to ensure that the GraphQL community is able to focus on its continued evolution on a neutral platform.

What does GraphQL mean?

GraphQL is language-agnostic, which means it can be used with any backend framework or programming language, and is essentially an addition to a backend service that allows developers to communicate with the database and request data in a specific way.

To create a GraphQL server for your data source, you can use specialized tools such as ApolloGraphQL, which allow you to create a layer on top of your backend and database(s), enabling your data to be represented, queried and changed via the Graph Query Language.

And finally, GraphQL stands for “Graph Query Language.” Let’s unpack what we mean by “graph” and “query language.”

Your data, represented in a graph

GraphQL creates a representation of your data that is designed to feel familiar and natural, like a visual graph. The Oxford Learner’s Dictionary defines a graph as:

[A] diagram consisting of a line or lines, showing how two or more sets of numbers are related to each other.

The graph part of GraphQL describes a data structure of a collection of objects — or nodes — that are connected to each other through a set of links, or edges. Relationships between different objects can be represented in a user interface as a result of this graph structure. The key concept is that the data structure is non-linear, meaning that one object can be connected to more than one other object, and relationships can also be circular.

There are specialized tools available, such as GraphiQL, to represent the relationships between node types on a GraphQL API. Here’s a screenshot from another great tool — the GraphQL Playground app available in Contentful’s app marketplace — showing the relationships between data in the Contentful space that powers my personal website. Notice how you can drill down and inspect the data types in each content type, and understand how they are related to each other.

A screenshot of the GraphQL playground in Contentful, showing the docs tabs open, showing the connection between objects or nodes in the GraphQL schema. In this particular example, a blogPost node contains an author node, which contains an image node, which contains a fileName of type String.

In this particular example, a blogPost node contains an author node, which contains an image node, which contains a fileName of type String. Trace the relationships down the tree by following the highlighted nodes.

Being able to inspect all types that exist in your data is a really powerful tool with predictable results to help you build robust and scalable applications. You might already be starting to realize that having this level of visibility and insight over the data structures that power your content — all within a user interface — is starting to look and feel pretty powerful if you’re a front-end developer! If you want to read more about “thinking in graphs,” have a look at this fantastic resource from graphql.org.

So that’s the graph part of GraphQL. Next, let’s take a look at the query language and how a type system ties everything together.

A type system makes things predictable

You may already be familiar with the concept of a REST API, which adopts a resource-based approach to data reading and writing, determined by the format of the API URLs over HTTP. (If you’re new to REST and you want some more context, check out this post — What is a REST API?) In contrast to REST, the GraphQL query language allows you to request data from multiple different “resources” (such as blog posts, pages, authors and anything else) in just one API call using a single URL endpoint — usually over HTTP.

When building up a web page, you may need to display different types of data in different UI components. Perhaps you might need to fetch a blog post, an author, a set of navigation links, a list of related blog posts, and so on — all for a single page. When using GraphQL, you can request all the different data types you need to build up your UIs in a single API call, instead of having to make multiple requests for different “resources.”

Here’s an example of a GraphQL query which is requesting data from four different content types (or resources) in Contentful: a blogPost, an author, an event, and a talk. Essentially, we’re requesting four different objects, and particular fields on those objects. For example, on the eventCollection object, we’re requesting the items field, and for each of those objects in items, the name field. The query is prefixed with the word query — on the GraphQL schema, a query is of type Query!

When using a REST API, you’d need to make four different API calls to request data from these four different content types. With GraphQL, you can do it all in one go!

query {
  blogPostCollection {
    items {
      title
      author {
        name
      }
    }
  }
  eventCollection {
    items {
      name
    }
  }
  talkCollection {
    items {
      title
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

And here’s the result of the query. Notice we have all the data we requested in one response. (Note: I added limits into the query below to be able to demonstrate this in a single page view.) What’s also great about the GraphQL response object is that the object keys returned are exactly the same as we requested. This makes GraphQL predictable and intuitive to use. You get exactly what you ask for in the response — no more, no less — in the same order, with the same structure.

A screenshot of the GraphQL playground in Contentful showing the result of the query described above.

Use the keyboard shortcut ctrl + space when you’re building up a query in a GraphQL explorer to see the fields available to select on an object. This is a handy way to get inline hints about the schema of your data as you build up your queries — and the data type of those fields.

An annotated diagram showing the hint or context menu that shows in the GraphQL explorer when you press ctrl and space. The menu shows the fields available to query on the current node, and the type of field it is when it is selected.

If you want to take a deeper dive into types in GraphQL, take a look at the official GraphQL documentation on schemas and types.

You might be thinking — how is this graph structure generated from the GraphQL schema? Let’s take a look at introspection queries.

Introspection queries expose a GraphQL schema

GraphQL comes with an introspection query system, which is a way to query the type system and data structures in your database in order to generate the documentation and provide hints in the GraphQL UI. If you’re not familiar with the word introspection, it means to look inward and examine your own state.

You can actually query your GraphQL schema using GraphQL itself! This root-level query returns all of the data types you have in your schema.

query {
  __schema {
    types {
      name
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

A screenshot of the GraphQL playground showing the result of the schema query made above.

You’ll see three different types of data returned in an introspection query.

  1. Types defined by the schema: in the case of my personal website built with Contentful, these will be types such as BlogPost, Asset, Talk, Event, Project and so on.
  2. Types defined by the type of field data (scalar types): such as String, Boolean.
  3. Internal introspection query types: such as __Schema, __Type, __Field — and these are prefixed by a double underscore.

In GraphQL, each field in a query acts as a function which returns the next field type, and the next type, and the next type, until the field returned is a scalar value, such as a String or a Boolean. This is demonstrated in the example above from my personal website, where a blogPost node contained an author node, which contained an image node, which contained a fileName of type String — a scalar value — and that’s where the journey ends.

When any field is executed, a resolver is called to produce the field value. When developing your own GraphQL servers and making database changes, you’ll need to provide a resolver for each new field type you add to the API. Learn more about resolvers from GraphQL.org.

A great feature of the Contentful GraphQL API is that the GraphQL schema of your data is generated at request time, meaning it is always up to date with the current status of your Contentful space. You don’t need to worry about resolvers — we handle it for you.

If you want to find out more about introspection queries and how to watch them run in the network tab of the browser when loading up a GraphQL explorer, check out this video on the Contentful Youtube channel.

So far we’ve focused on just reading data from a GraphQL API. But writing to a database via GraphQL is also possible — and this comes with another special word — mutation.

Write data with GraphQL mutations

To mutate something means to change, or manipulate it. You can manipulate your server-side data via GraphQL using the mutation keyword that prefixes a query. The Contentful GraphQL API is read-only, so you can’t perform mutations in Contentful using GraphQL, but in theory, here’s how it works if I wanted to create a new blog post, save the title, and return the new data in the response.

mutation CreateNewBlogPost($title: String!) {
  createBlogPost(title: $title) {
    title
  }
}
Enter fullscreen mode Exit fullscreen mode
  • The query begins with the word mutation, and in GraphQL APIs that support mutations, this is of type Mutation, in the same way that a read-query is of type Query as described above.
  • Next, we need to wrap the mutation in what looks like a function, where we define the variables needed — and their types — to complete the mutation. This is CreateNewBlogPost which takes in a variable title which is of type String. The ! means that the variable is required in order for the mutation to happen. For more information on how to use variables in GraphQL, check out this blog post I wrote a little while back:
  • Inside the “function,” you would use the mutation available on the GraphQL API (use introspection queries to find it!). In this case, it’s createBlogPost. Inside the mutation, define the variable(s) to pass in.
  • And finally, inside the mutation, define the fields you’d like to return in the response. In this case, I’m just creating a title, so I just want to return the new title in the response.

Make a request to the API with the mutation query and variables, and here’s the response you’ll see from the API after the mutation has completed. Again, the output is in the same recognizable format as the input!

{
  "data": {
    "createBlogPost": {
      "title": "My new blog post title!",
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

To read more on GraphQL mutations, check out the official documentation from GraphQL.org.

So now we’ve covered how to read from (query) and write to (mutate) a GraphQL API where supported, let’s take a brief look at how we can communicate with a GraphQL API to perform those actions.

How to communicate with a GraphQL API

GraphQL is usually served over HTTP via a GraphQL server. There are other ways to communicate with GraphQL, such as via WebSockets, but HTTP is largely the most popular choice. If you’d like to read up on how to use GraphQL with cURL, Python, JavaScript, Ruby and PHP over HTTP, check out this blog post: GraphQL via HTTP in five ways.

Here’s a quick example of how to request a title and excerpt from a blog post stored in Contentful via GraphQL, using JavaScript fetch. You can make this same HTTP call using any language or framework as long as it supports HTTP!

In this example we’re sending the request via HTTP POST by sending the access token in an Authorization header and the GraphQL query in the body of the request. You can also make the same request via HTTP GET, but you’ll need to append the query and access token to the URL of the request. Read more about using HTTP POST and GET on the Contentful GraphQL API in the documentation.

// Build the GraphQL Query
const query = `{
  blogPostCollection(limit: 1) {
    items {
      title
      excerpt
    }
  }`;

// Send a POST request via fetch to the Contentful GraphQL URL endpoint
const response = await fetch("https://graphql.contentful.com/content/v1/spaces/{yourSpaceId}", {
  method: "POST",
  // Include Authorization and Content-Type HTTP headers
  headers: {
    Authorization: "Bearer {yourAccessToken}",
    "Content-Type": "application/json",
  },
  // Send the GraphQL query in the body of the request
  body: JSON.stringify({ query }),
}).then((response) => console.log(response.json()));
Enter fullscreen mode Exit fullscreen mode

And boom, you’ve got data from a GraphQL API! Remember, GraphQL is language-agnostic, so you can read and write to a GraphQL API using any programming language or framework — as long as it supports the protocol you need, such as HTTP.

Further reading

GraphQL is a powerful way to organize how you communicate with your backend services and databases. I’ve really enjoyed exploring what’s possible with GraphQL this year, and I’m excited to dive deeper into new projects. I might even experiment with building my own GraphQL API!

To find out more about using GraphQL to get your Contentful data — including published and preview content — check out the official documentation. And if you want to explore the wonderful world of GraphQL in more detail, take a look at the official GraphQL specification and learning materials on graphql.org. Maybe it’ll inspire you to build your own GraphQL API. Happy querying!

Latest comments (6)

Collapse
 
mrdulin profile image
Info Comment hidden by post author - thread only accessible via permalink
official_dulin

A bunch of code examples of apollo graphql - github.com/mrdulin/apollo-graphql-...

Collapse
 
thenickest profile image
TheNickest

Very nice! Was exactly looking for that! Thank you :)

Collapse
 
whitep4nth3r profile image
Salma Alam-Naylor

Happy you found it useful! 🤩

Collapse
 
llbbl profile image
Logan Lindquist • Edited

I made you a meme Salma, imgflip.com/i/5yh2e7
Send me contentful goodies <3 lol

Collapse
 
zyabxwcd profile image
Akash

Amazinng!! This is a one of the very few articles that were quite wordy but surprisingly easy to read, ingest and comprehend. I am glad I was able to finish it. This is a first for me. I kept reading in a flow and everything made sense. Well connected sentences explaining things in a beautiful fashion.

Collapse
 
whitep4nth3r profile image
Salma Alam-Naylor

Thank you so much, Akash! 😃

Some comments have been hidden by the post's author - find out more