PWA Studio Setup for Magento 2
PWA Studio — official Adobe/Magento toolkit for creating Progressive Web App over Magento 2 backend. Includes: Venia (ready storefront), Peregrine (React hooks), Buildpack (build), UPWARD (serverside routing).
Architecture
Browser (React SPA)
↕ GraphQL
Magento 2 Backend
↕ Commerce API
Venia Storefront (PWA Studio)
PWA Studio runs as separate Node.js application. Magento — API backend only, no rendering.
Installation
# Node.js 16+, Yarn
node -v # 16+
# Create project from Venia
yarn create @magento/pwa my-storefront
# Select: template = @magento/venia-concept
cd my-storefront
cp .env.example .env
.env:
MAGENTO_BACKEND_URL=https://your-m2-backend.com
BRAINTREE_TOKEN=sandbox_...
CHECKOUT_BRAINTREE_TOKEN=sandbox_...
IMAGE_OPTIMIZING_ORIGIN=backend
USE_COMPUTED_IMAGES=true
NEXT_PUBLIC_GTAG_ID=G-...
yarn start # dev server on :10000
yarn build # production build
Project structure
my-storefront/
├── src/
│ ├── components/ # Override Venia components
│ ├── queries/ # GraphQL queries
│ └── index.js
├── venia-ui.yml # Venia configuration
├── package.json
└── .env
Component override (Targets API)
PWA Studio uses targets extensibility — override components without fork:
// intercept.js
module.exports = targets => {
const builtins = targets.of('@magento/venia-ui');
// Override Header component
builtins.esModules.tap(esModules => {
esModules.add({
module: '@my-store/src/components/Header',
publish: targets => {
targets.of('@magento/venia-ui').esModules.tap(modules => {
const headerModule = modules.get('Header');
if (headerModule) {
headerModule.module = '@my-store/src/components/Header';
}
});
}
});
});
};
Custom product page
// src/components/ProductFullDetail/productFullDetail.js
import React, { useMemo } from 'react';
import { useProductFullDetail } from '@magento/peregrine/lib/talons/ProductFullDetail/useProductFullDetail';
import { gql, useQuery } from '@apollo/client';
const GET_PRODUCT = gql`
query GetProduct($urlKey: String!) {
products(filter: { url_key: { eq: $urlKey } }) {
items {
id sku name
price_range {
minimum_price { final_price { value currency } }
}
media_gallery { url label }
description { html }
... on ConfigurableProduct {
configurable_options {
label
values { label value_index swatch_data { value } }
}
}
}
}
}
`;
const ProductFullDetail = ({ urlKey }) => {
const { data } = useQuery(GET_PRODUCT, { variables: { urlKey } });
const product = data?.products?.items?.[0];
if (!product) return <div>Loading...</div>;
return (
<div className="product-detail">
<h1>{product.name}</h1>
<p className="price">{product.price_range.minimum_price.final_price.value} USD</p>
<div dangerouslySetInnerHTML={{ __html: product.description.html }} />
</div>
);
};
UPWARD configuration (routing)
# my-storefront.yml
status:
resolver: inline
inline: 200
headers:
resolver: inline
inline:
content-type:
resolver: inline
inline: 'text/html'
body:
resolver: file
file:
resolver: inline
inline: './dist/index.html'
Deploy
# Build
yarn build
# Production server (Node.js)
NODE_ENV=production \
MAGENTO_BACKEND_URL=https://m2-backend.com \
node server.js
# Docker
FROM node:16-alpine
COPY . .
RUN yarn && yarn build
EXPOSE 10000
CMD ["node", "server.js"]
PWA Studio alternatives
PWA Studio — official but slow development. Alternatives:
- Vue Storefront 2 — more active community, Nuxt.js-based
- ScandiPWA — faster, closer to standard Magento UX
- Hyva Themes — NOT PWA, but light React/Alpine.js frontend, popular
Timeline
Basic store on Venia with key components overridden — 4–6 weeks. Full custom storefront with design system — 3–5 months.







