@bigcommerce/catalyst-core@1.7.0
Minor Changes
-
#2989
518d20aThanks @jorgemoya! - Restore locale-awarelangattribute on the root<html>tag. The previous root layout hardcodedlang="en"for all locales; ownership of<html>/<body>now lives inapp/[locale]/layout.tsxsolang={locale}reflects the active locale. The rootapp/layout.tsxis now a passthrough, andapp/not-found.tsxis self-sufficient (renders its own<html>/<body>) to preserve the branded 404 for non-localized requests. -
#2825
7b38d98Thanks @chanceaclark! - Add GraphQL proxy to enable client-side GraphQL requests through the storefront. This proxy forwards requests from allowed clients (such as checkout-sdk-js) to the BigCommerce Storefront API using a dedicated unauthenticated storefront token for API authorization, while still passing through the customer access token for customer-specific data. No browser cookies are forwarded.Migration
Step 1: Add environment variable
Add a
BIGCOMMERCE_STOREFRONT_UNAUTHENTICATED_TOKENto your.env.local. This should be a storefront API token scoped for client-side proxy use with minimal permissions.Step 2: Create proxy
Create a new file
core/proxies/with-graphql-proxy.ts:import { NextResponse, URLPattern } from 'next/server'; import { z } from 'zod'; import { auth } from '~/auth'; import { client } from '~/client'; import { type ProxyFactory } from './compose-proxies'; const ALLOWED_REQUESTERS = ['checkout-sdk-js']; const graphqlPathPattern = new URLPattern({ pathname: '/graphql' }); const bodySchema = z.object({ query: z.unknown(), variables: z.record(z.unknown()).default({}), }); export const withGraphqlProxy: ProxyFactory = (next) => { return async (request, event) => { // Only handle /graphql path if (!graphqlPathPattern.test(request.nextUrl.toString())) { return next(request, event); } const requester = request.headers.get('x-catalyst-graphql-proxy-requester'); // Validate required header if (!requester || !ALLOWED_REQUESTERS.includes(requester)) { return next(request, event); } // Only handle POST requests if (request.method !== 'POST') { return new NextResponse('Method not allowed', { status: 405 }); } // Wrap in auth to get customer access token for customer-specific data return auth(async (req) => { try { // Parse incoming GraphQL request body const body: unknown = await req.json(); const { query, variables } = bodySchema.parse(body); if (!query) { return NextResponse.json({ error: 'Missing query' }, { status: 400 }); } // Get customer access token if authenticated const customerAccessToken = req.auth?.user?.customerAccessToken; // Proxy the request using the existing client with an unauthenticated storefront token const response = await client.fetch({ document: query, variables, customerAccessToken, fetchOptions: { headers: { Authorization: `Bearer ${process.env.BIGCOMMERCE_STOREFRONT_UNAUTHENTICATED_TOKEN}`, }, next: { revalidate: 0 }, }, }); return NextResponse.json(response); } catch (error) { // eslint-disable-next-line no-console console.error(error); return NextResponse.json(error, { status: 500 }); } // @ts-expect-error auth() overload expects middleware return type, but we return NextResponse directly for the proxy })(request, event); }; };
Step 3: Register proxy
Update
core/proxy.tsto include the new proxy in the composition chain:import { composeProxies } from './proxies/compose-proxies'; import { withAnalyticsCookies } from './proxies/with-analytics-cookies'; import { withAuth } from './proxies/with-auth'; import { withChannelId } from './proxies/with-channel-id'; + import { withGraphqlProxy } from './proxies/with-graphql-proxy'; import { withIntl } from './proxies/with-intl'; import { withRoutes } from './proxies/with-routes'; export const proxy = composeProxies( withAuth, withAnalyticsCookies, withIntl, withChannelId, + withGraphqlProxy, withRoutes, );The
withGraphqlProxyproxy should be placed afterwithChannelIdand beforewithRoutesin the chain.
Patch Changes
-
#3002
24cc310Thanks @bc-alexsaiannyi! - Fix cart summary Discounts row not showing manual discounts applied via the Management Checkout API -
#2976
a85fa42Thanks @jorgemoya! - Add X-Correlation-ID header to all GraphQL requests. Each page render gets a stable UUID that persists across all fetches within the same render, enabling easier request tracing in server logs. -
#3021
4e44415Thanks @mfaris9! - Default brand PLP sort tofeaturedto honor the merchant's product sort order. -
#2964
d00beebThanks @chanceaclark! - Prevent breadcrumb array mutation on cached web pages by spreading the Reactcache()result before reversing, and fix an off-by-one intruncateBreadcrumbsthat incorrectly truncated arrays exactly at the target length. Also deferProductReviewSchemato client-only rendering to avoid a DOMPurify SSR crash. -
#3005
37e0a7cThanks @mfaris9! - FixformField.requiredmismatch forcheckbox-groupfields inDynamicForm. The schema branch was missing.optional()for non-required checkbox groups. -
#3013
9aacfdcThanks @chanceaclark! - Pass the customer access token through route resolution and the normal/contact webpage queries so customer-restricted web pages are accessible (and appear in navigation) for authenticated customers. Thewith-routesproxy is now wrapped inauth(), and webpagepage-dataqueries switch to an uncached fetch when a customer token is present. -
#2963
a8dd99eThanks @chanceaclark! - Fix DynamicForm not rendering hidden field types, which causedpageEntityIdto beNaNon contact form submission. -
#3014
a792a86Thanks @parthshahp! - TRAC-276 translate the gift certificate line item title in cart, order list, and order details. Previously the title was rendered as the raw English"{amount} Gift Certificate"string stored on the BigCommerce backend; it is now rendered from the existingCart.GiftCertificate.giftCertificatetranslation key, with the amount shown in the separate price column (the order list view now populatesprice/totalPricefor gift certificates, which were previously empty). -
#3008
77c8e8dThanks @bc-svc-local! - Update translations. -
#2959
4870221Thanks @bc-svc-local! - Update translations. -
#2987
e18feb6Thanks @bc-svc-local! - Update translations. -
#3022
c5fc1afThanks @bc-svc-local! - Update translations. -
Updated dependencies [
f4216a6]:- @bigcommerce/catalyst-client@1.0.2