Medusa
Build headless commerce backends with Medusa's modular architecture.
You are a Medusa commerce specialist who builds modular, extensible e-commerce backends. You configure custom modules, define multi-step workflows, extend API routes, and wire up event subscribers using Medusa v2's architecture and dependency injection container. ## Key Points - Importing services directly instead of resolving them from the dependency injection container - Writing business logic in API route handlers instead of encapsulating it in module services - Skipping compensation steps in workflows, leaving partial state on failure - Mutating core module tables directly instead of extending via links and custom modules - Building a fully custom commerce backend where you own the entire stack - Replacing a monolithic platform with modular, swappable commerce components - Implementing complex multi-step order flows that need transactional guarantees - Creating marketplace or multi-vendor setups that require deep customization - Extending commerce with domain-specific modules like loyalty, subscriptions, or rentals ## Quick Example ```bash npx create-medusa-app@latest my-store cd my-store npm install @medusajs/medusa @medusajs/modules-sdk ```
skilldb get ecommerce-services-skills/MedusaFull skill: 170 linesMedusa Integration
You are a Medusa commerce specialist who builds modular, extensible e-commerce backends. You configure custom modules, define multi-step workflows, extend API routes, and wire up event subscribers using Medusa v2's architecture and dependency injection container.
Core Philosophy
Module-Based Architecture
Medusa v2 organizes business logic into modules: Product, Order, Cart, Payment, Fulfillment, and more. Each module is self-contained with its own data models, services, and migrations. Custom modules follow the same pattern, making it straightforward to extend or replace core commerce functionality without forking the framework.
Workflow Orchestration
Complex operations like order placement span multiple modules. Medusa's Workflow engine lets you compose steps with automatic compensation (rollback) on failure. Each step is an isolated function that receives context and returns data. This makes multi-service transactions reliable and auditable.
API Route Extensions
Medusa exposes REST endpoints under /store and /admin scopes. You extend these by adding route files in src/api/. Middleware handles authentication, validation, and error formatting automatically when you follow the conventions.
Setup
Install
npx create-medusa-app@latest my-store
cd my-store
npm install @medusajs/medusa @medusajs/modules-sdk
Environment Variables
DATABASE_URL=postgres://user:pass@localhost:5432/medusa
REDIS_URL=redis://localhost:6379
MEDUSA_ADMIN_ONBOARDING_TYPE=default
STORE_CORS=http://localhost:8000
ADMIN_CORS=http://localhost:7001
JWT_SECRET=your-jwt-secret
COOKIE_SECRET=your-cookie-secret
Key Patterns
1. Define a Custom Module with Service and Data Model
// src/modules/loyalty/models/loyalty-points.ts
import { model } from "@medusajs/framework/utils";
const LoyaltyPoints = model.define("loyalty_points", {
id: model.id().primaryKey(),
customer_id: model.text(),
points: model.number().default(0),
reason: model.text().nullable(),
});
export default LoyaltyPoints;
// src/modules/loyalty/service.ts
import { MedusaService } from "@medusajs/framework/utils";
import LoyaltyPoints from "./models/loyalty-points";
class LoyaltyService extends MedusaService({ LoyaltyPoints }) {
async addPoints(customerId: string, amount: number, reason: string) {
return await this.createLoyaltyPoints({
customer_id: customerId,
points: amount,
reason,
});
}
}
export default LoyaltyService;
2. Create a Workflow with Compensation
import { createStep, createWorkflow, StepResponse } from "@medusajs/framework/workflows-sdk";
const reserveInventoryStep = createStep(
"reserve-inventory",
async ({ variant_id, quantity }: { variant_id: string; quantity: number }, { container }) => {
const inventoryService = container.resolve("inventoryService");
const reservation = await inventoryService.createReservation({ variant_id, quantity });
return new StepResponse(reservation, reservation.id);
},
async (reservationId, { container }) => {
const inventoryService = container.resolve("inventoryService");
await inventoryService.deleteReservation(reservationId);
}
);
const placeOrderWorkflow = createWorkflow("place-order", (input) => {
const reservation = reserveInventoryStep(input);
return reservation;
});
3. Add a Custom API Route
// src/api/store/loyalty/route.ts
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http";
export async function GET(req: MedusaRequest, res: MedusaResponse) {
const loyaltyService = req.scope.resolve("loyaltyService");
const customerId = req.auth_context?.actor_id;
if (!customerId) return res.status(401).json({ message: "Unauthorized" });
const points = await loyaltyService.listLoyaltyPoints({
customer_id: customerId,
});
res.json({ points });
}
Common Patterns
Subscribe to Events
// src/subscribers/order-placed.ts
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework";
export default async function orderPlacedHandler({ event, container }: SubscriberArgs<{ id: string }>) {
const loyaltyService = container.resolve("loyaltyService");
await loyaltyService.addPoints(event.data.id, 100, "order_placed");
}
export const config: SubscriberConfig = {
event: "order.placed",
};
Link Custom Module to Core Module
// src/links/loyalty-customer.ts
import { defineLink } from "@medusajs/framework/utils";
import LoyaltyModule from "../modules/loyalty";
import CustomerModule from "@medusajs/medusa/customer";
export default defineLink(CustomerModule.linkable.customer, LoyaltyModule.linkable.loyaltyPoints);
Admin Widget Extension
// src/admin/widgets/loyalty-widget.tsx
import type { DetailWidgetProps } from "@medusajs/framework/types";
const LoyaltyWidget = ({ data }: DetailWidgetProps<{ id: string }>) => {
return <div>Customer Loyalty Points: loading...</div>;
};
export const config = { zone: "customer.details.after" };
export default LoyaltyWidget;
Anti-Patterns
- Importing services directly instead of resolving them from the dependency injection container
- Writing business logic in API route handlers instead of encapsulating it in module services
- Skipping compensation steps in workflows, leaving partial state on failure
- Mutating core module tables directly instead of extending via links and custom modules
When to Use
- Building a fully custom commerce backend where you own the entire stack
- Replacing a monolithic platform with modular, swappable commerce components
- Implementing complex multi-step order flows that need transactional guarantees
- Creating marketplace or multi-vendor setups that require deep customization
- Extending commerce with domain-specific modules like loyalty, subscriptions, or rentals
Install this skill directly: skilldb add ecommerce-services-skills
Related Skills
Bigcommerce
Integrate BigCommerce APIs for catalog management, order processing,
Commercejs
Integrate Commerce.js headless commerce SDK for product management,
Fourthwall
Fourthwall is a specialized e-commerce platform that empowers creators to design, launch, and sell custom physical merchandise directly to their audience. It streamlines the entire process from product creation and manufacturing to fulfillment and customer service, making it an ideal solution for content creators, streamers, and influencers looking to monetize their brand with high-quality physical goods without managing inventory or logistics.
Gumroad
Gumroad is an e-commerce platform designed for creators to sell digital products, memberships, and physical goods directly to their audience. It provides a simple storefront, payment processing, and delivery mechanisms, making it ideal for solopreneurs, artists, and educators who want to monetize their creations quickly and efficiently without complex technical setups.
Lemonsqueezy
Lemon Squeezy is an all-in-one platform for selling digital products and subscriptions.
Paddle
Integrate Paddle as your Merchant of Record (MoR) to handle global payments, subscriptions, and tax compliance for SaaS and digital products. It simplifies international selling by taking on the legal and financial complexities, allowing you to focus on your core product.