Shopware — Composable Frontends (Headless)
See the shopware skill for the map of Shopware skills.
Shopware Composable Frontends (Headless)
Headless Vue 3 + Nuxt storefront that communicates exclusively via the Store API. Successor to the archived shopware-pwa (Vue Storefront). Fully replaces the classic Twig-based Storefront.
shopware-pwa is archived (Oct 2024). All new headless work uses Shopware Composable Frontends (
@shopware/*packages).
Architecture
| Package | npm | Purpose |
|---|---|---|
| API Client | @shopware/api-client | Typed Store API abstraction, auth/context-token management |
| Composables | @shopware/composables | Vue 3 composables: useProduct, useCart, useListing, useCustomer, etc. |
| CMS Base Layer | @shopware/cms-base-layer | Vue components for all default CMS sections/blocks/elements |
| Helpers | @shopware/helpers | Price formatting, translations, URL handling |
| Nuxt Module | @shopware/nuxt-module | Wires up API client + composables + context for Nuxt |
| API Gen CLI | @shopware/api-gen | Generates TypeScript types from your Shopware instance's API schema |
Tech stack: Vue 3 + Nuxt 4 + TypeScript + UnoCSS/Tailwind. SSR by default.
vs. Classic Storefront (Twig)
| Aspect | Classic Storefront | Composable Frontends |
|---|---|---|
| Rendering | PHP/Twig (server) | Vue/Nuxt (Node.js SSR) |
| Extension | Twig blocks, PHP events | Vue components, Nuxt layers |
| Deployment | Same process as Shopware | Separate Node.js application |
| CMS customization | PHP DataResolver + Twig template | Vue component (naming convention) |
| Plugin effects | Subscribers, decorators, Twig | No effect — Store API only |
| Styling | SCSS + Shopware theme system | Free choice (Tailwind, UnoCSS, etc.) |
CMS Component Resolution
The Store API returns a nested CMS tree. Each node's type is converted to a PascalCase Vue component:
CMS type "image-text" → component CmsBlockImageText CMS type "product-listing" → component CmsElementProductListing
Custom CMS blocks from backend plugins have no Vue implementation by default — you must create them manually.
Composable Frontends Gotchas
-
Sales Channel type must be "Storefront" — Do NOT use the "Headless" type. The Headless type does not generate SEO URLs. This is counterintuitive but required for proper URL resolution.
-
devStorefrontUrlfor local dev — Customer registration requires astorefrontUrlmatching a domain in Admin > Sales Channel > Domains. Set innuxt.config.ts:typescriptshopware: { devStorefrontUrl: 'https://your-production-domain.com', }Or via env:
NUXT_PUBLIC_SHOPWARE_DEV_STOREFRONT_URL. -
Store API access token is public — The token appears in client-side code. Only data visible on a normal storefront should be exposed. Use a Vite proxy for production to hide the backend URL:
typescriptvite: { server: { proxy: { '/store-api': { target: 'https://your-shopware-backend.com', changeOrigin: true, secure: false, }, }, }, } -
SSR + DDEV self-signed certs — SSR causes 500 errors because Node.js rejects self-signed SSL certificates. Workaround (dev only):
dotenvNODE_TLS_REJECT_UNAUTHORIZED=0 -
CORS with local frontend — Frontend at
localhost:3000is cross-origin to the Shopware backend. Fix with server-side proxy (see above) or setAccess-Control-Allow-Originon the backend. -
Custom CMS blocks not rendered — Only default Shopware CMS blocks have Vue implementations in
@shopware/cms-base-layer. Plugin-added blocks must be manually implemented as Vue components following theCmsBlock<PascalCaseType>/CmsElement<PascalCaseType>naming convention. -
Missing
createShopwareContext— Occurs when@shopware/nuxt-moduleis installed but the composables layer is not extended. Fix:typescript// nuxt.config.ts extends: ['@shopware/composables/nuxt-layer'], -
Type generation recommended — Default types may not match your instance's custom entities. Run
@shopware/api-genagainst your Shopware instance for accurate TypeScript types. -
Demo Store Template is deprecated — Use the Vue Starter Template with Nuxt layers pattern instead.
-
No automated migration from shopware-pwa — Package names changed (
@shopware-pwa/*→@shopware/*), composable API signatures differ, Vue 2→3 and Nuxt 2→4 migration required. Effectively a frontend rewrite. -
Routing via
useNavigationSearch— Uses Shopware'sSeoUrlsystem. A catch-all route resolves the path to one of three types:frontend.detail.page(product),frontend.navigation.page(category),frontend.landing.page(landing page). -
API Client hooks — Use
onContextChanged,onResponseError,onSuccessResponsefor global request/response handling. The client manages thesw-context-tokencookie automatically.


