Universal Medusa: The why, when and how of universal e-commerce apps with Medusa.js, Expo and Next.js
Universal Medusa is a monorepo starter kit that allows you to build Expo universal native apps for e-commerce that run on iOS, Android, and the web (as a Next.js app). It provides React Native components that seamlessly function on all platforms and that integrate fully with the e-commerce headless modules of Medusa.js.
On this post we will take a look into explaining why you may want to use it in your next or current e-commerce app, on which cases it makes sense to build on top of a universal arquitecture like this one and finally details as to how the project is configured.
Why you should start your next e-commerce project with Universal Medusa
If you want to own your e-commerce stack and have it fit your needs perfectly as your project keeps growing, a great way to do so is to use Medusa.js. An OSS project, MIT licensed, robust headless solution. It's the most popular e-commerce project in the JS ecosystem (20k stars on Github), with an amazing roadmap, awards in between, and a great team behind it.
Out of the box you get all the core e-commerce building blocks you need, both backend and frontend-wise, with unlimited flexibility to build it according to your own business requirements, features, pipelines, and tools on top.
Medusa modules are integrated to the frontend to bring you a full-fledged e-commerce app that has a flexible frontend architecture which enables you to target multiple platforms, such as native mobile (IOS/Android) and web. We take this for granted on the React Native world but now add on top that you get a web app too. How many engineering hours will you save on the lifespan of the project? The scale of efficiency this brings has no comparison when building just for one platform or when buildings many apps separately, each on it’s own stack. Universal means pushing the efficiency limits even further when we add web compatibility on top. That's why Universal Medusa is built with React Native/Expo. Because it’s built to be multi-platform and cross-platform too with this extra setup.
There are many benefits of building e-commerce apps with Universal Medusa but for the purposes of brevity let’s focus on two important ones related to the the universal architecture:
Faster time to market: One team / one tech stack to develop on all platforms at the same time which enables faster time to market on all your development features.
More resilient applications: There are less bugs and less vulnerabilities in Universal Medusa because the code is not spread out across different implementations.
The Expo team and the React Native community have been steadily growing an ecosystem that allows you to build the most powerful type of universal apps available in the market.
All the Expo core packages have universal compatibility, you have React Native Web to convert native views to web views (used on production at Meta and X/Twitter), as well as the instant compatibility of React components that work out of the box on all platforms. There is also a huge amount of universal compatible packages that you can find on the React Native Directory by filtering with the web tag. You can also develop components with custom implementations per platform when needed (We have used this feature a few times on the project, such as when using the country select component as a dropdown on the web and an Action Sheet on native).
When to build with Universal Medusa
You don't always need a universal app stack. It is specific to the needs of a project. So if your app doesn't require web or mobile functionality, and you're satisfied with a core platform that meets your users needs, then you can skip universal app development. However, note that often you initially focus on solving for one platform and later on realize the need for web or mobile capabilities further down the road.
That aside, my take is that for e-commerce, you need both platforms right away. That's because when you need to choose your platforms, it's about where your users are, and in e-commerce, they are buying on mobile and web independently - interchangeably.
We should not forget that having the web app bound to native also means you empower your app's discoverability cycle by enabling discovery through the web, which boosts your native installs and usage.
Focusing solely on Medusa.js for a second which will be your core e-commerce logic provider on this setup, I believe it is the right technology for you if you have an e-commerce project of any size where the most important requirement is that you want 100% control. That is in all senses: technically and financially. If you need/want to skip fees, such as Shopify's percentage on sales, require custom solutions that external providers (through plugins) have but don't apply 100% to your use case, or want, for many reasons, to have full control of the frontend, backend, and logistics layers, this setup is for you.
How to build with Universal Medusa
Universal Medusa is built on top of the Solito stack. It comes as a turbo-charged monorepo with all the logic and components placed in the packages/app
workspace. The Expo and Next.js apps are each standalone apps in different workspaces. This enables easy sharing of all your logic and screens in a flexible and organized structure, allowing your e-commerce to continue growing. You get to share all your JavaScript and React logic, such as modules, hooks, types, providers, context, and components, as well as JS-only libraries and modules.
When it’s time to use and share components on each platform the process is very simple. Both apps are wrapped with the same providers on the root and then by just importing any screen component on the respective router file for each platform your are all set and done.
Styling on the project was done with Nativewind, React Native’s best alternative to Tailwind.
It could be the case too that if you started your Medusa project using Medusa.js Next.js starter you will get a good surprise: this project is a port from that repository so it has a good compatibility layer of styling (enhanced to match Nativewind) and of code structure. Good to know that if you want to port from web to universal this is a testament that it is 100% doable.
When you choose to follow the Expo Universal approach, what you get back is a lot of code reuse. We're talking about 95% or more reuse. Pretty much all of the codebase is reusable, except for some pieces such as the navigation. This is a good thing, though. Navigation is a platform-specific implementation that is different on the web and on native. The reason for this is that we have different user expectations on both platforms. That's why you should implement them differently.
The good news is that by having file-based navigation on both platforms, you gain the mental model to implement new routes easily. You create routes with the same paradigm by using Expo Router and Next.js Pages Router, matching route paths. It's super simple, just adhere to the folder structure, and what you get is seamless routing that behaves the same on both web and native.
Thanks to the power of Expo Router, we have something very significant here: universal links out of the box. If you want to share a product item URL on native, you got it. Want to have a deep link that opens a product page from a mobile browser to your native app? it's done.
Final thoughts
The idea of this post was to give you a brief introduction to the project and some insights about how it came to be and what it is for. But enough talk already! You can go and spin up a full-sized project right away with:
npx create-universal-medusa-app my-app
Get to know all about the project on the docs @ http://dub.sh/universalmedusa
Take a look at the repo and give us a ⭐ @ http://github.com/bidah/universal-medusa
Got questions about the project, need more comprehensive support, or want to move into production using Universal Medusa? You can reach out by booking a meeting.
Last but not least you can follow me on X / Twitter where I share all about building expo universal native apps in public.
Subscribe to my newsletter
Read articles from Rodrigo Figueroa directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by