Mixing Data from Storyblok CMS using StepZen's Custom @graphql and @rest Directives
CMSs are a crucial component in any developer’s stack. But a CMS may not include everything your project needs. Sometimes we need to mix and match data from CMSs and other data sources. With StepZen, you can easily mix data from an external CMS with your own project by incorporating StepZen’s custom directives.
Storyblok is a headless CMS that includes a visual editor and various APIs to access your content. It gives your team the ability to manage content for multiple use-cases including corporate websites, eCommerce sites, help desks, mobile apps, and screen displays. In this example we use StepZen's @graphql
directive to connect to Storyblok's GraphQL API.
In addition to connecting to the Storyblok GraphQL API, we can also use StepZen's other custom directives to bring in data from any kind of REST endpoint we want. This example will include a Shopify backend to bring in products along with the blog posts from Storyblok.
You can find the code for this example on the StepZen Samples GitHub.
1. Create a Blog Post on Storyblok
Sign up for Storyblok
You can sign up for Storyblok at the following link.
Create a New Space
After signing up, you are asked whether you want to use a demo or create a new space. A space is a content repository for keeping all the content related to one project. Each space has its own components, datasources, assets, environments, domains, collaborators, and permissions.
Choose to create a new space instead of playing with a demo so we can build up our content from scratch.
Storyblok Dashboard
After creating a new space you are taken to your Storyblok dashboard. You can manage your content here. Create a new folder and give your folder a name and slug, then create a new entry and use the Post content blueprint to create a blogpost.
The post editor gives you the ability to create your blog post and include images, an intro, and an author.
The JSON response looks like the following:
{
"_uid": "ec395043-549c-43d5-a389-6e3334e1f35a",
"component": "Post",
"title": "My Super Awesome Post",
"image": "//a.storyblok.com/f/122199/1920x1080/823e44a555/gorillas-shark-explosion-high-five-wallpaper.jpeg",
"intro": "This is the intro to my super awesome post. It isn't a very long intro.",
"long_text": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is the long text of my super awesome post. It is slightly longer than the intro."
}
]
}
]
},
"author": ""
}
2. Connect to the Storyblok GraphQL API
You can find your API keys listed under the Settings tab. Use this token to access Storyblok's GraphiQL editor.
Storyblok GraphiQL Editor
Storyblok includes a GraphiQL editor similar to StepZen to explore your data. Include ?token=YOUR_TOKEN
after the URL to access your specific content. Open the Explorer tab to see the different queries that are available. The queries include the content itself as well as information about your content and space.
Send the following test query returning the title
, intro
, and long_text
of the blog posts to make sure you are connected.
{
PostItems {
items {
content {
title
intro
long_text
}
}
}
}
3. Create a StepZen Project
Now that we have data in our CMS and our API key, we can create our StepZen project. Lets create schema files called storyblok.graphql
and products.graphql
along with the other files we need to setup our project including stepzen.config.json
, config.yaml
, and index.graphql
.
mkdir -p stepzen-storyblok/schema
cd stepzen-storyblok
touch index.graphql schema/storyblok.graphql schema/products.graphql stepzen.config.json config.yaml
In this example there are only two files in the schema
to show the base case of connecting to the CMS and an eCommerce backend. As your schema grows it is important to separate out the schema into separate files.
stepzen.config.json
stepzen.config.json
gives you the ability to configure different aspects of your StepZen project such as the endpoint name or root directory. Include the following JSON object to specify that our endpoint is called api/stepzen-storyblok
.
{
"endpoint": "api/stepzen-storyblok"
}
If you do not have a stepzen.config.json
file then the CLI asks for a name for your endpoint the first time you deploy your project with stepzen start
.
index.graphql
index.graphql
is the glue that pulls together all the other .graphql
files in your schema. Our index.graphql
file only includes two schema files called storyblok.graphql
and products.graphql
.
schema
@sdl(
files: [
"schema/storyblok.graphql"
"schema/products.graphql"
]
) {
query: Query
}
config.yaml
config.yaml
is a file written in YAML to relay information regarding your configuration and keys to StepZen. This is where we set our API token we received from Storyblok. Including storyblok_config
in the @graphql
query lets us authenticate our queries to the Storyblok GraphQL API.
configurationset:
- configuration:
name: storyblok_config
token: <YOUR_TOKEN_HERE>
- configuration:
name: shopify_config
api_key: <YOUR_API_KEY>
api_password: <YOUR_API_PASSWORD>
store_name: <YOUR_STORE_NAME>
Include your own token and information for your Shopify store.
storyblok.graphql
In our schema directory is a file called storyblok.graphql
for our types and queries. Our types include a PostItem
with a name
for the post and a Content
type for the title
and intro
of the post. The PostItems
type returns an array of those PostItem
objects.
type PostItems {
items: [PostItem]
}
type PostItem {
name: String
content: Content
}
type Content {
title: String
intro: String
}
This example shows how to query for just a small subset of all the information available from the Storyblok GraphQL API. If you want to generate a complete schema without needing to code it by hand, you can introspect your endpoint with stepzen import graphql
.
type Query {
PostItems: PostItems
@graphql(
endpoint: "https://gapi.storyblok.com/v1/api"
headers: [
{ name:"Token" value:"$token" }
]
configuration: "storyblok_config"
)
}
Our query includes the endpoint
and sets the headers
for our token. configuration
includes our token from config.yaml
.
Deploy your GraphQL API to StepZen
stepzen start
deploys the code in your current directory to the specified endpoint on StepZen. It also watches the directory for changes and automatically deploys them to the endpoint specified.
stepzen start
You can now use the StepZen dashboard to test your API by exploring the queries and types available and querying the API running on StepZen.
Test the Endpoint
Run the following test query for the intro
and title
of your post.
{
PostItems {
items {
content {
intro
title
}
}
}
}
This returns the information we created early in the Storyblok editor.
{
"data": {
"PostItems": {
"items": [
{
"content": {
"intro": "This is the intro to my super awesome post. It isn't a very long intro.",
"title": "My Super Awesome Post"
}
}
]
}
}
}
4. Connect an eCommerce REST API
Now that we have connected our blog to our StepZen project, we can pull in products from an eCommerce backend by using the @rest
directive. This example connects to Shopify and queries for a set of products.
products.graphql
products.graphql
has a Product
type and a products
query that returns an array of Product
objects. Our product type only has a few properties.
type Product {
id: ID!
handle: String
title: String
}
Our products
query connects to the Shopify REST API using StepZen's @rest
directive. The @rest
directive accepts the URL of the REST endpoint that we want to connect to.
type Query {
products: [Product]
@rest(
resultroot: "products[]"
endpoint: "https://$api_key:$api_password@$store_name.myshopify.com/admin/api/2020-01/products.json"
configuration: "shopify_config"
)
}
Query for Products and Posts
With our blog and shop connected into our main schema, we can query for both the blog posts and the products with a single query.
{
PostItems {
items {
content {
title
intro
}
}
}
products {
title
id
handle
}
}
This returns the following output:
{
"data": {
"PostItems": {
"items": [
{
"content": {
"intro": "This is the intro to my super awesome post. It isn't a very long intro.",
"title": "My Super Awesome Post"
}
}
]
}
"products": [
{
"handle": "this-is-a-product",
"id": "661261903800",
"title": "BUY ME"
}
]
}
}
Next Steps
With the two directives pulling in data from two completely separate backends, StepZen does the heavy lifting of merging the schemas together and providing the resolvers under the hood. This allows the developer to get all the data they need with just a single query.
Curious to learn more about Storyblok? You can see Facundo Giuliani and Anthony Campolo walk through creating content in Storyblok and connecting to StepZen in How to mix data from Storyblok CMS with your own project using StepZen.
You can sign up for StepZen here to give it a try. If you have more questions or just want to hang out you can also join us on our Discord.