Make no compromises on content design with GraphQL Union Types
Tags: graphql, cms, api
Published: 2020-04-30 11:23:56

---
title: Make no compromises on content design with GraphQL Union Types
published: true
description: Build a marketing site using GraphCMS union types to compose UI ‘blocks’ with components.
tags: graphql, cms, api
---

Designers are often given a hard time by developers on their their wild design aesthetics and how difficult it is to translate pixels into HTML. 

Developers often cut corners leaving designers enraged that the final piece in production looks nothing like it did during the design phase! _I've done this before._🙈

Thankfully we've moved on from using tables to create our 3 column layout and images as borders, _oh what a time to be alive_.

Then same can be said about developers and marketing, or content teams specifically. Most out of the box Content Management Systems give you a set way of building things, and provide additional `attributes` or `meta` you can tag onto content entries to make your wild designs "work".

Often all of this leads to more code to maintain and more ways for things to go wrong. It's also just damn right unnecessary thanks to Headless [APIs](https://graphcms.com/academy/headless-cms).

We at [GraphCMS](https://graphcms.com) like to do things a little differently. We don't provide any content models out of the box but instead give you a schema editor to design how your content should be structured.

The real power of this is you can now create and connect content models to work with your wild designs, and one of the biggest benefits of using GraphQL is the native [Union Types](https://graphql.org/learn/schema/#union-types).

## Content types

- Heros
- Gallery
- Testimonial
- Grid
- CTAs
- and much more...!

Now it's not uncommon for these content types to appear more than once on a page, and ordered.

Using GraphCMS we can define each of these content models and connect them using relations, and thanks to the power of GraphQL, working with this data is even easier.

Consider a `Page` model:

![GraphCMS Page Model](https://dev-to-uploads.s3.amazonaws.com/i/hjms6z4dx2hjzpvelkcv.png)

The `Page` model itself is pretty bare bones, and is only used in a way to query the specific page we need, but using the references field type in GraphCMS, we can connect multiple other models.

We've called these `Blocks` but they could be named `Sections` or `ContentBlocks`, that's up to you!

An example of one of these "Blocks" is `Hero`. The `Hero` model contains its own fields.

![GraphCMS Hero Model](https://dev-to-uploads.s3.amazonaws.com/i/hldo73q91u247ar28zuk.png)

---

## Querying a GraphQL Union Type

Let's imagine we have some data in our project, and we want to get the a `Page` by `slug` that is `home` in our GraphQL query.

The query will look a little something like this:

```graphql
query PageQuery($slug: String!) {
  page(where: { slug: $slug }) {
    blocks {
      __typename
      ... on Cta {
        content
        title
      }
      ... on Grid {
        columns {
          __typename
          ... on Feature {
            content
            title
          }
        }
      }
      ... on Hero {
        subtitle
        title
      }
    }
  }
}
```

The import thing to note is we use `...` to query `on` a specific GraphQL type. **GraphQL types are automatically generated by GraphCMS when you define your content models.**

When it comes to implement the design and switching between what "blocks" you should render to the page, we can leave that to the developer.

In the example below we are using React to import all exported "Blocks" from one folder, and then mapping through our `blocks` array, and depending on the `__typename` returned from our GraphQL query, we can show the corresponding view.

```js
import * as Blocks from "../components";

function Index({ page }) {
  return (
    <>
      {page.blocks.map((block, index) => {
        const Component = Blocks[block.__typename];

        if (!Component) return null;

        return <Component key={index} {...block} />;
      })}
    </>
  );
}
```

Now for our `Hero` all that's left to do is create a component and that will be rendered!

```js
function Hero({ subtitle, title }) {
  return (
    <header className="bg-blue-800 py-12 md:py-20 text-center">
      <div className="max-w-4xl mx-auto px-6">
        <h1 className="font-semibold mb-4 text-2xl md:text-4xl text-white">
          {title}
        </h1>
        {subtitle && (
          <h2 className="font-medium text-blue-300 text-lg">{subtitle}</h2>
        )}
      </div>
    </header>
  );
}
```

So there we have it! We have the data a format that is custom to my project needs, and a way to render these blocks thanks to the `__typename` value from our GraphQL query.

Here is an example of the finished piece with more content models:

![GraphCMS GraphQL Union Types Example](https://dev-to-uploads.s3.amazonaws.com/i/z9h8y6yqq1b3c0d0bmb6.png)

---

You can get started with this example built by [@ynnoj](https://twitter.com/ynnoj) over on GitHub, and try out the queries for yourself using the API Playground.

- [Demo](https://nextjs-union-types.now.sh)
- [Code on GitHub](https://github.com/GraphCMS/graphcms-examples/tree/master/using-union-types)
- [View API Playground](https://api-eu-central-1.graphcms.com/v2/ck9e0p6nh1fby01yyfvww984d/master)