Product Module Demo
Powered by Medusa
SDK for CommerceRead more

Medusa Product Module demo inNext.jsfunctions

This demo showcases our Product Module running in a serverless Next.js function. In the demo, we're using the Product Module to personalize the storefront in real time based on the user location and behavior.

What are Medusa Modules?

Modules are packages with self-contained commerce logic, promoting separation of concerns, maintainability, and reusability. Modules increase Medusa's extensibility, allowing for customization of core commerce logic and composition with other tools. This flexibility allows for greater choice in the tech stack used in conjunction with Medusa.

Why run it from a Next.js function?

Running Medusa's Product Module in a serverless function provides several benefits over hosting a conventional backend:

  • It offers fast response times, making it suitable for use cases like realtime personalization.
  • The Next.js function scales automatically to meet demand, meaning there is no need to worry about provisioning and managing servers.
  • The Next.js function is only invoked when needed, reducing the overall cost of running the module.

Our future work will focus on publishing all core Medusa domains as modules and making them compatible with edge runtimes.

How does the demo work?

The demo storefront personalizes the products shown based on user location and last viewed products.
The top part is based on your (simulated) country. It looks up the country's continent and shows all products tagged with that continent. So if you're visiting from France, you'll see European content, and so on.
The All products part will be sorted based on your last viewed product. It uses the product's category and shows all products from that category first. So if your last viewed product was from the tote bags category, it will show all tote bags on top.

How we implemented personalization

The code snippets below are simplified for readability. You can check out the full source code on GitHub.
  • Product Module
    Initialize the Product Module.

    Simply initialize the module in the Next.js API route.

    import { initialize as initializeProductModule } from "@medusajs/product";
    export async function GET(req) {
    const productService = await initializeProductModule();
    // list all products
    const products = await productService.list({});
    return NextResponse.json({ products });
    }

    All products are now displayed in standard order.

    All products - initial state
  • User location
    Get the user's location from the request header.

    We use the Vercel country header by default, or overwrite it with a simulated location when provided.

    import { initialize as initializeProductModule } from "@medusajs/product";
    export async function GET(req) {
    const productService = await initializeProductModule();
    // Get the user's (simulated) country code from the header.
    const countryCode = req.headers.get("x-country");
    // Get the user's continent from a mapper.
    const { name: country, continent } = isoAlpha2Countries[countryCode];
    // List 3 products with a tag that matches the user's continent.
    const personalizedProducts = await productService.list(
    { tags: { value: [continent] } },
    { take: 3 }
    );
    return NextResponse.json({ personalizedProducts });
    }

    Display the localized products.

    Localised products - initial state

    You can simulate a different location using the control panel.

    Simulate your location from the control panel.
  • Last viewed product
    Store the user's last viewed category in a Vercel KV store.

    When a user clicks a product, we store the product's category data in a KV store.

    import { kv } from "@vercel/kv";
    export async function POST(req) {
    // Grab the category data from the request.
    const { categoryId, categoryName } = await req.json();
    const userData = {
    categoryId,
    categoryName,
    };
    // Grab the userId from the cookie and assign the category data to the userId
    // in the KV store.
    const userId = req.cookies.get("userId").value;
    await kv.set(userId, userData);
    return new NextResponse();
    }

    Click a product to view its product page.

    Click a product to view its product page.
  • Personalize products
    Display all products with the last viewed category's products on top.

    We grab the user's last viewed category from the KV store and sort all products with that category on top.

    import { initialize as initializeProductModule } from "@medusajs/product";
    import { kv } from "@vercel/kv";
    export async function GET(req) {
    const productService = await initializeProductModule();
    // Grab the userId from the request and look up the categoryId from the KV.
    const userId = req.cookies.get("userId").value;
    const { categoryId } = await kv.get(userId);
    // Get all products.
    const allProducts = await productService.list({});
    // Re-order the products based on the last viewed categoryId.
    const orderedProducts = orderProductByCategoryIdFirst(allProducts, categoryId);
    return NextResponse.json({ orderedProducts });
    }

    Tote bags are now displayed on top!

    Tote bags are now displayed on top

Start building with the Product Module in Next.js

Ready to get started with the Medusa Product Module in your Next.js app? Visit our documentation to learn more and start building today!