Published on July 7, 2022
Rich headless CMS functionalities give you full control of your ecommerce store. From here, you can manage page content, page blocks, and advanced details for your ecommerce pages without the need to rely on a development team.
From an open source headless commerce solution like Medusa, you can then customize everything ecommerce related from products, customers, and orders to advanced features such as local pricing, gift-carding, and specific payment/shipping. All of it is easily extensible and with two-way sync to your Contentful setup.
This tutorial is for developers that want to learn how to build an ecommerce store with rich CMS features from scratch using Medusa and Contentful, the benefits of such an integration, and how this solution can be managed by end users.
Medusa is the leading open source node.js ecommerce platform available. Unlike traditional monolithic ecommerce solutions, Medusa offers an open and modular architecture that removes the need for hacky workarounds and secures maintainability and speed. The solution is built to optimize the developer experience based on an abstraction-based architecture that makes it easy to extend and customize.
Medusa ships many advanced ecommerce features out of the box such as; automated RMA flows, advanced promotion logic, and local configurations for tax, currency, shipping, and payment.
Medusa as a project is composed of three components:
The headless server: It is the core of Medusa. It handles all the data and logic of your ecommerce store. Other components connect to the headless server through the REST APIs.
The Medusa Admin: It’s a protected dashboard that allows store operators to manage their store’s settings, products, orders, and more. It connects to the headless server using the REST APIs.
The Storefront: It’s the interface that customers use to browse products and make purchases. Medusa provides two starter storefronts, one built with Next.js and one with Gatsby. Alternatively, you have the freedom to choose any frontend framework for your storefront. It just needs to connect to the headless server using the REST APIs.
Before moving along with this tutorial, you need the following installed on your system:
Node.js v14 or greater.
Redis which Medusa uses as the event queue in the server.
A Contentful account with an empty space created to host the data of your Medusa server.
It’s also recommended to install PostgreSQL. You can use SQLite, which is the default development database used for a Medusa server, but you might face some issues while using it due to SQLite’s limitations.
In this section, you’ll set up the Medusa server with the necessary configurations to connect it to Contentful.
Before you can install the Medusa server, install Medusa’s CLI tool:
Then, install the Medusa server with the following command:
This installs the Medusa server in a newly created directory medusa-contentful-store
. This Medusa server is based on a Contentful starter server that already has the necessary configurations and files to integrate Medusa into Contentful.
Medusa gives developers the freedom to choose how they load their environment variables. In this section, you’ll add the code necessary to load the environment variable from a .env file. If you prefer to load your environment variables differently, you can skip this step.
Change to the medusa-contentful-store
directory. Then, open medusa-config.js
and add the following at the top of the file:
This loads the environment variables from a .env
file based on the current environment.
Open .env
. You’ll find the following environment variables:
These environment variables are necessary for your integration with Contentful. The first one is the ID of the Contentful Space you’re using to manage the CMS data for your Medusa server.
The second variable is the token needed to push and sync data between your Medusa server and Contentful Space.
The last variable is the environment of your Contentful Space to use. Environments are used in Contentful to allow you to manage different versions of your content. The default environment is the master
environment.
To retrieve the CONTENTFUL_SPACE_ID
on your Contentful Space dashboard go to Settings > API keys from the navigation bar.
Then, click on Add API key at the top right. This opens a form where you have to fill in a name for the API key. Once you’re done click Save.
You can see in the form two important fields: Space ID and Content Delivery API - Access Token. Copy the Space ID and use it as the value for CONTENTFUL_SPACE_ID
. As for the Content Delivery API access token, you’ll use this one later when you set up the Gatsby storefront.
Then, go back to the API keys page, and click on the Content Management Tokens tab. On that tab, click on Generate Personal Token.
Enter a name for the token then click Generate to get a token. Use the token as the value for CONTENTFUL_ACCESS_TOKEN
. Please note that you will not be able to see the token after closing the pop-up so make sure to copy it before you close the pop-up.
Finally, set the value for CONTENTFUL_ENV
to master.
This is all you need to configure the Contentful plugin.
By default, Medusa connects to Redis on the URL redis://localhost:6379
. If you need to change that, add the following environment variable to .env with the value set to your Redis URL:
If you want to use a PostgreSQL database instead of an SQLite database, add the following environment variable to .env:
Where <YOUR_DATABASE_URL>
is the URL of your PostgreSQL database.
Then, in medusa-config.js
in the exported object, remove the lines that use the SQLite database and add the following properties instead:
Medusa gives developers the freedom to choose where to host their product images and files. It’s recommended to install one of the following file service plugins:
Before you sync the data between the Medusa server and the Contentful Space, you need to migrate the content models into your Contentful space.
In your terminal, run the following command:
After the command finishes running successfully, open the Content Models page on your Contentful Space Dashboard. You should see new content models added.
If you open the Content page you’ll find that there’s currently no data.
In this step, you’ll seed Contentful with some initial data that is in data/contentful-seed.json
. Run the following command to seed your Contentful Space:
After the command runs successfully, you can find the Contents page filled with data of different Content Types.
Run the following command to seed your Medusa database with some dummy data including dummy products:
Based on your database configurations, this will either create an SQLite database in the root of the project or seed your PostgreSQL database.
Among the data added, two demo products will be added to your Medusa server. But how will these products become available in the Contentful Space?
Every time you run your server or every time a product is created while your server is running, Redis emits an event that the Contentful plugin listens to. Then, the plugin adds the new products to your Contentful Space. This behavior is also applied whenever a product is updated.
To run the Medusa server, run the following command:
When you start your server after seeding the database with dummy data, Redis detects and emits the event product.created
which the Contentful plugin listens to.
If you open the Content page and filter the data to only show content of type Products, you’ll find two products added.
Both products are currently drafts. Open each product and set it to Published to find it later in the Gatsby storefront.
With the current configuration, the content on your Contentful Space is updated whenever the product data on your Medusa server is updated. However, how do you make sure that updates on the Contentful Space are reflected on the Medusa server as well?
This step requires that your Medusa server is hosted on a public server. You can follow this guide to learn how to host Medusa on Heroku.
Then, on your Contentful Space Dashboard, click on Settings > Webhooks from the navigation bar.
Then, click on Add Webhook. In the form, enter a name for the webhook.
In the URL field, choose the method POST
and in the input next to it enter the URL <YOUR_SERVER_URL>/hooks/contentful
where <YOUR_SERVER_URL>
is the URL of your server.
You can leave the rest of the fields the same and click Save. Now, every time you change a product’s data on your Contentful Space it will be updated on your Medusa server as well.
To add products to your Medusa server, you either need to use the REST APIs or, for a better and easier approach, use the Medusa admin.
This section is optional and you can skip it if you’re not interested in installing the Medusa admin.
To install the Medusa admin in a different directory than the one holding the server, run the following command:
This creates the directory medusa-contentful-admin
that holds the codebase for the Medusa admin. Change to that directory and install the necessary dependencies:
Before the admin can make requests to the Medusa server, you need to add the URL of the Medusa admin as an environment variable on the Medusa server.
By default the admin runs on either port 7000
or 7001
based on the available port. So, add the following environment variable to .env on the Medusa server:
If your admin is running on a different URL, feel free to change the value to your Medusa admin URL.
While your Medusa server is still running, run the following command to start the Medusa admin:
Then, open the Medusa admin in your browser (by default running on localhost:7000
). You’ll see a login screen.
When you seed the database with demo data, it creates a demo admin user. Enter the email “admin@medusa-test.com” and password “supersecret” to log in using the demo admin user.
From the sidebar, click on Products. You’ll see two products there which are the demo products you seeded the database with earlier.
To add a new product, click on New Product at the top right. In the form, enter the product details such as name, price, quantity, and weight. You can also upload an image.
Once you’re done, click on Save, then Save and Publish at the bottom right.
This triggers the event product.created
on the server. As mentioned earlier, the Contentful plugin has a subscriber that listens to this event, among other product events.
When this event is triggered, the product is also added to your Contentful Space. So, if you open the Contents page of your Contentful Space, you should find a new product automatically added. If you open it, you’ll find the same information you entered on the Medusa admin.
In this section, you’ll set up the Gatsby storefront that connects to the Medusa server to give customers ecommerce functionalities, and uses CMS data from your Contentful Space for the content of the products and pages.
First, install the Gatsby CLI:
Then, run the following command in a different directory than those holding the Medusa server and Medusa admin:
This installs the Gatsby storefront in a newly created directory medusa-contentful-storefront
. Change to that directory and rename the file .env.template
to .env
.
Inside .env there are two environment variables necessary for the Contentful integration:
You already have the value of CONTENTFUL_SPACE_ID
so you can set its value.
As for CONTENTFUL_ACCESS_TOKEN
, go back and find it on the dashboard of your Contentful Space by going to Settings > API keys and selecting the API key you created earlier. Then, copy the key under Content Delivery API - Access Token and use it for the value of CONTENTFUL_ACCESS_TOKEN
.
The Gatsby storefront displays pages that are configured on your Contentful Space. To make sure it works properly, you need to configure them before running your storefront.
Go to the Content page and select Featured Products of the content type Tile Section. This section is shown on the homepage of your Gatsby storefront.
On this page, click on Add Content, then choose Add Existing Content. In the pop-up, choose the products you want to be featured on the home page.
Once you’re done, click on the Insert Entities button. Then, click on the Publish Changes button at the right.
Next, go back to the Content page and click on Products of the content-type Tile Section. This tile is displayed on the Products page of your Gatsby storefront. Similarly, click on Add Content and select some or all of the products you have added, then publish changes.
Make sure the Medusa server is still running. Then, run the following command in your terminal to run the Gatsby storefront:
This runs your storefront on localhost:8000
. On the homepage, you can see the Featured Products section with the products you selected.
You can also see the products you selected for the Products tile by clicking on Products in the navigation bar.
Click on any of the products and you can see its information such as name and description.
When you update the CMS data on your Contentful Space, the changes are not instantly reflected on your Gatsby storefront. That’s because the data is fetched during build time.
To view updated data, restart the Gatsby server. The data will be fetched again from your Contentful Space and the updated data will be displayed.
The two-way sync functionality allows the ecommerce and operation team and the marketing and content management team to work separately without affecting or depending on one another.
The ecommerce team can focus on handling all ecommerce functionalities such as product upload, order management, promotions management, and more, all from the Medusa admin.
On the other hand, store operators and content managers can manage the content of the ecommerce storefront from the Contentful Space dashboard.
For example, the home page can be updated whenever there’s a new sale or promotional season right from the Contentful Space.
Contentful also provides advanced functionalities that can make your storefront even better. For example, you can utilize its localization feature to create a store in multiple languages all managed in one place.
Using a headless commerce solution like Medusa provides developers with an abstraction level that allows them to extend the platform and implement this integration without making any component dependent on another.
This abstract-based architecture and Medusa’s open source nature gives developers freedom in choosing their preferred stack. They can integrate any payment provider, fulfillment provider, CMS solution, or any other ecommerce aspect.
Medusa is also a perfect choice for ecommerce platforms that have custom use cases. It is being used by developers looking to implement online marketplaces and subscription-based platforms.
A huge benefit that comes from Medusa’s headless architecture is the decoupling of the frontend from the backend. Developers have full freedom in choosing the frontend framework they want to use for their ecommerce store.
This is what makes integrations to solutions like Contentful possible for rich CMS functionalities. Developers can utilize Contentful’s powerful features such as localization, no-code content editing, content versioning, secure previews, and much more.
There are more features that you can add to your ecommerce store with Medusa:
Learn how you can add a payment provider like Stripe.
Learn about subscribers and what events you can listen to.
Check the REST APIs for a list of all endpoints you can use to interact with your Medusa server.
Join Medusa’s Discord server for direct assistance from their core team.
You can also learn about what more you can do with Contentful:
Learn more about Images API to enhance the images retrieved on the storefront.
Learn more about what Content Delivery APIs are available that you can use on the storefront.
Learn how to localize your content with Contentful. Join the Contentful Slack Community to chat with the makers of Contentful and other developers in the community.
Subscribe for updates
Build better digital experiences with Contentful updates direct to your inbox.