Інтеграція Medusa.js з фронтендом (Next.js/Gatsby)
Medusa предоставляє Store API та опціональний TypeScript SDK @medusajs/js-sdk для роботи з фронтендом. Офіційний Next.js Storefront Starter — готова точка відлику, але для продукту потребує істотної доробки. Gatsby використовується рідше — підходить для каталогів з повільно мінливим контентом завдяки SSG.
Настройка Medusa JS SDK
npm install @medusajs/js-sdk @medusajs/types
import Medusa from '@medusajs/js-sdk';
export const medusaClient = new Medusa({
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL!,
auth: {
type: 'session',
},
publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
});
Next.js App Router: сторінка товара
export async function generateStaticParams() {
const { products } = await medusaClient.store.product.list({
fields: 'handle',
limit: 200,
});
return products.map(p => ({ handle: p.handle }));
}
export async function generateMetadata({ params }): Promise<Metadata> {
const { products } = await medusaClient.store.product.list({
handle: params.handle,
});
const product = products[0];
return {
title: product.title,
description: product.description,
};
}
export default async function ProductPage({ params }) {
const { products } = await medusaClient.store.product.list({
handle: params.handle,
fields: '*variants,*variants.prices,*images',
});
const product = products[0];
if (!product) notFound();
return <ProductTemplate product={product} />;
}
Управління корзиною
'use client';
import { createContext, useContext, useState, useEffect } from 'react';
type CartContextType = {
cart: HttpTypes.StoreCart | null;
addItem: (variantId: string, quantity: number) => Promise<void>;
};
const CartContext = createContext<CartContextType | null>(null);
export function CartProvider({ children }) {
const [cart, setCart] = useState(null);
useEffect(() => {
const cartId = localStorage.getItem('cart_id');
if (cartId) {
medusaClient.store.cart.retrieve(cartId)
.then(({ cart }) => setCart(cart));
}
}, []);
const addItem = async (variantId: string, quantity: number) => {
let currentCart = cart;
if (!currentCart) {
const { cart: newCart } = await medusaClient.store.cart.create({
region_id: process.env.NEXT_PUBLIC_MEDUSA_REGION_ID,
});
localStorage.setItem('cart_id', newCart.id);
currentCart = newCart;
}
const { cart: updatedCart } = await medusaClient.store.cart.createLineItem(
currentCart.id,
{ variant_id: variantId, quantity }
);
setCart(updatedCart);
};
return (
<CartContext.Provider value={{ cart, addItem }}>
{children}
</CartContext.Provider>
);
}
export const useCart = () => useContext(CartContext);
Мультирегіональність
import { NextRequest, NextResponse } from 'next/server';
const REGION_MAP = {
RU: process.env.MEDUSA_REGION_RU!,
BY: process.env.MEDUSA_REGION_BY!,
DEFAULT: process.env.MEDUSA_REGION_DEFAULT!,
};
export function middleware(request: NextRequest) {
const country = request.geo?.country ?? 'DEFAULT';
const regionId = REGION_MAP[country] ?? REGION_MAP.DEFAULT;
const response = NextResponse.next();
response.cookies.set('medusa_region', regionId, { maxAge: 60 * 60 * 24 });
return response;
}
Терміни інтеграції
- Next.js Storefront Starter + кастомізація: 2–3 тижні
- Кастомний Next.js з нуля (App Router, SSR/SSG, корзина, checkout): 6–10 тижнів
- Gatsby SSG-каталог з динамічною корзиною (hybrid): 4–6 тижнів
- Мультирегіональний магазин з локалізацією: +2–3 тижні







