dist/codex/medusa-commerce/skills/medusa-storefront/SKILL.md
Build Medusa v2 storefronts with Next.js 15 — App Router, JS SDK client setup, Tanstack Query, server components, product pages, cart, and checkout flow. Use when developing headless storefronts.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins medusa-storefrontInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch live docs:
https://docs.medusajs.com/resources/storefront-development for storefront overviewsite:docs.medusajs.com nextjs starter storefront for starter templatesite:docs.medusajs.com JS SDK client setup for Medusa SDK configurationsite:docs.medusajs.com storefront API reference for Store API endpointssite:github.com medusajs nextjs-starter-medusa for latest starter sourceMedusa v2 storefronts are headless -- they consume the Store API over HTTP:
| Layer | Component |
|-------|-----------|
| Frontend | Next.js App (SSR/RSC) |
| HTTP Client | Medusa JS SDK |
| Backend | Medusa Backend (/store/* API routes) |
| Storage | PostgreSQL / Redis |
| Directory | Key Files |
|-----------|-----------|
| app/ | layout.tsx, page.tsx (homepage) |
| app/(main)/products/ | page.tsx (listing), [handle]/page.tsx (detail) |
| app/(main)/collections/ | [handle]/page.tsx (collection) |
| app/(main)/cart/, app/(main)/checkout/ | Cart page, checkout flow |
| app/(auth)/, app/account/ | Login/register, customer dashboard |
| lib/ | sdk.ts (Medusa client), data/ (fetching), util/ |
| components/ | products/, cart/, checkout/, layout/ |
| Root | next.config.js, .env.local |
The Medusa JS SDK provides typed access to the Store API:
// lib/sdk.ts — Fetch live docs for Medusa SDK initialization
import Medusa from "@medusajs/js-sdk"
export const sdk = new Medusa({
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL!,
// Fetch live docs for publishableKey and other options
})
NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://localhost:9000
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_...
The publishable API key is required for Store API requests and scopes them to a specific sales channel.
| Domain | SDK Namespace | Key Operations |
|--------|--------------|----------------|
| Products | sdk.store.product | List, retrieve by handle |
| Collections | sdk.store.collection | List, retrieve |
| Categories | sdk.store.category | List, tree |
| Cart | sdk.store.cart | Create, add items, update |
| Checkout | sdk.store.cart | Add shipping, complete |
| Customer | sdk.store.customer | Register, login, profile |
| Orders | sdk.store.order | List customer orders |
| Regions | sdk.store.region | List regions and currencies |
| Shipping | sdk.store.fulfillment | List shipping options |
Fetch live docs for the complete SDK namespace list and method signatures.
| Pattern | Use For | |---------|---------| | Server Component (RSC) | Product listing, product detail, static content | | Client Component | Cart interactions, checkout form, quantity selectors | | Server Action | Cart mutations, checkout submission |
// app/(main)/products/[handle]/page.tsx
// Fetch live docs for SDK method signatures
export default async function ProductPage({ params }) {
const { product } = await sdk.store.product.retrieve(params.handle)
return <ProductTemplate product={product} />
}
| Step | Action | SDK Method |
|------|--------|-----------|
| 1. Create cart | On first add-to-cart | sdk.store.cart.create() |
| 2. Add line item | User adds product | sdk.store.cart.addLineItem() |
| 3. Update quantity | User changes qty | sdk.store.cart.updateLineItem() |
| 4. Remove item | User removes product | sdk.store.cart.removeLineItem() |
| 5. Set region | Auto or user selection | sdk.store.cart.update() |
Cart ID is typically stored in a cookie or localStorage for persistence across sessions.
| Step | Required Data | SDK Call |
|------|--------------|---------|
| 1. Address | Shipping + billing address | sdk.store.cart.update() |
| 2. Shipping | Selected shipping option | sdk.store.cart.addShippingMethod() |
| 3. Payment | Payment provider session | sdk.store.cart.initiatePaymentSession() |
| 4. Complete | Confirmation | sdk.store.cart.complete() |
| Flow | Description | |------|-------------| | Registration | Create customer account via Store API | | Login | Authenticate and receive session token | | Session | Token stored in cookie, sent with requests | | Profile | Update customer info, addresses | | Orders | View past orders linked to customer |
// Fetch live docs for customer auth SDK methods
await sdk.auth.login("customer", "emailpass", {
email: "[email protected]",
password: "password",
})
| Technique | Implementation |
|-----------|---------------|
| Static Generation (SSG) | Use generateStaticParams for product pages |
| ISR | Revalidate product pages periodically |
| Streaming | Use Suspense boundaries for slow data |
| Image optimization | Use Next.js <Image> with Medusa image URLs |
| Prefetching | Use <Link> for product navigation |
generateStaticParams for product and collection pages for SEO and speedFetch the Medusa storefront documentation and Next.js starter source for exact SDK method signatures, component patterns, and checkout flow details before implementing.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.