Medusa 2.0 for Railway Boilerplate

repository·master·Indexed 42 days ago

https://github.com/rpuls/medusajs-2.0-for-railway-boilerplate

A production-ready monorepo for deploying Medusa 2.0 on Railway. Includes a Medusa backend, Next.js storefront, and infrastructure services including Postgres, Redis, MeiliSearch, and S3-compatible storage. Features custom email notifications using react-email and Resend/SendGrid, a preconfigured product search index for Medusa 2.19, and a one-click deployment template.

Tokens
24.9K
Snippets
84
Records
116
Agent score
51%

What's inside Medusa 2.0 Railway Boilerplate

  1. Template-specific backend features

    master

    This boilerplate includes several custom additions to the standard Medusa 2.0 installation:

    • src/modules/email-notifications/: A Resend provider using react-email templates for order confirmations and admin invites.
    • src/subscribers/: Custom subscribers for order-placed and invite-created events to trigger emails.
    • src/search/products.ts: Defines the product search index for the Medusa 2.19 Search Module.
    • src/api/key-exchange/: An API endpoint that provides the storefront with its publishable API key at boot time.
    • src/scripts/seed.ts: A demo store setup including one Europe region (covering gb, de, dk, se, fr, es, it), a sales channel, a publishable key, and four products.
    • src/lib/constants.ts: A central file documenting every environment variable read by the backend and its fallbacks.
  2. Understand Storefront routing and middleware

    master

    The storefront uses a dynamic routing structure where every route lives under app/[countryCode]/. This allows different regions, currencies, and prices to be served based on the URL path (e.g., /gb/store vs /de/store).

    Route Groups

    Inside the country code segment, routes are organized into two groups that do not appear in the URL:

    • (checkout): Contains a stripped-down layout for the checkout process.
    • (main): Contains the standard store layouts.

    Country Code Resolution

    The middleware.ts determines the [countryCode] using this priority:

    1. A country code already present in the URL that matches a configured Medusa region.
    2. The x-vercel-ip-country header (only available on Vercel).
    3. The NEXT_PUBLIC_DEFAULT_REGION environment variable.
    4. The first country of the first available region (logs a warning if this occurs).
  3. Understanding reset-password link destinations

    master

    The reset-password template dynamically determines the destination URL based on the actor_type of the user requesting the reset:

    • Administrators (actor_type: "user"): Links to BACKEND_URL/app/reset-password?token=.... This is served by the backend.
    • Shoppers (any other type): Links to STOREFRONT_URL/reset-password?token=...&email=....

    Note on STOREFRONT_URL: This value is derived from the server configuration and falls back to the first plain origin in STORE_CORS. The destination is determined strictly by server configuration to prevent security vulnerabilities where a caller might attempt to redirect a customer to a malicious site via the metadata bag.

  4. Use the Data Layer and Cache Tags correctly

    master

    The storefront uses a specific pattern for data fetching in lib/data/ to ensure Next.js caching works correctly.

    Avoid sdk.store.* for cached reads

    Do not use sdk.store.* helpers for reads that require Next.js cache tags. The SDK helpers treat the last parameter as HTTP headers rather than Next.js fetch options. Passing { next: { tags: [...] } } to these helpers will result in the object being serialized into a literal HTTP header named next, which fails to trigger Next.js caching.

    Correct Pattern

    Use sdk.client.fetch directly for data fetching. This allows you to pass the correct Next.js fetch options. If you need to implement a cached read, copy an existing pattern from lib/data/.

    Visitor-Scoped Caching

    To prevent one user's actions (like updating a cart) from purging the cache for all users, cache tags are suffixed with a visitor-specific _medusa_cache_id. This ID is managed via cookies in lib/data/cookies.ts.

  5. Understand the Medusa 2.0 Railway architecture

    master

    The deployment consists of seven interconnected services running within a single Railway project:

    1. Next.js Storefront: The customer-facing web application.
    2. Medusa Backend: The core commerce engine.
    3. Postgres: The primary relational database.
    4. Redis: Used for caching and background tasks.
    5. MeiliSearch: Powers product search functionality.
    6. S3-compatible Storage: Stores product images and files.
    7. Bucket-proxy: A specialized Railway Function that acts as a read-only proxy for the S3 bucket. Since Railway buckets do not serve content publicly by default, this proxy handles public GET and HEAD requests so product images can be loaded in browsers via the S3_FILE_URL.
  6. Required and optional backend services

    master

    The backend expects several services to function correctly. While Railway provisions these automatically in the full stack, you may need to configure them locally via .env.

    • Postgres (Required): The primary database.
    • Redis (Optional): Used for the event bus and workflow engine. If REDIS_URL is not provided, it falls back to an in-memory bus which is single-process and loses events on restart.
    • S3-compatible storage (Optional): Used for product images. Supports Railway buckets, AWS S3, Cloudflare R2, and MinIO. If unconfigured, it falls back to local disk (which is ephemeral on Railway).
    • MeiliSearch (Optional): Used for search. Requirement: Must be version 1.20 or later to support the rename field on POST /swap-indexes. Older versions will result in silent indexing failures.
  7. Set up and run the Storefront locally

    master

    The storefront is a Next.js App Router project. Note: A running backend on port 9000 is required for the storefront to work, as it fetches its publishable API key from the backend at boot time.

    1. Navigate to the storefront directory.
    2. Create your .env.local file from the template.
    3. Install dependencies using pnpm.
    4. Start the development server.

    Endpoint:

    cd storefront
    cp .env.local.template .env.local
    pnpm install
    pnpm dev
  8. Run the Storefront locally

    master

    To run the storefront, you must have the Medusa backend running on port 9000 first. The storefront relies on the backend to provide its publishable API key via the /key-exchange endpoint.

    Important: This project uses pnpm exclusively. The build scripts call pnpm directly, so using npm or yarn will cause deployment failures.

    Local Development

    1. Ensure the backend is running.
    2. Set up environment variables.
    3. Install dependencies and start the development server.

    To test caching and prerendering behavior (simulating a Railway deployment), use the build and start commands instead of the dev command.

    cd storefront
    cp .env.local.template .env.local
    pnpm install
    pnpm dev                    # http://localhost:8000
    
    # To test caching/prerendering (Railway-like):
    pnpm build && pnpm start     # http://localhost:8000
  9. Local development setup for the Medusa backend

    master

    To run the backend locally, follow these steps. Note that this project requires pnpm exclusively; using npm or yarn will cause deployment failures because the postBuild.js script calls pnpm i --frozen-lockfile directly.

    Prerequisites:

    • Node.js 22.12 or later (as specified in .nvmrc).
    • pnpm installed.

    Setup Steps:

    1. Navigate to the backend directory.
    2. Create your environment file from the template:
      cp .env.template .env
      Note: Review the .env file carefully, as the order and presence of variables matter.
    3. Install dependencies:
      pnpm install
    4. Initialize the database (run migrations and seed demo data):
      pnpm ib
    5. Start the development server:
      pnpm dev

    Accessing the services:

    • API: http://localhost:9000
    • Admin Dashboard: http://localhost:9000/app
    • Email Template Preview: http://localhost:3002 (via pnpm email:dev)
    cd backend
    cp .env.template .env
    pnpm install
    pnpm ib
    pnpm dev
  10. Set up the E2E testing environment

    master

    To prepare the end-to-end testing suite, you must configure your environment variables and install the necessary browser binaries. The tests rely on a .env file for configuration.

    1. Initialize environment variables: Copy the provided example to a .env file:
      cat e2e/.env.example >> .env
    2. Install Playwright: Ensure Playwright and its browsers are installed:
      npx playwright install
    3. Configure CLIENT_SERVER: Ensure the CLIENT_SERVER variable in your .env points to the server the Next.js instance is listening on.
    cat e2e/.env.example >> .env
    npx playwright install
  11. Configure Resend email notifications

    master

    Email services (order confirmations, admin invites, password resets) are powered by Resend.

    • To enable, provide your Resend API keys in the environment variables.
    • The templates use react-email for email layouts.
    • You can edit and preview these templates locally using the command: pnpm email:dev.
  12. Set up and run the Medusa Backend locally

    master

    Follow these steps to initialize the backend. Note that pnpm ib (migrate and seed) should only be run against a database you are willing to overwrite.

    1. Navigate to the backend directory.
    2. Create your .env file from the template.
    3. Install dependencies using pnpm.
    4. Run the migration and seeding command.
    5. Start the development server.

    Endpoints:

    To connect to your deployed Railway database locally, copy the DATABASE_URL from Railway into your local .env.

    cd backend
    cp .env.template .env
    pnpm install
    pnpm ib
    pnpm dev