Introduction
Build your own marketplace from scratch using Medusa
In 2022, I embarked on my first project using Medusa to build a marketplace all by myself. Since then, Medusa has undergone significant improvements, and I believe it’s beneficial to share insights on constructing a marketplace with the 1.x versions.
A marketplace is…
A marketplace, conceptually, is a platform where multiple vendors can sell various products to numerous customers. One key aspect I’ve learned is that typically, the marketplace retains funds until certain conditions are met (e.g an order has been delivered to the customer), after which payouts are made to vendors, including fees.
In this blog series, we’ll delve into building a specific type of marketplace—a clothing marketplace where anyone can register and start selling their products.
While we won’t cover every detail, the aim is to equip you with the knowledge to customize Medusa for creating a simple yet functional marketplace. You’ll likely need to manage many aspects independently, but this guide will prepare you well.
It’s important to note that not every marketplace will be identical, and the provided examples might not exactly match the marketplace you envision.
Let’s start by following the recipe detailed in the Medusa documentation. The documentation covers various concepts and sometimes includes actual code implementations.
This will be a heavy first part, as it will condense certain points from the official documentation, but I promise that the rest of the parts will be lighter in terms of text.
Before we proceed, I’ll assume you’ve already set up your Medusa app.
Before we start…
As we progress through this series, we will be enhancing and altering some of Medusa’s fundamental logic and functionality.
However, the ability to use the sales channels feature flag may be impossible upon the design approach taken.
The current design of the Cart system, particularly its integration with sales channels, poses a challenge. It is structured in a way that precludes the possibility of associating multiple sales channels with a single Cart.
If you wish to leverage the sales channels feature, you have the flexibility to modify the Cart system or develop a similar mechanism to fully capitalize on its capabilities.
You’ll learn how to disable the sales_channels
feature flag by clicking here.
Following the recipe
The first part of our journey involves extending entities. The documentation guides us on how to begin this process, starting with the concept of a User
linked to a Store
(where the User
acts as a vendor, it’s distinct from a Customer
).
Extending the User entity
Here’s how we can start extending the User
entity:
Extending the Store entity
Next, we extend the Store
entity to include a new property representing our OneToMany
relationship, which is necessary to avoid type errors in the previously extended User
model :
Our First Migration
After extending the User
and Store
entities, we proceed with a database migration to reflect these changes in the schema. We continue following the recipe by executing the following command in our terminal:
It’s crucial to manually write your migrations when updating an existing core entity to avoid errors. Detailed instructions are available in the callout section of the Medusa documentation on migrations.
Here’s how we replace the up
and down
functions in our new migration with the ones provided in the docs :
How to apply migrations ?
To apply these migrations, we build our server and run the CLI command:
If we check our database now, we should see a new store_id
column in the user
table!
Our First Middleware
We have just set up the foundation for our marketplace by extending the User and Store entities and creating the necessary migrations. Now, we’ll dive deeper into customizing the data management functionalities using middleware and service extensions.
Registering a Logged-in User / Middleware
Medusa provides a way to create middleware that can be applied to specific routes. In the context of our marketplace, we want to ensure that the logged-in user’s information is available throughout our application, especially when retrieving data. Let’s create a new middleware that will register the logged-in user in the request scope:
In this middleware, we first check if there is a logged-in user in the request. If so, we retrieve the user’s information using the userService
.
We then register the loggedInUser
value in the request scope, which can be accessed by other services and components.
The middleware is applied to all /admin
routes, except for a few specific routes that don’t require authentication (This is why the long regex)
Extending the User Service
Next, let’s extend the UserService
to automatically create a new store when a new user is registered. This will ensure that every user has a store associated with their account, which is a key requirement for our marketplace :
In this extended UserService
, we override the create
method to check if the user has a store_id
associated with their account. If not, we create a new store and associate it with the user’s account before creating the new user.
Let’s run our server and try to create a new User
, we can use Postman or HTTPie to make a POST
request to /admin/users
when logged-in.
Let’s try with a simple payload like this one :
You should get a server’s response like this one :
Now, whenever we create a new User
a new Store
is associated to it !
Common Issues
I have CORS errors since I’ve added middlewares
If you have any CORS errors when accessing the Admin UI, this might solves your issue
Do not forget to add the environment variable ADMIN_CORS
in your .env
file
My loggedInUser
is undefined
or null
If you have this issue and are sure that you are logged in before making a request, please update your LIFE_TIME
services to TRANSIENT
, it should fix the issues :
GitHub Branch
You can access the complete part’s code here.
Next Steps
And this is where this first part of the series ends, as the recipe gives us a few more concepts, such as associating a store_id
with the creation of a product etc., before moving on to the “events/subscribers” part.
We’re not going to tackle events just yet, but rather continue to focus on service management and how to extend them so as to have everything nicely tied up to a vendor.
Was this page helpful?