medusajs/medusa-agent-skills14 files

Building With Medusa

Load automatically when planning, researching, or implementing ANY Medusa backend features (custom modules, API routes, workflows, data models, module links, business logic). REQUIRED for all Medusa backend work in ALL modes (planning, implementation, exploration). Contains architectural patterns, best practices, and critical rules that MCP servers don't provide.

Specification
Skill ID
medusajs/medusa-agent-skills/building-with-medusa
Publisher
medusajs
Repository
medusa-agent-skills
Installs
0
Files
14
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

medusajs/medusa-agent-skills/building-with-medusaInstalls these files
  • SKILL.md
  • reference/api-routes.md
  • reference/authentication.md
  • reference/custom-modules.md
  • reference/data-models.md
  • reference/error-handling.md
  • reference/frontend-integration.md
  • reference/module-links.md
  • reference/querying-data.md
  • reference/scheduled-jobs.md
  • reference/subscribers-and-events.md
  • reference/troubleshooting.md
  • reference/workflow-hooks.md
  • reference/workflows.md

What this skill tells the agent

Medusa Backend Development

Comprehensive backend development guide for Medusa applications. Contains patterns across 6 categories covering architecture, type safety, business logic placement, and common pitfalls.

When to Apply

Load this skill for ANY backend development task, including:

  • Creating or modifying custom modules and data models
  • Implementing workflows for mutations
  • Building API routes (store or admin)
  • Defining module links between entities
  • Writing business logic or validation
  • Querying data across modules
  • Implementing authentication/authorization

Also load these skills when:

  • building-admin-dashboard-customizations: Building admin UI (widgets, pages, forms)
  • building-storefronts: Calling backend API routes from storefronts (SDK integration)

CRITICAL: Load Reference Files When Needed

The quick reference below is NOT sufficient for implementation. You MUST load relevant reference files before writing code for that component.

Load these references based on what you're implementing:

  • Creating a module? → MUST load reference/custom-modules.md first
  • Creating workflows? → MUST load reference/workflows.md first
  • Creating API routes? → MUST load reference/api-routes.md first
  • Creating module links? → MUST load reference/module-links.md first
  • Querying data? → MUST load reference/querying-data.md first
  • Adding authentication? → MUST load reference/authentication.md first

Minimum requirement: Load at least 1-2 reference files relevant to your specific task before implementing.

Critical Architecture Pattern

ALWAYS follow this flow - never bypass layers:

Module (data models + CRUD operations)
  ↓ used by
Workflow (business logic + mutations with rollback)
  ↓ executed by
API Route (HTTP interface, validation middleware)
  ↓ called by
Frontend (admin dashboard/storefront via SDK)

Key conventions:

  • Only GET, POST, DELETE methods (never PUT/PATCH)
  • Workflows are required for ALL mutations
  • Business logic belongs in workflow steps, NOT routes
  • Query with query.graph() for cross-module data retrieval
  • Query with query.index() (Index Module) for filtering across separate modules with links
  • Module links maintain isolation between modules

Rule Categories by Priority

PriorityCategoryImpactPrefix
1Architecture ViolationsCRITICALarch-
2Type SafetyCRITICALtype-
3Business Logic PlacementHIGHlogic-
4Import & Code OrganizationHIGHimport-
5Data Access PatternsMEDIUM (includes CRITICAL price rule)data-
6File OrganizationMEDIUMfile-

Quick Reference

1. Architecture Violations (CRITICAL)

  • arch-workflow-required - Use workflows for ALL mutations, never call module services from routes
  • arch-layer-bypass - Never bypass layers (route → service without workflow)
  • arch-http-methods - Use only GET, POST, DELETE (never PUT/PATCH)
  • arch-module-isolation - Use module links, not direct cross-module service calls
  • arch-query-config-fields - Don't set explicit fields when using req.queryConfig

2. Type Safety (CRITICAL)

  • type-request-schema - Pass Zod inferred type to MedusaRequest<T> when using req.validatedBody
  • type-authenticated-request - Use AuthenticatedMedusaRequest for protected routes (not MedusaRequest)
  • type-export-schema - Export both Zod schema AND inferred type from middlewares
  • type-linkable-auto - Never add .linkable() to data models (automatically added)
  • type-module-name-camelcase - Module names MUST be camelCase, never use dashes (causes runtime errors)

