Skip to main content

Installation

This guide covers all methods for installing and setting up a Medusa project, from the automated CLI to manual installation. The fastest way to get started is with create-medusa-app, which handles project scaffolding, database setup, and initial configuration.

Prerequisites

  • Node.js 20 or higher
  • PostgreSQL 13 or higher
  • npm, yarn, or pnpm

Installation

npx create-medusa-app@latest
See the Quickstart guide for detailed walkthrough of create-medusa-app.

With Options

Customize your installation with command-line options:
npx create-medusa-app@latest my-medusa-store \
  --seed \
  --db-url postgres://localhost:5432/medusa \
  --use-pnpm
Available options:
OptionDescription
--seedSeed database with demo products
--skip-dbSkip database creation
--db-url <url>PostgreSQL connection string
--no-migrationsSkip database migrations
--no-browserDon’t open admin in browser
--use-npmUse npm as package manager
--use-yarnUse yarn as package manager
--use-pnpmUse pnpm as package manager
--directory-path <path>Installation directory
--verboseShow detailed logs

Method 2: Manual Installation

For more control over the setup process, you can install Medusa packages manually.

Step 1: Create Project Directory

mkdir my-medusa-store
cd my-medusa-store

Step 2: Initialize Package Manager

npm init -y

Step 3: Install Core Packages

Install the Medusa framework and required dependencies:
npm install @medusajs/framework @medusajs/medusa

Step 4: Install Commerce Modules

Add the commerce modules you need:
npm install \
  @medusajs/product \
  @medusajs/cart \
  @medusajs/order \
  @medusajs/payment \
  @medusajs/fulfillment \
  @medusajs/customer \
  @medusajs/inventory
You can install only the modules you need. See the Commerce Modules documentation for the complete list.

Step 5: Install Development Dependencies

npm install -D typescript @types/node tsx

Step 6: Create Configuration Files

Create medusa-config.ts in your project root:
medusa-config.ts
import { defineConfig, Modules } from "@medusajs/framework/utils"

export default defineConfig({
  projectConfig: {
    databaseUrl: process.env.DATABASE_URL,
    http: {
      storeCors: process.env.STORE_CORS || "http://localhost:8000",
      adminCors: process.env.ADMIN_CORS || "http://localhost:9000",
      jwtSecret: process.env.JWT_SECRET || "supersecret",
      cookieSecret: process.env.COOKIE_SECRET || "supersecret",
    },
  },
  admin: {
    path: "/app",
  },
  modules: {
    [Modules.PRODUCT]: {
      resolve: "@medusajs/product",
    },
    [Modules.CART]: {
      resolve: "@medusajs/cart",
    },
    [Modules.ORDER]: {
      resolve: "@medusajs/order",
    },
    [Modules.CUSTOMER]: {
      resolve: "@medusajs/customer",
    },
    [Modules.PAYMENT]: {
      resolve: "@medusajs/payment",
    },
    [Modules.FULFILLMENT]: {
      resolve: "@medusajs/fulfillment",
    },
    [Modules.INVENTORY]: {
      resolve: "@medusajs/inventory",
    },
  },
})
Create .env file:
.env
DATABASE_URL=postgres://postgres:postgres@localhost:5432/medusa-store
JWT_SECRET=your-secret-key-change-in-production
COOKIE_SECRET=your-cookie-secret-change-in-production
STORE_CORS=http://localhost:8000
ADMIN_CORS=http://localhost:9000
Create tsconfig.json:
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2021",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

Step 7: Add Scripts to package.json

Update your package.json with these scripts:
package.json
{
  "name": "my-medusa-store",
  "version": "1.0.0",
  "scripts": {
    "dev": "medusa develop",
    "build": "medusa build",
    "start": "medusa start",
    "migrations:run": "medusa migrations run",
    "migrations:revert": "medusa migrations revert",
    "seed": "medusa seed"
  },
  "dependencies": {
    "@medusajs/framework": "^2.13.3",
    "@medusajs/medusa": "^2.13.3"
  },
  "devDependencies": {
    "@types/node": "^20.12.11",
    "typescript": "^5.6.2",
    "tsx": "^4.0.0"
  },
  "engines": {
    "node": ">=20"
  }
}

Step 8: Create Source Directory

