# Running the storefront The storefront serves on and always talks to a backend on . Two backends can fill that slot — the real Medusa app or the bundled mock. **Only one at a time**: they both bind port 9000. --- ## Option A — real Medusa backend (recommended) ```bash cd backend && yarn dev ``` ```bash cd frontend && yarn dev ``` `frontend/.env.local` must match that backend on two values, or the storefront will not load: | Variable | Why it must match | |---|---| | `NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY` | Every Store API call is rejected with `not_allowed` without a key the backend knows. `pk_test` is a placeholder that only works with the mock. | | `NEXT_PUBLIC_DEFAULT_REGION` | Must be a country code the backend has a region for. The middleware redirects `/` to `/`; if the value has no region it falls back to whichever country comes first, which is rarely what you want. | ### Finding the publishable key From the Medusa admin: **Settings → Publishable API keys**. Or straight from the database: ```bash cd backend && node -e "require('dotenv').config();const{Client}=require('pg');const c=new Client({connectionString:process.env.DATABASE_URL});c.connect().then(async()=>{const r=await c.query(\"select token from api_key where type='publishable' and revoked_at is null\");console.log(r.rows.map(x=>x.token).join('\n'));await c.end()})" ``` ### Finding the valid region country codes ```bash cd backend && node -e "require('dotenv').config();const{Client}=require('pg');const c=new Client({connectionString:process.env.DATABASE_URL});c.connect().then(async()=>{const r=await c.query('select iso_2 from region_country where region_id is not null');console.log(r.rows.map(x=>x.iso_2).join(', '));await c.end()})" ``` The backend currently configured here has a single **Europe** region (EUR) covering `dk, fr, de, it, es, se, gb` — there is no `us`, so `.env.local` is set to `dk`. Also check `STORE_CORS` in `backend/.env` includes `http://localhost:8000`. ### After editing `.env.local` Restart `yarn dev`. Next.js reads env files at boot. --- ## Option B — mock backend (no database) `frontend/mock-backend/` is a small Node server implementing enough of the Store API — regions, categories, collections, products, search and an in-memory cart — for browsing and add-to-bag to work with no database. ```bash cd frontend && yarn mock-backend ``` ```bash cd frontend && yarn dev ``` With the mock, `.env.local` wants `NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_test` (the mock does not validate it) and `NEXT_PUBLIC_DEFAULT_REGION=us`. Not emulated: checkout completion, payments, customer accounts, orders. Those endpoints answer "nothing configured" so the storefront degrades gracefully rather than erroring. --- ## Checks ```bash cd frontend && yarn check ``` Runs `typecheck`, `lint` and `test`. `next build` also runs the type-check and lint — they are no longer disabled in `next.config.js`, so a type error fails the build. Do not run `yarn build` while `yarn dev` is running: they share `.next` and the build pulls the directory out from under the dev server. --- ## Branding Everything user-visible that names the store lives in [`src/lib/brand.ts`](src/lib/brand.ts) — wordmark, storage-key slug, tagline, title helper and social links. Change `BRAND_NAME` and `BRAND_SLUG` there and the whole storefront follows. Footer copy for the informational pages lives in [`src/lib/content/info-pages.ts`](src/lib/content/info-pages.ts); it is generic boilerplate and should be replaced (or swapped for a CMS query) before launch.