Medusa is an open source composable ecommerce platform that allows developers to create their own customizable and extendable online store. Medusa aims to provide developers with a great experience creating unique ecommerce stores.
Combining Medusa and Strapi allows you to create a powerful ecommerce store. Strapi is an open source headless CMS platform that is fully customizable.
With Medusa, you can perform ecommerce functionalities while using Strapi to control the content displayed on your store.
To top it off, with Remix you can create awesome and fast UI. Remix is an open source react framework focused on web standards and modern web app UX. You can also easily fetch data from Medusa and Strapi to your storefront.
In this tutorial, you will be building an ecommerce storefront with Medusa, Strapi, and Remix.
You can find the source code for this article in this repository.
Prerequisites
- Node v14 or above
- Yarn is recommended, but you can also follow along with npm.
- Redis
- Medusa CLI: To install the CLI, run
.Copy to clipboardyarn global add @medusajs/medusa-cli
Set Up Strapi
Install the Template
This creates a folder named
in your project. Once the installation is complete, the Strapi development server will start on portCopy to clipboardstrapi-medusa
. A new page will also open in your default browser to create a new admin user and log in. After you have logged in, you can access your Strapi Dashboard.Copy to clipboardlocalhost:1337
Change Authorization Settings for the User
Your Medusa sever will require the credentials of a Strapi User in order to seed Strapi with mock data. To create a new user, go to Content Manager, then choose User under Collection Types.
Click on the Create new entry button at the top right. This opens a new form to enter the user’s details.
Enter the user’s username, email, and password. Once you’re done, click on the Save button at the top right.
Next, go to Settings → Roles → Authenticated and select all the permissions, and hit save.
Set up Medusa
To initiate your Medusa server, run the following command:
The
flag creates an SQLite database and seeds it with some demo data.Copy to clipboard--seed
Change to the
directory and go toCopy to clipboardmedusa-server
. Change the exported object at the end to enable Redis:Copy to clipboardmedusa.config.js
The default Redis connection string is
but if you have made changes to it, go to theCopy to clipboardredis://localhost:6379
file and add the following:Copy to clipboard.env
Where
is your connection string.Copy to clipboard<YOUR_REDIS_URL>
Additionally, since the Remix storefront runs on
, you have to add an environment variableCopy to clipboardlocalhost:3000
that sets the URL of the storefront.Copy to clipboardSTORE_CORS
Add the following in
:Copy to clipboard.env
Install Strapi Plugin
To install the Strapi plugin, run the following command in your Medusa server’s directory:
Then, add the following environment variables:
Where:
is either the email address or username of the user you created in the previous step.Copy to clipboard<STRAPI_IDENTIFIER>
is the password of the user you created in the previous step.Copy to clipboard<STRAPI_PASSWORD>
is the protocol of your Strapi server. Since, you’re using a local Strapi server, set this toCopy to clipboard<STRAPI_PROTOCOL>
. The default value isCopy to clipboardhttp
.Copy to clipboardhttps
is the URL of your Strapi server. By default, the URL isCopy to clipboard<STRAPI_URL>
.Copy to clipboardlocalhost
is the port the Strapi server runs on. By default, the port isCopy to clipboard<STRAPI_PORT>
.Copy to clipboard1337
Finally, open
and add the following new item to theCopy to clipboardmedusa-config.js
array:Copy to clipboardplugins
Test Integration
Make sure the Strapi server is still running. If not, you can run the following command to run the Strapi server in the directory of the Strapi project:
Make sure your Redis server is up and running as well.
Then, in the directory of your Medusa server, run the following command to start the Medusa server:
This will start your Medusa server on
. You’ll see thatCopy to clipboardlocalhost:9000
events have been triggered along with similar events.Copy to clipboardproduct.created
This will update Strapi with the demo products you seeded.
Add CMS Pages in Strapi
You will now use Strapi to manage content on your storefront’s homepage. You will be able to control three things from Strapi after this implementation: the hero text that will appear at the top of the storefront; the subheading below the hero text; and the list of products shown on the homepage.
On your Strapi dashboard, go to Content-Type Builder under Plugins in your Strapi Dashboard. This is where you can define the model/schema for your content.
Click on “Create new single type” under “Single Types”.
Enter the display name as “Home Page” (if you have used another, you will have to use the appropriate API ID for it later) and hit continue.
Next, select the component field and give it the display name “Hero Text”, and a category homepage (click create “homepage” under the category). Then, click on configure the component.
Then give it the name
in the next step and click Finish.Copy to clipboardhero_text
Go to the Hero Text component under Homepage in components and create three text fields named
,Copy to clipboardstart_text
andCopy to clipboardmid_text
.Copy to clipboardend_text
Here, the three text fields have been added because later on in the article you will give a special underline to the
to highlight it.Copy to clipboardmid_text
Go back to the Home Page type under single types and add a relation field to products. The relation should be “homepage has many products”. Give it a field name
.Copy to clipboardproducts_list
Finally, add a text field
. Save your changes in the homepage content type.Copy to clipboardheading_2
This is what your homepage content type should look like:
Next, go to Settings → Users & Permissions Plugin → Roles → Public, and enable find permission for the homepage and product type. Hit save.
Now, go to the content manager and under the Home Page add your hero text and the products you wish to display under the relations section to the right. Hit save and then publish.
Set up the Remix Storefront
In this section, you’ll set up the ecommerce storefront with Remix.
Remix has three official pre-built templates for you to use depending on your needs, but you can also start with a basic one or create your own.
Set up Remix
To setup a Remix app (do this in a separate directory from
andCopy to clipboardmedusa-server
), run the following command:Copy to clipboardstrapi-medusa
It will ask you a few questions. Choose
, then choose your preferred hosting platform (you can choose Remix App Server if you are unsure), choose typescript, and no forCopy to clipboardJust the basics
if you wish to useCopy to clipboardnpm install
.Copy to clipboardyarn
Then, change to the
directory and install dependencies with yarn:Copy to clipboardmy-storefront
Configure Tailwind CSS
Install Tailwind CSS to design the UI element:
Run
to create yourCopy to clipboardnpx tailwindcss init
file. Then, set its content to the following:Copy to clipboardtailwind.config.js
Also, change the scripts in your package.json:
Then, create the file
with the following content:Copy to clipboardstyles/app.css
Lastly, add this to your
after the list of imports:Copy to clipboardapp/root.tsx
You can now use Tailwind CSS in your app.
Connect Storefront to Medusa Server
Once this is done let’s connect your storefront to your Medusa server.
First, you need to install a few packages with the following command:
The
library uses react-query as a solution for server-side state management and lists the library as a peer dependency.Copy to clipboardmedusa-react
In order to use the hooks exposed by
, you will need to include theCopy to clipboardmedusa-react
somewhere up in your component tree. TheCopy to clipboardMedusaProvider
takes aCopy to clipboardMedusaProvider
prop which should point to your Medusa server. Under the hood,Copy to clipboardbaseUrl
uses theCopy to clipboardmedusa-react
client library (built on top ofCopy to clipboardmedusa-js
) to interact with your server.Copy to clipboardaxios
In addition, because medusa-react is built on top of react-query, you can pass an object representing react-query's QueryClientProvider props, which
will pass along.Copy to clipboardMedusaProvider
You also need to wrap your app in a
since that will let you use the cart functionalities provided by Medusa, which you will do later.Copy to clipboardCartProvider
Create a file
. This file will contain yourCopy to clipboardapp/lib/config.ts
which will let you use Medusa’s Javascript client in your app.Copy to clipboardmedusaClient
Now go to your
and import the required packages:Copy to clipboardapp/root.tsx
You can also edit the
here to change your metadataCopy to clipboardmeta
Below this, you will see the
component. In the returned JSX add theCopy to clipboardApp
andCopy to clipboardMedusaProvider
with some base styles to theCopy to clipboardCartProvider
:Copy to clipboardbody
Display Home Page from Strapi
The data for your home page is available on the Strapi endpoint:
(addCopy to clipboardlocalhost:1337/api/home-page
to also show the nested products). It returns an object with theCopy to clipboard?populate=*
&Copy to clipboarddata
arrays. You don't have to care about theCopy to clipboardmeta
, what you should really care about isCopy to clipboardmeta
, it contains all the content you entered in your Strapi Dashboard.Copy to clipboarddata
First, create the file
with the following content:Copy to clipboardapp/types/StrapiResponse.ts
This is the format in which your data is returned from the Strapi API.
Next, create a utility function to fetch your content from the Strapi API. Create a file
with the following content:Copy to clipboardapp/models/home.server.ts
In the
function, you should only return the data you need on your home page.Copy to clipboardgetHomePageData
In the above code sample, you will notice that in the import statement
is used, this is because it is the alias set for theCopy to clipboard~
directory set in theCopy to clipboardapp
by default in Remix, if you wish you can change it at your convenience.Copy to clipboardtsconfig
All files inside the
directory will be a route. For example,Copy to clipboardapp/routes
will contain theCopy to clipboardapp/routes/store.tsx
route.Copy to clipboard/store
Next, go to
and create a loader function:Copy to clipboardapp/routes/index.tsx
To use the response you received from the loader function you will use the
hook from Remix inside theCopy to clipboarduseLoaderData
component:Copy to clipboardIndex
Here,
was destructured and brought in usingCopy to clipboardhomePageData
, now you can use it on your page.Copy to clipboarduseLoaderData
Then, change the returned JSX to the following:
brings data from theCopy to clipboardheroText.start_text
text field under theCopy to clipboardstart_text
component you made in Strapi. Similarly,Copy to clipboardhero_text
andCopy to clipboardheroText.mid_text
are fromCopy to clipboardheroText.end_text
andCopy to clipboardmid_text
fields from Strapi respectively.Copy to clipboardend_text
Then
has been split so that each word gets a uniform underline in case there are multiple words, you will see it happen a bit later in the homepage UI.Copy to clipboardmid_text
To display your products, create the file
with the following content:Copy to clipboardapp/components/productCard.tsx
The
comes from Remix and will help you redirect to the products page. The handle prop which is available in Medusa products will be used as a slug.Copy to clipboardLink
Now getting back to your
, you will map your Strapi response (products) to the page.Copy to clipboardapp/routes/index.tsx
Do this just below your hero section:
Test Homepage
To test out your homepage, start your Remix development server with
(make sure that your Medusa and Strapi servers are already running).Copy to clipboardyarn dev
Your app is ready at
and it will look like the following:Copy to clipboardlocalhost:3000
Implement Add to Cart Functionality with Medusa
To add your products to the cart, you first need to associate a cart with the customer. To do this, you can create a wrapper around your app that checks if a cart has already been initialized or need to be created, and does the needful.
Create the file
with the following content:Copy to clipboardapp/components/outletContainer.tsx
You are using
'sCopy to clipboardmedusa-react
hook,Copy to clipboarduseCart
will set your cart globally. You can then use it anywhere in your app. TheCopy to clipboardsetCart
will also save cart localStorage so that the added items persist even when the user returns.Copy to clipboardoutletContainer
You will also need to show toast notifications when a product is added to the cart. Install
to do this:Copy to clipboardreact-hot-toast
Now, go back to your
and wrap yourCopy to clipboardapp/root.tsx
withCopy to clipboard<Outlet />
. Also, addCopy to clipboardOutletContainer
fromCopy to clipboard<Toaster />
that will let you show notifications:Copy to clipboardreact-hot-toast
Create Product Page
In this section, you’ll create a product page. When you are deploying to production, you can’t make a separate page for each of your products, so you will create a dynamic page that will run according to your product’s
. In Remix you will name your dynamic pages asCopy to clipboardhandle
.Copy to clipboard$slug.tsx
You will need to get the
from the URL of your page, you can do that with a loader function but it’s much simpler to useCopy to clipboardhandle
hook.Copy to clipboarduseParams
Create the file
with the following content:Copy to clipboardapp/routes/products/$slug.tsx
is getting your page’s slug from your URL, for example, inCopy to clipboardslug
the slug isCopy to clipboardlocalhost:3000/products/sweatshirt
(remember you passed in theCopy to clipboardsweatshirt
in yourCopy to clipboardhandle
component).Copy to clipboardProductCard
Next, fetch your product from Medusa using the
hook and add it to the UI:Copy to clipboarduseProducts
Here, the
hook was used and passed the slug. While the product is being loaded you show an empty div (you can use a skeleton loader instead).Copy to clipboarduseProducts
Finally, you use the first item returned by the
hook which is the product that has the handle in the page’s URL.Copy to clipboarduseProducts
Please notice that the title and description are used here from the Medusa server since the Strapi plugin supports two-way sync. So, whenever you make changes to the products in Strapi, they’re reflected on the Medusa server as well. You can alternatively show the CMS data for the product from Strapi instead.
You also need to show the prices for your customers according to their region. To do this, create the file
:Copy to clipboardapp/lib/formatPrice.ts
You use the
function here fromCopy to clipboardformatVariantPrice
. This formats the price according to your user’s region and the product variant selected.Copy to clipboardmedusa-react
Then, use it in
:Copy to clipboardapp/routes/products/$slug.tsx
Next, create a function to add to the cart and push notifications.
The
hook lets you add items. It requires a cart ID. TheCopy to clipboarduseCreateLineItem
function will add the product to the cart and then show a toast notification.Copy to clipboardaddItem
Add the button that will run this function on click in the returned JSX:
The last step is to add a navigation bar to make it easy to navigate to the cart.
Create the file
with the following content:Copy to clipboardapp/components/topNavigator.tsx
Add the
component to yourCopy to clipboardTopNavigator
so it appears on all pages. Add it just above theCopy to clipboardroot.tsx
:Copy to clipboardOutlet
Test Product Page
To test out your product page, restart your Remix server (make sure Strapi and Medusa servers are already running).
Click on any of the products on your homepage and you will be able to see the details.
Create Cart Page
Now, you will create your very final cart page.
Create the file
with the following content:Copy to clipboardapp/routes/cart.tsx
is an array of all the items in the customer’s cart. You display each item with its thumbnail, title, and quantity.Copy to clipboardcart.items
Test Cart Page
Restart your Remix server (make sure Strapi and Medusa servers are already running). When you add an item to the cart it will show on the cart page.
Conclusion
There’s still much more that can be done to improve your storefront such as:
- Improve the UI
- Improve Cart page to add functionalities such as removing or updating items.
- Implement Checkout Flow
- Integrate Stripe Plugin for payment.
- Install Medusa Admin to manage orders, products, and much more.
- Check out Medusa’s Storefront API Reference to learn what more you can do in your storefront.
Should you have any issues or questions related to Medusa, then feel free to reach out to the Medusa team via Discord.
Share this post
Try Medusa
Spin up your environment in a few minutes.