Create the basic directory structure:
mkdir -p src/api/admin
mkdir -p src/api/store
mkdir -p src/workflows
mkdir -p src/subscribers
mkdir -p src/modules

Step 9: Initialize Database

Run database migrations:
npm run migrations:run

Step 10: Start Development Server

npm run dev
Your Medusa application is now running at http://localhost:9000!

Database Setup

PostgreSQL Installation

Using Homebrew:
brew install postgresql@13
brew services start postgresql@13
Create database:
createdb medusa-store

Database Connection String Format

postgres://[user]:[password]@[host]:[port]/[database]
Example:
postgres://postgres:mypassword@localhost:5432/medusa-store
With SSL (for hosted databases):
postgres://user:password@host:5432/database?sslmode=require

Installing Providers

Providers extend Medusa modules with specific implementations.

Payment Providers

npm install @medusajs/payment-stripe
Configure in medusa-config.ts:
medusa-config.ts
import { Modules } from "@medusajs/framework/utils"

export default defineConfig({
  modules: {
    [Modules.PAYMENT]: {
      resolve: "@medusajs/payment",
      options: {
        providers: [
          {
            resolve: "@medusajs/payment-stripe",
            id: "stripe",
            options: {
              apiKey: process.env.STRIPE_API_KEY,
            },
          },
        ],
      },
    },
  },
})

File Storage Providers

npm install @medusajs/file-local
Configure in medusa-config.ts:
medusa-config.ts
[Modules.FILE]: {
  resolve: "@medusajs/file",
  options: {
    providers: [
      {
        resolve: "@medusajs/file-s3",
        id: "s3",
        options: {
          file_url: process.env.S3_FILE_URL,
          access_key_id: process.env.S3_ACCESS_KEY_ID,
          secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
          region: process.env.S3_REGION,
          bucket: process.env.S3_BUCKET,
        },
      },
    ],
  },
},

Notification Providers

npm install medusa-notification-sendgrid

Admin Dashboard Setup

The admin dashboard is included by default. To customize:

Install Admin SDK

npm install @medusajs/admin-sdk

Build Admin for Production

npm run admin:build

Configure Admin Path

In medusa-config.ts:
export default defineConfig({
  admin: {
    path: "/app",              // Admin URL path
    outDir: "build/admin",     // Build output directory
    backendUrl: process.env.MEDUSA_BACKEND_URL,
  },
})

Environment Variables

Required Variables

.env
# Database
DATABASE_URL=postgres://localhost:5432/medusa-store

# Security
JWT_SECRET=your-jwt-secret-key
COOKIE_SECRET=your-cookie-secret-key

# CORS
STORE_CORS=http://localhost:8000
ADMIN_CORS=http://localhost:9000

Optional Variables

.env
# Redis (for caching and sessions)
REDIS_URL=redis://localhost:6379

# Email
SENDGRID_API_KEY=your-sendgrid-key
SENDGRID_FROM=[email protected]

# Storage
S3_URL=https://s3.amazonaws.com
S3_BUCKET=medusa-uploads
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key

# Stripe
STRIPE_API_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Server
PORT=9000
NODE_ENV=development
LOG_LEVEL=info

Verification

After installation, verify everything works:

1. Check Server Health

curl http://localhost:9000/health
Expected response:
{
  "status": "ok",
  "timestamp": "2026-03-03T15:00:00.000Z"
}

2. Test API

curl http://localhost:9000/store/products

3. Access Admin

Open http://localhost:9000/app in your browser.

4. Check Database Connection

psql $DATABASE_URL -c "SELECT version();"

Troubleshooting

“Cannot find module @medusajs/framework”Ensure all packages are installed:
rm -rf node_modules package-lock.json
npm install
“Database connection failed”Verify PostgreSQL is running and credentials are correct:
psql $DATABASE_URL
“Port 9000 is already in use”Change the port in your .env:
PORT=9001
Or kill the process using the port:
lsof -ti:9000 | xargs kill -9

Next Steps

Quickstart

Follow the quickstart guide for your first steps

Architecture

Understand Medusa’s architecture and design

API Routes

Learn to create custom API endpoints

Commerce Modules

Explore all available commerce modules

Build docs developers (and LLMs) love