Medusa storefront with multiple vendors
Tags: medusa, javascript, router, products
Published: 2022-06-02 02:18:47

Medusa is open-source project which provides many powerful e-commerce functions and extensions as Shopify. I follows the [article for multi-vendor marketplaces](https://dev.to/medusajs/create-an-open-source-commerce-marketplace-part-1-3m5k) shared from Shahed Nasser who is very outstanding engineer in Medusa Dev community. But it only shows for backend modification with [medusa-extender](https://github.com/adrien2p/medusa-extender), not include the change of frontend side. 

So I start to try to figure out how to modify the part of store frontend, but first we need to customize the original APIs for all vendors.

At first, following all steps from the [article for multi-vendor marketplaces](https://dev.to/medusajs/create-an-open-source-commerce-marketplace-part-1-3m5k).

Second, add the **store.router.ts** file as below. In where, I refined the client API '/store/products' for all vendors.
```
import { MedusaAuthenticatedRequest, Router } from 'medusa-extender';
import { Response, NextFunction } from "express";
import { User } from '../../user/entities/user.entity';

@Router({
    routes: [{
        requiredAuth: false,
        path: '/store/products',
        method: 'get',
        handlers: [
            async (req: MedusaAuthenticatedRequest, res: Response, next: NextFunction): Promise<Response<User[]>> => {
                const productService = req.scope.resolve("productService")
                const resProducts = await productService.list({},
                    {
                        relations: [
                            "variants",
                            "variants.prices",
                            "variants.options",
                            "options",
                            "options.values",
                            "images",
                            "tags",
                            "collection",
                            "type",
                        ],
                    });
                return res.send({
                    "products": resProducts,
                    "count": resProducts.length,
                    "offset": 0,
                    "limit": 100
                });
            }
        ]
    }] 
})
export class StoreRouter {}
```

Then add **StoreRouter** into your **store.module.ts**
```
@Module({
    imports: [Store, StoreRepository, StoreService, StoreRouter],
})
```

Easy way to skip the loggedInUser condition in **product.service.ts** then the product list will be changed to query for all vendors. It looks like tricky but I didn't get other options to make multi-vendors workable.
```
    prepareListQuery_(selector: object, config: object): object {
        /*const loggedInUser = this.container.loggedInUser
        if (loggedInUser) {
            selector['store_id'] = loggedInUser.store_id // this is for one store
        }*/

        return super.prepareListQuery_(selector, config);
    }
```

Rebuild and start backend in your local environment. Try to create a new vendor by postman.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nz1uxena0avhoyu5ldz4.png)

authenticate to this vendor then create a new product.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jltara78z02oas3xjueo.png)

In the end, all clients can query all products including the new product created by the new vendor, even the client didn't login yet.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qsnw1v10679cv8nrwuk.png)

**The difficult part is for the modification of store frontend**. I use [Medusa Gatsby Starter](https://github.com/medusajs/gatsby-starter-medusa) to my store frontend. However, there are many incompatible with my above modification of backend.

When I deployed all modification on the production environment, the store frontend rebuilt as well. But it shows failure as below:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9xc42x7oww4y1oc0rns.png)
  
Finally, I found the create node function(in the build time) from [gatsby-source-filesystem of gatsby](https://www.gatsbyjs.com/plugins/gatsby-source-filesystem/) does not support to pass the empty link address of product thumbnail. You must give it a valid url.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnau6mw6jfq1r8ofv7zo.png) 

I manually updated it to [imgur images I created in my previous post](https://dev.to/ivanchiou/medusa-images-uploading-using-imgur-api-2hli) in postgresql using [pgweb tool](https://github.com/sosedoff/pgweb) then it rebuilt successfully. But it is not the last mission. I still found an error in gatsby-starter-medusa if the product doesn't have any uploaded images.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z6l6v7t92kh3f9kfpwbo.png)
So we need to add below condition to prevent from this error.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51lrny38e47ymmul15f5.png)
  
I think it is not efficient to debug simultaneously both on these open-source projects, gatsby and medusa. But I will keep fighting with open-sources:)