19 Jan 2022 by Roy Derks

Combining Headless Architectures with Saleor and Strapi

In this post, you'll learn how Saleor and Strapi work together to create a performant and adaptable storefront. We’ll cover how you can use the power of GraphQL to combine headless architectures, such as a CMS and Commerce API, and how to combine the schemas of multiple GraphQL APIs.

Developers have been building decoupled applications on top of headless CMS APIs for a long time. With a headless CMS, you can integrate without worrying about how the CMS is providing its API endpoint. One of the companies that’s offering an API for its headless CMS is Strapi. How you build a frontend application for the Strapi API is very similar to how it's made with Saleor, as both are based on GraphQL.

A few months back, there was a talk about Saleor at the annual Strapi Conf, showing how to combine a headless CMS with a headless commerce API. One of the significant advantages of an API based on GraphQL is that you can combine them with other GraphQL APIs.

What is Saleor?

Saleor is an all-in-one platform for creating a production-grade, online commerce experience for your company. The headless commerce API that Saleor provides gives you a complete set of options to build an online shop. Saleor allows you to manage any number of storefronts such as web or mobile apps from a single backend. You can run Saleor on your servers as a free, open-source project. But if you don't want to maintain the platform yourself, you can sign up to run it in the cloud. This way, your developers don't have to worry about your backend's deployment, scalability, and availability.

Saleor Commerce

Saleor Commerce

Because the headless commerce API from Saleor is based on GraphQL, you get even more advantages by leveraging the GraphQL ecosystem.

GraphQL is a query language for APIs that gives the user control of the API's returned fields. This gives you a lot of flexibility and takes away the hassle of normalizing or restructuring data returned by an API.

Next to flexibility, you can easily combine with other systems that rely on GraphQL. All GraphQL APIs expose a schema, which gives the user information on what the API can do.

What is Strapi?

Strapi is another example of a service that runs on GraphQL. With Strapi, you can build applications based on their headless CMS API. It’s available as an open-source Node.js project, but it will also become available as a fully managed version on the cloud. Using its headless API, content creators can use Strapi to streamline their content delivery across multiple devices or applications. Developers like using Strapi because they can quickly build applications that need to display content that needs to be managed by a different team. For example, the Saleor blog uses Strapi as a headless CMS to display its content.

The API from Strapi's headless CMS is based on GraphQL, making it easy to combine this API with other GraphQL APIs. However, you can also access Strapi through a headless REST API. A headless CMS is very similar to a headless Commerce API, like what Saleor is offering. The advantages of going headless with your backend are the same for a CMS and Commerce. It's a perfect solution to combine these two headless APIs or headless architectures.

What are the benefits of combining headless architectures?

Both Saleor and Strapi offer a headless GraphQL API. The API from Saleor gives you access to a complete Commerce platform for building online shopping experiences, while Strapi is perfect for content delivery through their headless CMS.

Imagine you want to sell products on your blog or add a blog to your e-commerce store. Combining Strapi and Saleor would be perfect for these examples.

Headless architectures are very friendly to developers, as they share all the benefits of having a decoupled system. The upside is that you don't need to maintain a headless architecture, it’s either open-source or running on the cloud. Both will decrease your development time, as these architectures are already very feature-complete or extended with plugins. If you decide to run them on the cloud instead of self-hosting, it will also save you time and costs for handling deployments.

The only code you need to write as a developer is the User Interface (UI) that interacts with the API from the headless architecture. When you want to change the UI, you no longer have to change the backend as long as the information you want to display in your UI is available from the API of the headless architecture. This makes headless architectures very future-proof, as you can build applications for different devices or users without rebuilding the backend.

By combining multiple headless architectures together, you'll double the results of your investments. Think about the development time you save when setting up a headless CMS with Strapi. And at the same time, you can set up a feature-rich online experience using the headless API from Saleor. Both make it very easy to have an API running that lets you build applications that either help you with content delivery or let customers buy your products.

Combining Saleor and Strapi

As a developer, it makes no difference if this architecture is a CMS or built for Commerce. But if your team wants to use two (or more) different headless architectures together, they need to make sure these systems can be combined. You don’t want to integrate these systems, as you’ll lose the advantage of having a headless architecture. Luckily, GraphQL makes this easy as you only need to combine the schemas instead of the underlying architectures.

