Crafting a Dynamic E-Commerce Experience: Customizable UI with Sanity CMS, Medusa.js, and Next.js
As e-commerce continues to evolve, the demand for customizable and dynamic user interfaces has skyrocketed. In my latest project, I’ve harnessed the power of Sanity CMS, Medusa.js, and Next.js to create an e-commerce platform that allows users to configure their own UI with ease. Join me as I walk you through the core concept behind this project, focusing on the configurable UI aspect that truly sets it apart from traditional setups.
Why Configurable UI?
The main goal of integrating Sanity CMS into my Medusa.js e-commerce application was to empower content creators and marketers. They can now define the user interface and its components directly from a user-friendly interface without needing any developer intervention. This flexibility not only accelerates the development process but also enhances the ability to quickly adapt to market changes.
Designing the Schema in Sanity
To facilitate this configurability, I designed a series of schemas in Sanity that correspond to different sections of the e-commerce UI. Each schema defines the structure and options available for a given section, enabling users to customize content blocks easily. Here’s a glimpse at some key schemas I implemented for specific UI sections:
Here’s an example of one of the schemas — mediaItems, which allows users to include images or videos in their layout:
export const mediaItems = {
name: generateName(SECTION_NAME.MEDIA_ITEMS),
title: SECTION_NAME.MEDIA_ITEMS,
type: "object",
fields: [
{
name: "mediaType",
title: "Media Type",
type: "string",
options: { list: ["Image", "Video"] },
},
{
name: "media",
title: "Media",
type: "array",
of: [{ type: "image" }],
hidden: ({ parent }) => parent?.mediaType !== "Image",
},
{
name: "video",
title: "Video",
type: "array",
of: [{ type: "url" }],
hidden: ({ parent }) => parent?.mediaType !== "Video",
},
],
};
In this schema, users can choose between different media types (Image or Video) and provide the necessary content. This flexibility allows for a rich media experience directly managed through Sanity.
Dynamic Section Creation
What makes this project truly exciting is the ability for users to create and configure multiple types of sections on-the-fly. For instance, if a user wants to add a carousel of featured products, they can simply select the carousel section in the CMS and input the relevant media.
Carousel Schema Example:
export const carousel = {
name: generateName(SECTION_NAME.CAROUSEL),
title: SECTION_NAME.CAROUSEL,
type: "object",
fields: [
{
name: "carouselType",
title: "Carousel Type",
type: "string",
options: { list: ["Image", "Short Video", "Category Link"] },
},
{
name: "carouselImage",
title: "Image",
type: "array",
of: [{ type: "image" }],
hidden: ({ parent }) => parent?.carouselType !== "Image",
},
{
name: "category",
title: "Category",
type: "array",
of: [{ type: "reference", to: [{ type: "productCategory" }] }],
hidden: ({ parent }) => parent?.carouselType !== "Category Link",
},
],
};
By allowing users to choose the type of carousel they want to implement, it grants them the freedom to create a visually engaging and functional section tailored to their branding and messaging.
Rendering Dynamic UI with Next.js
With the schemas defined, the next step was to dynamically render these components in Next.js. I implemented a function that interprets the section data from Sanity and renders the corresponding React components accordingly:
export default function RenderSection({ section }) {
switch (section.sectionName) {
case SECTION_NAME.CAROUSEL:
return <Carousel section={section as CarouselProps} />;
case SECTION_NAME.MEDIA_ITEMS:
return <MediaItem section={section as MediaItemProps} />;
default:
return <div className="text-black">{section.sectionName}</div>;
}
}
This function ensures that the right components are displayed based on user choices while maintaining a clean and organized codebase.
Synchronizing Data with Medusa.js
A crucial part of this project is the integration of Medusa.js services and subscribers, which synchronize data between Sanity and the Medusa backend. By utilizing Medusa’s API, I ensured that updates made in the Sanity CMS — such as adding new products or editing existing ones — are reflected in real-time within the e-commerce platform.
Implementing Services and Subscribers
Services: I used Medusa’s services to handle events triggered from Sanity. For instance, when an admin updates product details in Sanity, a service can invoke a Medusa API call to update the corresponding data in the Medusa database.
Subscribers: Medusa’s subscriber model allows for real-time communication. By subscribing to specific data changes, I ensured that the UI dynamically reflects any updates made in Sanity. For example, if a new section is added or an existing one is modified in Sanity, subscribers alert the front end to refresh and display the updated content.
Example Integration
Here’s an example of how a product update in Sanity triggers an update in Medusa:
Sanity Update: A product’s description is modified in Sanity CMS.
Service Trigger: A Medusa service listens for this change and retrieves the updated data.
API Call: An API call is made to Medusa to update the product information in the database.
Subscriber Notification: The frontend, subscribed to the product updates, automatically refreshes to display the new product details.
An Empowering E-Commerce Solution
Integrating Sanity CMS with Medusa.js has created a powerful and flexible e-commerce platform that empowers users to configure their UI as they see fit. The combination of dynamic schemas, customizable components, and real-time data synchronization results in a rich user experience and an easy-to-manage system for content creators.By leveraging these technologies, you can drastically reduce the time needed for content updates and allow marketers and admins to create engaging pages that resonate with customers. If you’re interested in building a similar solution, I encourage you to explore Sanity and Medusa.js. The potential for customization and flexibility is immense! Thank you for reading! I hope this insight into building a configurable UI with Medusa.js and Sanity CMS inspires your next e-commerce project. This blog post now combines the themes of configurable UI, schema design, and Medusa.js integration, providing a comprehensive overview of your project. Let me know if there are any other aspects you’d like to focus on!