Command Palette

Search for a command to run...

Getting Started with Medusa DTC Starter

In this guide, you'll learn how to install Medusa DTC Starter by Gorgo, configure both apps, and connect your first integration.

Requirements

  • Node.js v20 or later
  • PostgreSQL v15 or later
  • npm, yarn, or pnpm

Installation

Install the starter one of two ways: scaffold a new project with Medusa's own CLI, or clone the repository and configure each app by hand.

Approach 1: Install with Medusa Application

yarn dlx create-medusa-app@latest --repo-url https://github.com/gorgojs/medusa-dtc-starter

tells to scaffold from the specified repository instead of the official Medusa starter, but the usual prompts for a project name and a database stay the same. By default, the command also runs migrations, creates an admin user, and seeds the database. Pass to skip all three.

Approach 2: Install Separately

  1. Clone the repository and install dependencies:

    1git clone https://github.com/gorgojs/medusa-dtc-starter.git
    2cd medusa-dtc-starter
    3yarn install
  2. Create the backend's environment file and point at a real database:

    Terminal
    cp apps/backend/.env.template apps/backend/.env
    apps/backend/.env
    DATABASE_URL=postgres://postgres:@localhost:5432/medusa-dtc-starter
  3. Run the migrations, create an admin user, seed the initial data, and start the backend:

    1cd apps/backend
    2yarn medusa db:migrate
    3yarn medusa user -e admin@medusajs.com -p supersecret
    4yarn seed
    5yarn dev
  4. Open the Admin dashboard at , log in, and copy the publishable API key from Settings → Publishable API Keys.

  5. Create the storefront's environment file with that key:

    Terminal
    cp apps/storefront/.env.template apps/storefront/.env.local
    apps/storefront/.env.local
    NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_6c3...
  6. Start the storefront:

    1cd apps/storefront
    2yarn dev

The storefront runs at . The repository root is set up for pnpm, so there starts both apps at once. With npm or yarn, start each app from its own directory.


Configuration

Backend

Before the backend can run, set a real value for and :

apps/backend/.env
1DATABASE_URL=postgres://postgres:@localhost:5432/medusa-dtc-starter
2INTEGRATION_ENCRYPTION_KEY=supersecret

Everything else in ships with a working localhost default, apart from the SMTP block, which points at a placeholder host until you fill it in. What the rest of them do:

VariableWhat it does
Connection string for PostgreSQL. holds the database name it interpolates
Encrypts the secret fields the Integration Module stores
, Signing secrets for tokens and cookies
Set it to on a live domain to send cookies over HTTPS only
, , Origins allowed to call the Store API, Admin, and authentication. Add your own domain here when you move either app off localhost
Redis instance for the cache, event bus, and workflow engine. Production uses it whenever it is set. points the cache alone at a separate instance
Set it to to use in development too. Without it all three run in memory, which is enough for development
, , , , Mail server the transactional emails go through. Nothing is sent until you fill these in
, Sender and reply-to addresses on those emails
, , , Store details printed in the email templates
Language an email falls back to when the buyer's own is unknown
Storefront address, used for the links inside emails and for revalidation webhooks
Shared secret the backend sends with every revalidation webhook. It has to match the storefront's value
, , , , Move file uploads to S3-compatible storage. Read in production only
Storefront directory that Medusa's onboarding flow points at

Replace every value before going to production.

Storefront

For the storefront, you need at least the publishable API key from your Medusa backend:

apps/storefront/.env.local
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_6c3...

The rest already ship with working localhost defaults:

VariableWhat it does
Publishable API key from Medusa Admin. Required
Address the storefront calls the backend at
The storefront's own address, used for absolute URLs in metadata, the sitemap, and
Store name shown in the header, footer, and checkout, and used in the markup and the endpoint
Country code the storefront falls back to when it cannot tell where a visitor is. The template's matches no seeded region, and then the first region the backend returns wins
, How a first-time visitor's country is detected. On Vercel or Cloudflare you can leave the provider unset, see the Set Up Country Detection documentation
Set it to and every response explains which country the middleware picked and why
, Address suggestions during checkout, see the Set Up Address Autocomplete documentation
Stripe publishable key, needed only if you take payments through Stripe
, Key and connected account for Medusa Cloud Payments. The key is used when is empty
Google Analytics 4 measurement ID. Leave it empty and the storefront loads no analytics script at all
Has to match the same variable in , because the backend sends that value with every revalidation webhook. Change it before production
, Allow images from the Medusa Cloud bucket. Needed only when you deploy there
Node environment

Add Integrations

The Integration Module () is already registered in with an empty array, so there's nothing to wire up before you can add one. Once the backend is running, add a payment, fulfillment, or ERP integration and configure it from Medusa Admin, see the Browse and Add an Integration documentation.


Troubleshooting

Storefront Can't Reach the Backend, or Shows a Region Error

The storefront's logs show:

Storefront logs
Error fetching regions. Did you set up regions in your Medusa Admin and define a NEXT_PUBLIC_MEDUSA_BACKEND_URL environment variable.

The cause is one of two things: either isn't set or points to the wrong place, or the backend has no region configured yet. Check that the backend is running and reachable at that URL. If there really are no regions, the seed script creates several, see the Customize Seed Data documentation.

Stripe Checkout Doesn't Load

The storefront's logs show one of two errors:

Storefront logs
Stripe key is missing. Set NEXT_PUBLIC_STRIPE_KEY environment variable.

The first one means the storefront tried to render Stripe Elements without a Stripe publishable key set.

Storefront logs
Stripe client secret is missing. Cannot initialize Stripe.

The second one means no Stripe payment session exists on the cart yet, usually because the selected region has no Stripe provider configured.

The Storefront Opens in the Wrong Country

A first-time visitor lands in a region that has nothing to do with their location, usually the same one every time.

Set in , reload, and read the headers on the document request in the browser's network panel. names what answered: means the cookie was never cleared, so clear it or open a new private window; means nothing resolved and matched no seeded region either, so set it to a real country code; means never reached the server. See the Set Up Country Detection documentation for what each header means.


Address Autocomplete Doesn't Work

If the address field doesn't suggest anything as you type during checkout, the DaData key is probably missing. Create an account on DaData, set your key in , and leave set to . See the Set Up Address Autocomplete documentation for configuring autocomplete and connecting a different provider.

CORS Errors in the Browser Console

, , and in the backend's are allow-lists. If you move the storefront or Admin to a different port or domain, add that origin to the matching variable and restart the backend.

Edited Aug 28, 2026·Edit this page