3. Business Logic Placement (HIGH)

  • logic-workflow-validation - Put business validation in workflow steps, not API routes
  • logic-ownership-checks - Validate ownership/permissions in workflows, not routes
  • logic-module-service - Keep modules simple (CRUD only), put logic in workflows

4. Import & Code Organization (HIGH)

  • import-top-level - Import workflows/modules at file top, never use await import() in route body
  • import-static-only - Use static imports for all dependencies
  • import-no-dynamic-routes - Dynamic imports add overhead and break type checking
  • import-zod-framework - Import Zod from @medusajs/framework/zod, never from zod directly. Medusa is on Zod v4 (since v2.14.0): use z.email()/z.url()/z.uuid() instead of z.string().email() etc., .extend(other.shape) instead of .merge(other), z.strictObject()/z.looseObject() instead of .strict()/.passthrough(), z.enum(MyEnum) instead of z.nativeEnum(), and z.record(z.string(), value) instead of z.record(value)

5. Data Access Patterns (MEDIUM)

  • data-price-format - CRITICAL: Prices are stored as-is in Medusa (49.99 stored as 49.99, NOT in cents). Never multiply by 100 when saving or divide by 100 when displaying
  • data-query-method - Use query.graph() for retrieving data; use query.index() (Index Module) for filtering across linked modules
  • data-query-graph - Use query.graph() for cross-module queries with dot notation (without cross-module filtering)
  • data-query-index - Use query.index() when filtering by properties of linked data models in separate modules
  • data-list-and-count - Use listAndCount for single-module paginated queries
  • data-linked-filtering - query.graph() can't filter by linked module fields - use query.index() or query from that entity directly
  • data-no-js-filter - Don't use JavaScript .filter() on linked data - use database filters (query.index() or query the entity)
  • data-same-module-ok - Can filter by same-module relations with query.graph() (e.g., product.variants)
  • data-auth-middleware - Trust authenticate middleware, don't manually check req.auth_context

6. File Organization (MEDIUM)

  • file-workflow-steps - Recommended: Create steps in src/workflows/steps/[name].ts
  • file-workflow-composition - Composition functions in src/workflows/[name].ts
  • file-middleware-exports - Export schemas and types from middleware files
  • file-links-directory - Define module links in src/links/[name].ts

Workflow Composition Rules

The workflow function has critical constraints:

// ✅ CORRECT
const myWorkflow = createWorkflow(
  "name",
  function (input) { // Regular function, not async, not arrow
    const result = myStep(input) // No await
    return new WorkflowResponse(result)
  }
)

// ❌ WRONG
const myWorkflow = createWorkflow(
  "name",
  async (input) => { // ❌ No async, no arrow functions
    const result = await myStep(input) // ❌ No await
    if (input.condition) { /* ... */ } // ❌ No conditionals
    return new WorkflowResponse(result)
  }
)

Constraints:

  • No async/await (runs at load time)
  • No arrow functions (use function)
  • No conditionals/ternaries (use when())
  • No variable manipulation (use transform())
  • No date creation (use transform())
  • Multiple step calls need .config({ name: "unique-name" }) to avoid conflicts

Common Mistakes Checklist

Before implementing, verify you're NOT doing these:

Architecture:

  • [ ] Calling module services directly from API routes
  • [ ] Using PUT or PATCH methods
  • [ ] Bypassing workflows for mutations
  • [ ] Setting fields explicitly with req.queryConfig
  • [ ] Skipping migrations after creating module links

Type Safety:

  • [ ] Forgetting MedusaRequest<SchemaType> type argument
  • [ ] Using MedusaRequest instead of AuthenticatedMedusaRequest for protected routes
  • [ ] Not exporting Zod inferred type from middlewares
  • [ ] Adding .linkable() to data models
  • [ ] Using dashes in module names (must be camelCase)

Business Logic:

  • [ ] Validating business rules in API routes
  • [ ] Checking ownership in routes instead of workflows

Use this skill in a project

Open any RiverX project, search the Skills panel for medusajs/medusa-agent-skills/building-with-medusa, and install it in one click.

Use this skill