# 0.27.0 (/docs/changelog/0-27-0)



<Callout type="warn" title="Contains native changes">
  In-app update ships a **new native module**, and the iOS web view changed.
  Picking up either needs a [store release](/docs/ship/app-releases) — a config
  publish is not enough. Everything else in this release is JavaScript and
  needs only an app build at 0.27.0.
</Callout>

## Breaking [#breaking]

Three changes can stop your code compiling on 0.27.0. Read these before you upgrade.

* **PLP product-card registration was removed.** `registerPLPProductCardComponent`, `getPLPProductCardComponent`, and the `PLPProductCardProps` type are gone from `@gauntlet/brewery`. Cards are now registered by variant key: `app.components.register('product-card', '<variant>', Card)`. A product-grid block selects one with `options.productCardVariant`. Any app that overrode the PLP card must migrate.
* **`ICatalogProvider` gained three required methods**: `handleToId`, `idToHandle`, and `resolveRedirect`. A partner package implementing a custom catalog provider will no longer type-check until it adds them.
* **`CommonBlockKey` is now `string`** rather than a union of known block ids, so remote bundles can register ids the platform has never heard of. Not a compile break, but code relying on exhaustive narrowing loses it.

## New [#new]

**App extension host** — `@gauntlet/brewery` now exports an `app` object that owns registration and behavior: `app.components.register`, `app.modules.register`, `app.trackers.add`, `app.actions.define/extend/run`, and `app.events.on/emit`. Every registration returns an undo. `app.actions.extend` lets an integration gate, reshape, replace, or observe built-in actions like `cart:add` and `checkout:begin` without the app owner editing their code; see [Extending app behavior](/docs/build/extending-app-behavior). The existing `blockRegistry` pattern still works.

**`Result` return values** — `@gauntlet/types` adds `Result` with `ok`, `err`, `isOk`, `isErr`, and `toDisplayMessage`. Every `app.actions.run` returns one instead of throwing, so a blocked action comes back with a reason you can show.

**`onConfigReady(cb)`** — a one-shot callback in `@gauntlet/state` for "app config has landed", replacing `config.init(...).then(...)`.

**PLP grid density** — product listings can offer several column layouts, with a shopper-facing density toggle in the sort-and-filter row. Layouts are authored per block (`options.gridLayouts`, each `{ id, columns, productCardVariant? }`) with per-layout styling, and the shopper's choice carries across listings. Build your own toggle with the new `usePlpGridToggle()` hook from `@gauntlet/state`. Page-size counts authored for a 2-up grid scale automatically so rows-per-page stay constant at other densities.

**Forced and flexible in-app update** — a config-driven update gate under `settings.global.appUpdate`: a blocking overlay when the installed version is below `minRequiredVersion`, or (on Android) a background download with install prompts. The iOS version check is scoped to the store's country, which fixes apps published outside the US. Adds the `in-app-update` common block. Requires the new native module, and degrades to the older prompt if the app has not been rebuilt.

**Shopify URL redirects on deep links** — opt-in via `enableShopifyUrlRedirects`, with a `shopifyUrlRedirectsTimeoutMs` cap (default 1.5s). When a link's handle no longer exists, the store's redirect is resolved before navigation parses the URL, so a dead product link can land on its replacement collection. Applies to links that open the app, which is the ad-campaign case; links tapped inside a running app keep their path.

**Time-windowed carousel slides** — individual slides can carry a `visibility.duration` window and the carousel re-renders itself at each boundary. The underlying `useScheduledItems` / `isWithinSchedule` helpers work for anything with a schedule.

**Cart visibility rules by product tag** — visibility conditions gain `filters`, `aggregate` (`count` or `sum`), and `path`, so a rule can express "the cart holds at least four units tagged `gift`". Note that `sum` fails closed if any item's value is non-numeric, and per-unit `price` ignores quantity; sum the line total instead.

**Two new integrations** — Smart Wishlist (syncs a signed-in customer's wishlist between web and app) and Unbxd Recommendations (PDP, cart, and generic recommendation blocks). Both are config-only.

**Smaller additions** — loyalty reward-summary, VIP-program, and wallet-transaction blocks gained v2 versions with tiering and expiry; cart list v2 exposes divider, card border, and bottom-sheet styles; toasts take `numberOfLines` and a leading icon on add-to-cart; product videos now carry a poster image; search suggestions can surface metafields; wallet passes respect merchant activation flags.

## Fixed [#fixed]

* Sign-in on the Shopify checkout web view, and a consistent sign-in success message across components.
* An invalid freebie could persist in the cart.
* Navigating back to a product listing re-fetched the collection because unmounting cleared its cache.
* Deep links carrying a collection handle routed to the wrong parameter.
* The orders list blanked while a single order loaded.
* The price-range filter flickered when tapped outside.
* Web-view intent links that fail to open now fall back to a configured URL.
* **iOS**: `window.appbrew` was torn down when `hideElementSelectors` was set, which broke pages that rely on the bridge.
* Review-list pagination did not scroll to the top; analytics sent a wrong transaction id; metafields were injected into product payloads where they did not belong.
* Cold starts re-downloaded JS chunks because the script cache was not persisted.
* The flat product-listing renderer is now used on tabbed screens too.
* Per-block profiling was removed from rendering, cutting measurable overhead.

## Upgrading [#upgrading]

Bump every `@gauntlet/*` entry to `0.27.0` together with the Appbrew-published `@app-brew/*` packages, which move with the platform, then rebuild. Full workflow: [Upgrading @gauntlet packages](/docs/ship/upgrading).
