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.
We at GraphCMS 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.
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:
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.
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:
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.
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!
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:
You can get started with this example built by @ynnoj over on GitHub, and try out the queries for yourself using the API Playground.
Top comments (2)
Thanks for the straightforward writeup. A lot of voices say to no longer "compose" pages, but for marketing sites, it seems like a good idea. This is perfect.
I would LOVE an example of this using SvelteKit!! Please please :)