There are different flavors in combining GraphQL schemas, but we’ll focus on schema stitching in this post. Schema stitching is part of the popular npm library GraphQL Tools, which offers a broad toolchain to build GraphQL servers. With schema stitching, you can merge multiple GraphQL schemas or part of them. For this example, we want to combine information about posts coming from Strapi with product information retrieved from Saleor. The information should be combined in a frontend application, as we don’t want to create additional backend services.

Combining Saleor and Strapi

Combining Saleor and Strapi

In the diagram above, you can see what this looks like. The query GetProducts will get product information from Saleor, and the GetPosts query will get the post information from Strapi. In a React frontend application built with Next.js, the calls to the underlying headless architectures are made from an API Route. This API Route will serve as a lightweight GraphQL server that lives inside your frontend React application.

The API Route will have the following code, which is the basic setup to create a GraphQL server that can do schema stitching:

import { ApolloServer } from 'apollo-server-micro';
import { stitchSchemas } from '@graphql-tools/stitch';
import { delegateToSchema } from '@graphql-tools/delegate';
import { RenameTypes, RenameRootFields } from '@graphql-tools/wrap';

import createRemoteSchema from '../../utils/createRemoteExecutor';

// Configuration for Next.js API Routes
export const config = {
 api: {
   bodyParser: false,
 },
};

// Export as a Next.js API Route
export default async (req, res) => {
 // Setup subschema configurations
 const productsSubschema = ``
 const cmsSubschema = ``

 // Build the combined schema and set up the extended schema and resolver
 const schema = stitchSchemas({
   subschemas: [productsSubschema, cmsSubschema],
 });

 // Set up the GraphQL server
 const apolloServer = new ApolloServer({ schema });
 const apolloServerHandler = apolloServer.createHandler({
   path: '/api/graphql',
 });

 // Return the GraphQL endpoint
 return apolloServerHandler(req, res);
};

The library apollo-server-micro is used to create a lightweight GraphQL server in the Next.js API Route. GraphQL Tools is used to do the schema stitching. The actual stitching of the schemas happens in the code block you see below. First, you set up the subschemas, which are the schemas of the headless Strapi and Saleor GraphQL APIs. As the schema of Saleor is our first source of information, the types and operations from the Strapi schema are prefixed to prevent possible merge conflicts. This happens if types and operations have the same name.

// Setup subschema configurations
 const productsSubschema = await createRemoteSchema({
   url: // Your Saleor GraphQL endpoint
 });

 const cmsSubschema = await createRemoteSchema({
   url: // Your Strapi GraphQL endpoint,
   transforms: [
     new RenameRootFields(
       (operationName, fieldName, fieldConfig) => `strapi_${fieldName}`,
     ),
     new RenameTypes((name) => `Strapi_${name}`),
   ],
 });

After which, you need to merge the types by extending the schema and resolvers. This is the most crucial part. The information from the posts in Strapi (now called products) resembles the metadata for the product information in Saleor. Using a custom resolver, the types get merged, and the info gets appended on the field cmsMetaData:

// Build the combined schema and set up the extended schema and resolver
 const schema = stitchSchemas({
   subschemas: [productsSubschema, cmsSubschema],
   typeDefs: `
   extend type Product {
     cmsMetaData: [Strapi_Products]!
   }
 `,
   resolvers: {
     Product: {
       cmsMetaData: {
         selectionSet: `{ id }`,
         resolve(product, args, context, info) {
           // Get the data for the extended type from the subschema for Strapi
           return delegateToSchema({
             schema: cmsSubschema,
             operation: 'query',
             fieldName: 'strapi_products',
             args: { where: { saleorId: product.id } },
             context,
             info,
           });
         },
       },
     },
   },
 });

By extending the Saleor API schema in this API Route with the content information from Strapi, you're now able to query both headless architectures. The data from the headless CMS is now available on every operation that returns the type Product from Saleor, merging them on the value for saleorId. An example of an operation would be the query product, where the id you pass as a parameter should exist within Strapi.

Summary

In this post, you've learned about the benefits of combining multiple headless architectures, in particular Strapi and Saleor. Both architectures are based on GraphQL and have an open-source and cloud version (the cloud version of Strapi is coming soon). While Saleor provides a headless Commerce API, Strapi is used for content delivery. By combining both of them, you get all the benefits of connecting with headless architectures from your front-end application without integrating them. You can find the complete code example for this perfect combination here.


Lastly, we’d like to thank you for your contribution and support. Stay up to date with Saleor updates by following us on Twitter.


Learn more:

— Share