Release January 20, 2026 - #2582
Open
github-actions[bot] wants to merge 271 commits into
Open
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
github-actions
Bot
force-pushed
the
changeset-release/from-canary
branch
from
January 23, 2026 15:25
0fc4cb5 to
6629180
Compare
Contains a Storyblok renderer on pages/index & pages/[…url] Includes multi language support and renderes for RowHeroBanner and RowLinks
…rror) halfway through Cursor: The issue was a TTY handling bug in graphql-codegen's CLI. When running in Cursor's terminal without a proper TTY: The spinner/progress output was suppressed The exit code was incorrectly set to 1 The fix was to pipe gc-gql-codegen through cat, which forces proper output handling
In live preview user should not be redirected based on system lang (i18n: { localeDetection: false }).
…ildren in a Fragment MUI's ButtonBase passes props.children as-is to the LinkComponent (NextLink). When ButtonBase has multiple children (Asset + Box), props.children is an array. React treats this array as an iterable inside LinkComponent and warns about missing keys. Wrapping in a Fragment (<>...</>) makes children a single element, avoiding the warning without adding an extra DOM node.
The Storyblok CLI generates types and component schemas under directories named after the space ID. This makes imports brittle when cloning the example as a starting point for new projects — every import path would need updating. - Add copy steps to storyblok:pull and storyblok:types scripts that copy artifacts to fixed paths without the space ID - Create components/Storyblok/types.ts barrel file so components import from a single location - Gitignore .storyblok/types/*/ and .storyblok/components/*/ (the space-ID directories are intermediate artifacts recreated by the CLI) - The space ID now only exists in storyblok.config.ts
… and per-page row component overrides When no override is provided, it just uses the default StoryblokComponent (components defined in /lib/storyblok.ts)
Pull components in space-id folder first, to prevent command from failing if (ignored) space-id folder is missing. Then copy the generic component schema to the space-id folder and push
…m the Storyblok visual editor) Sadly you can’t edit multiple stories in 1 visual editor session (edit footer from any page). To allow updating this content, a separate /pages/global-content.tsx path is created.
Slashes aren’t valid in Story slugs
A `<video>` paints nothing until it has buffered enough for its first
frame, and nothing at all when autoplay is blocked (iOS Low Power Mode).
An autoplaying video banner therefore starts out black, and can stay
black. `Asset` now takes a `poster`, rendered as `<video poster>`.
Storyblok's `type: asset` has no room for a poster, so `assetWithPoster()`
reads the convention of an asset value carrying an extra `poster` key:
{ "fieldtype": "asset", "filename": "…", "poster": { "filename": "…" } }
Keeping the poster beside the asset rather than nesting both under a
wrapper is what makes a custom field type storing that shape a drop-in
for a plain asset field: existing content stays valid and
`value.filename` keeps working for consumers that ignore the poster. The
narrowing is unavoidable regardless — Storyblok has no JSONSchema for
custom field types, so its type generator emits `unknown` for them.
`@graphcommerce/image` gains `imageUrl()`, which builds an optimized URL
outside of a React tree for the spots that need a bare URL rather than an
`<Image>` — `<video poster>`, `background-image`, `og:image`. It routes
through the configured loader, so the bytes are served and cached by the
deployment instead of every visitor hitting the origin host; that matters
when the origin meters bandwidth. Width snaps up to the nearest
configured size, since the optimizer 400s on anything outside
`imageSizes`/`deviceSizes`.
Improve Braintree checkout flow and make 3D Secure optional
…ndpoint feat(graphql-mesh): route Magento traffic over an internal network via GC_MAGENTO_ENDPOINT_SERVER
…Poster Each asset field in the example now goes through `assetWithPoster()` instead of reading `blok.asset` directly, and forwards the resulting `poster` to `<Asset>`. This makes the choice of field type a content decision rather than a code one: a plain `type: asset` and a custom field storing the poster convention both narrow through the same call, so a project can switch any field between the two — in either direction — without touching a component. Fields that never hold a video simply resolve `poster` to undefined.
`HeroBanner` rendered a `<video>` itself, from a raw URL. That meant it
could only ever hold a video, and left nowhere to hang a poster — the one
component where a poster matters most, being a full-bleed autoplaying
video above the fold.
It now takes `asset?: React.ReactNode` and renders it, exactly as its
sibling SpecialBanner already does. Positioning stays with the banner:
whatever is passed gets stretched to fill via `& img, & video`.
- <HeroBanner videoSrc={asset.filename} … />
+ <HeroBanner asset={<Asset asset={asset} poster={poster} />} … />
Taking a node rather than data also keeps next-ui free of any CMS: the
Storyblok and Hygraph examples each pass their own `<Asset>`, both of
which already render images and video. Importing a CMS `Asset` into
next-ui would have inverted the dependency — storyblok-ui and hygraph-ui
depend on next-ui, not the other way round.
Non-breaking: `videoSrc` stays as a deprecated fallback that renders a
bare autoplaying video (keeping the HeroBanner-video class), and the
`animated`/`video` class parts stay exported. The only behavioural change
on the videoSrc path is the loss of the scroll parallax, along with the
framer-motion, useScrollY and clientSize machinery it required.
…et-poster Feature/storyblok asset poster
…routes
Magento renders links from base_link_url, which on a headless setup points
at the GraphCommerce storefront. Every stock email template contains a
customer/account/ link ("Sign in to your account") and gated Magento routes
302 to customer/account/login — GraphCommerce serves none of those, so
customers landed on a 404.
withGraphCommerce now adds permanent redirects for /customer/account,
/customer/account/index, /customer/account/login, /customer/account/create,
/customer/account/forgotpassword and /sales/order/history. They are exact
matches on purpose: redirects run before the filesystem routes, so a
/customer/account/:path* catch-all would shadow the
pages/customer/account/{confirm,createPassword} routes that
@graphcommerce/magento-customer copies into the project.
This restores the /customer/account redirect that was dropped as collateral
in "Remove redirects for /product/$type/[url] routes".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`multilinkHref` preferred the multilink's `cached_url`, which Storyblok freezes at the moment the *referencing* story is published. Renaming the target story does not rewrite it in already-published content, so every link to the renamed story kept emitting the old URL — a 404 — until an editor re-published each referencing story. `story.full_slug` is injected by `@storyblok/react` from the `links` map the CDN builds from the live story index on every request, and `sbParams` already sends `resolve_links: 'story'` on all reads, so it is populated for story links and always current. Prefer it, and fall through unchanged for `url` / `email` / `asset` links, which have no resolved story. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review feedback: the entry had no evidence behind it. Grepping every stock Magento email template shows only three customer URLs — customer/account/ (48x), customer/account/createPassword (12x, carries id + rp_token) and customer/account/confirm (2x, carries id + key). forgotpassword appears in none of them; Magento's reset token rides on createPassword, and forgotpassword is just the form where a customer types their email. The remaining five are re-audited for shadowing. GraphCommerce serves exactly two paths under /customer: confirm and createPassword, both real pages in all three examples. None of the five sources collide with them (/customer/account/ create is an exact match and does not cover createPassword), and the comment now states the mechanism that makes this matter: a redirect wins over a filesystem route, so redirecting a path that has a page makes that page unreachable. Also corrects the comment's claim that @graphcommerce/magento-customer copies those pages in — it has no copy/ directory; they are scaffolded from the examples. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…refer-resolved-full-slug fix(storyblok-ui): resolve story multilinks to the target's current slug
…omer-account-urls fix(next-config): redirect Magento account URLs to the GraphCommerce routes
Add Google Places address autocomplete
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated release PR from canary branch