| name | Medusa Ecommerce |
| description | Build ecommerce applications with Medusa v2 - commerce modules, customization, workflows, and deployment |
| version | 2 |
Medusa Ecommerce Skill
Build modern ecommerce applications with Medusa v2's modular architecture.
Context7 Integration
Always use context7 MCP for up-to-date API documentation:
mcp-cli call context7/resolve-library-id '{"libraryName": "medusajs"}'
Query pattern:
mcp-cli call context7/query-docs '{"libraryId": "/websites/medusajs_learn", "topic": "your topic"}'
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ Medusa Application │
├─────────────────────────────────────────────────────────────────┤
│ API Layer │ Admin Routes (/admin) │
│ │ Store Routes (/store) │
│ │ Custom Routes (/custom) │
├─────────────────────────────────────────────────────────────────┤
│ Workflows │ Multi-step operations with compensation │
├─────────────────────────────────────────────────────────────────┤
│ Commerce Modules │ Product │ Cart │ Order │ Payment │ etc. │
├─────────────────────────────────────────────────────────────────┤
│ Infrastructure │ Cache │ Events │ File │ Notification │
├─────────────────────────────────────────────────────────────────┤
│ Database │ PostgreSQL with MikroORM │
└─────────────────────────────────────────────────────────────────┘
Project Structure
my-medusa-store/
├── src/
│ ├── modules/ # Custom modules
│ │ └── my-module/
│ │ ├── index.ts
│ │ ├── service.ts
│ │ └── models/
│ ├── workflows/ # Custom workflows
│ ├── subscribers/ # Event subscribers
│ ├── api/ # API routes
│ │ ├── admin/
│ │ ├── store/
│ │ └── middlewares.ts
│ ├── admin/ # Admin UI extensions
│ │ ├── routes/
│ │ └── widgets/
│ └── links/ # Module links
├── medusa-config.ts
└── package.json
Quick Reference
Container Resolution
const productService = container.resolve("product")
const query = container.resolve("query")
Query (Graph) Operations
import { Query } from "@medusajs/framework"
const { data: products } = await query.graph({
entity: "product",
fields: ["id", "title", "variants.*", "variants.prices.*"],
filters: { id: productId }
})
const { data, metadata } = await query.graph({
entity: "order",
fields: ["*", "items.*"],
pagination: { skip: 0, take: 20 }
})
Remote Query (Cross-Module)
import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
const { data } = await useQueryGraphStep({
entity: "product",
fields: ["*", "inventory_items.*"]
})
Creating API Routes
import { MedusaRequest, MedusaResponse } from "@medusajs/framework"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const query = req.scope.resolve("query")
res.json({ data })
}
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
const body = req.body
res.json({ success: true })
}
Protected Admin Routes
import { MedusaRequest, MedusaResponse } from "@medusajs/framework"
import { authenticate } from "@medusajs/medusa"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
res.json({ data })
}
Creating Workflows
import { createWorkflow, createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
const myStep = createStep(
"my-step",
async (input: { data: string }, { container }) => {
const service = container.resolve("myService")
const result = await service.doSomething(input.data)
return new StepResponse(result, result.id)
},
async (id, { container }) => {
const service = container.resolve("myService")
await service.undoSomething(id)
}
)
export const myWorkflow = createWorkflow("my-workflow", (input) => {
const result = myStep(input)
return result
})
Event Subscribers
import { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
export default async function orderPlacedHandler({
event,
container
}: SubscriberArgs<{ id: string }>) {
const orderId = event.data.id
const logger = container.resolve("logger")
logger.info(`Order placed: ${orderId}`)
}
export const config: SubscriberConfig = {
event: "order.placed"
}
Data Models
import { model } from "@medusajs/framework/utils"
const MyModel = model.define("my_model", {
id: model.id().primaryKey(),
name: model.text(),
description: model.text().nullable(),
metadata: model.json().nullable(),
is_active: model.boolean().default(true),
created_at: model.dateTime(),
})
export default MyModel
Module Links
import { defineLink } from "@medusajs/framework/utils"
import ProductModule from "@medusajs/medusa/product"
import MyModule from "../modules/my-module"
export default defineLink(
ProductModule.linkable.product,
MyModule.linkable.myModel
)
Common Operations
Create Product with Variants
const product = await productService.createProducts({
title: "T-Shirt",
options: [{ title: "Size", values: ["S", "M", "L"] }],
variants: [
{ title: "Small", options: { Size: "S" }, prices: [{ amount: 1000, currency_code: "usd" }] },
{ title: "Medium", options: { Size: "M" }, prices: [{ amount: 1000, currency_code: "usd" }] },
]
})
Cart to Order Flow
const cart = await cartService.createCarts({ region_id, currency_code: "usd" })
await cartService.addLineItems(cart.id, [{ variant_id, quantity: 1 }])
await cartService.addShippingMethods(cart.id, [{ shipping_option_id }])
await paymentService.createPaymentCollections({ cart_id: cart.id })
import { completeCartWorkflow } from "@medusajs/medusa/core-flows"
await completeCartWorkflow(container).run({ input: { id: cart.id } })
Payment Integration
const paymentCollection = await paymentService.createPaymentCollections({
cart_id: cartId,
amount: cart.total,
currency_code: cart.currency_code,
})
await paymentService.createPaymentSession(paymentCollection.id, {
provider_id: "stripe",
data: { }
})
CLI Commands
npx medusa develop
npx medusa db:migrate
npx medusa db:generate
npx medusa db:sync-links
npx medusa build
npx medusa start
Reference Files
Detailed documentation organized by topic:
| File | Topics |
|---|
| commerce-modules.md | Product, Cart, Order, Pricing, Inventory, Customer |
| checkout-payments.md | Payment, Fulfillment, Tax, Region, Sales Channel |
| customization.md | Custom modules, services, data models, links, API routes |
| workflows-events.md | Workflows, steps, compensation, subscribers, events |
| admin-storefront.md | Admin UI extensions, JS SDK, storefront integration |
| infrastructure-production.md | Redis, S3, SendGrid, deployment, medusa-config.ts |
Best Practices
- Use workflows for multi-step operations - Built-in compensation handles failures
- Query with
query.graph() - Efficient data fetching with relations
- Extend, don't modify - Create custom modules instead of modifying core
- Use module links - Connect custom data to core entities
- Validate at API layer - Use Zod schemas for request validation
- Subscribe to events - React to changes asynchronously
Troubleshooting
Module not found: Ensure module is registered in medusa-config.ts
Link not working: Run npx medusa db:sync-links after adding links
Migration issues: Check model definitions match database schema
Type errors: Regenerate types with npx medusa generate:types