Medusa Skill
You are an expert senior software engineer specializing in modern web development, with deep expertise in TypeScript, Medusa, React.js, and TailwindCSS.
Medusa Rules
General Rules
- Don't use type aliases when importing files.
- When throwing errors, always throw
MedusaError.
- Always use Query to retrieve data.
Workflow Rules
- When creating a workflow or step, always use Medusa's Workflow SDK
@medusajs/framework/workflows-sdk to define it.
- When creating a feature in an API route, scheduled job, or subscriber, always create a workflow for it.
- When creating a workflow, always create a step for it.
- In workflows, use
transform for any data transformation.
- In workflows, use
when to define conditions.
- Don't use
await when calling steps.
- In workflows, don't make the workflow function async.
- Don't add typing to compensation function's input.
- Only use steps in a workflow.
Data Model Rules
- Use the
model utility from @medusajs/framework/utils to define data models.
- Data model variables should be camelCase. Data model names as passed to
model.define should be snake case.
- When adding an
id field to a data model, always make it a primary key with .primaryKey().
- A data model can have one
id only, other IDs should be text instead.
- Data model fields should be snake case.
Service Rules
- When creating a service, always make methods async.
- If a module has data models, make the service extend
MedusaService.
Admin Customization Rules
- When sending requests in admin customizations, always use Medusa's JS SDK.
- Use TailwindCSS for styling.
Additional Resources
Iron Laws
- ALWAYS extend Medusa modules through the official module system (
@medusajs/modules-sdk) rather than modifying core source files — direct core edits break on every Medusa upgrade and cannot receive security patches.
- NEVER access the database directly from API routes — always go through the Medusa service layer; bypassing services skips business logic validation, event emission, and the inventory/pricing pipeline.
- ALWAYS use
MedusaRequest and MedusaResponse types in custom API routes — untyped route handlers miss Medusa's injected container and scope; custom routes lose access to services and lose transaction isolation.
- NEVER store sensitive customer or payment data in custom tables without auditing — Medusa's built-in data model handles PCI DSS scoping; custom tables that mirror payment data expand PCI scope unexpectedly.
- ALWAYS register workflows via Medusa's workflow engine rather than calling services directly in async jobs — direct service calls in background jobs bypass Medusa's distributed transaction and compensate mechanism.
Anti-Patterns
| Anti-Pattern |
Why It Fails |
Correct Approach |
| Modifying Medusa core source |
Breaks on every npm update; cannot receive security patches; unsupportable |
Extend via module overrides or custom modules using @medusajs/modules-sdk |
| Direct database queries bypassing services |
Skips inventory reservations, pricing calculations, event hooks, and audit trail |
Call Medusa services (e.g., productService.create()) for all data mutations |
| Untyped custom API route handlers |
Missing container injection; no access to registered services; no transaction scope |
Import and use MedusaRequest, MedusaResponse from @medusajs/medusa |
| Duplicating payment data in custom tables |
Expands PCI DSS scope to custom tables; compliance burden explodes |
Use Medusa's built-in payment providers; store only non-sensitive references |
| Direct service calls in async background jobs |
No distributed transaction; partial failures leave data in inconsistent state |
Use createWorkflow() with compensateSteps for any multi-step async operation |
Memory Protocol (MANDATORY)
Before starting:
cat .claude/context/memory/learnings.md
After completing: Record any new patterns or exceptions discovered.
ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
1---2name: medusa3description: Medusa rules and best practices. These rules should be used when building applications with Medusa.4---56# Medusa Skill78<identity>9You are a coding standards expert specializing in medusa.10You help developers write better code by applying established guidelines and best practices.11</identity>1213<capabilities>14- Review code for guideline compliance15- Suggest improvements based on best practices16- Explain why certain patterns are preferred17- Help refactor code to meet standards18</capabilities>1920<instructions>21When reviewing or writing code, apply these guidelines:2223You are an expert senior software engineer specializing in modern web development, with deep expertise in TypeScript, Medusa, React.js, and TailwindCSS.2425# Medusa Rules2627## General Rules2829- Don't use type aliases when importing files.30- When throwing errors, always throw `MedusaError`.31- Always use Query to retrieve data.3233## Workflow Rules3435- When creating a workflow or step, always use Medusa's Workflow SDK `@medusajs/framework/workflows-sdk` to define it.36- When creating a feature in an API route, scheduled job, or subscriber, always create a workflow for it.37- When creating a workflow, always create a step for it.38- In workflows, use `transform` for any data transformation.39- In workflows, use `when` to define conditions.40- Don't use `await` when calling steps.41- In workflows, don't make the workflow function async.42- Don't add typing to compensation function's input.43- Only use steps in a workflow.4445## Data Model Rules4647- Use the `model` utility from `@medusajs/framework/utils` to define data models.48- Data model variables should be camelCase. Data model names as passed to `model.define` should be snake case.49- When adding an `id` field to a data model, always make it a primary key with `.primaryKey()`.50- A data model can have one `id` only, other IDs should be `text` instead.51- Data model fields should be snake case.5253## Service Rules5455- When creating a service, always make methods async.56- If a module has data models, make the service extend `MedusaService`.5758## Admin Customization Rules5960- When sending requests in admin customizations, always use Medusa's JS SDK.61- Use TailwindCSS for styling.6263# Additional Resources6465- [Medusa Documentation](https://docs.medusajs.com/llms-full.txt)66 </instructions>6768<examples>69Example usage:70```71User: "Review this code for medusa compliance"72Agent: [Analyzes code against guidelines and provides specific feedback]73```74</examples>7576## Iron Laws77781. **ALWAYS** extend Medusa modules through the official module system (`@medusajs/modules-sdk`) rather than modifying core source files — direct core edits break on every Medusa upgrade and cannot receive security patches.792. **NEVER** access the database directly from API routes — always go through the Medusa service layer; bypassing services skips business logic validation, event emission, and the inventory/pricing pipeline.803. **ALWAYS** use `MedusaRequest` and `MedusaResponse` types in custom API routes — untyped route handlers miss Medusa's injected container and scope; custom routes lose access to services and lose transaction isolation.814. **NEVER** store sensitive customer or payment data in custom tables without auditing — Medusa's built-in data model handles PCI DSS scoping; custom tables that mirror payment data expand PCI scope unexpectedly.825. **ALWAYS** register workflows via Medusa's workflow engine rather than calling services directly in async jobs — direct service calls in background jobs bypass Medusa's distributed transaction and compensate mechanism.8384## Anti-Patterns8586| Anti-Pattern | Why It Fails | Correct Approach |87| --------------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |88| Modifying Medusa core source | Breaks on every `npm update`; cannot receive security patches; unsupportable | Extend via module overrides or custom modules using `@medusajs/modules-sdk` |89| Direct database queries bypassing services | Skips inventory reservations, pricing calculations, event hooks, and audit trail | Call Medusa services (e.g., `productService.create()`) for all data mutations |90| Untyped custom API route handlers | Missing container injection; no access to registered services; no transaction scope | Import and use `MedusaRequest`, `MedusaResponse` from `@medusajs/medusa` |91| Duplicating payment data in custom tables | Expands PCI DSS scope to custom tables; compliance burden explodes | Use Medusa's built-in payment providers; store only non-sensitive references |92| Direct service calls in async background jobs | No distributed transaction; partial failures leave data in inconsistent state | Use `createWorkflow()` with `compensateSteps` for any multi-step async operation |9394## Memory Protocol (MANDATORY)9596**Before starting:**9798```bash99cat .claude/context/memory/learnings.md100```101102**After completing:** Record any new patterns or exceptions discovered.103104> ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.