v2.17.2

comet-ml/opikv2.17.2Jul 1, 2026by NicolasGorga

AI Summary

This release introduces a new customizable Admin Layout Composer, async payment methods, and tiered pricing support for the admin dashboard.

Key Highlights

  • Breaking change: Widget injection zones `.after` and `.before` no longer control placement in LayoutComposer controlled pages
  • New Admin Layout Composer with drag-and-drop and database persistence
  • Async Payment Methods support across the checkout lifecycle
  • Tiered Pricing for Price List Prices

Breaking Changes

  • .after | .before widget injection zones no longer control placement in LayoutComposer controlled pages

New Features

  • Drag-and-drop Layout Composer
  • Async Payment Methods
  • Tiered Pricing
  • Contextual Browser Tab Titles

Full Release Notes

## Highlights

#### before / after on widgets injection zones

🚧 Breaking change

Since the components in a `LayoutComposer` controlled page are now arranged through the Editor view (including widgets), the `.after | .before` widget injection zones don't have an effect on where the Widget is placed within its injection zone - you should configure this, just like with any other layout component, through the Editor view. The `.side` is still relevant for Two Column page layouts.

### New Admin Layout Composer

The admin dashboard layout is now fully customizable through a reworked Layout Composer. You can rearrange the Topbar, Sidebar, Settings Sidebar and pages with drag and drop, and your arrangement is persisted in the database so it stays consistent across sessions and users.

This rework started as a community contribution from [@leobenzol](https://github.com/leobenzol), who built the drag-and-drop Layout Composer and settings persistence and applied it across the shell. Thanks to their work, extending and reordering the dashboard layout is now a first-class part of the admin. A prime example of the kind of high-value features the community can drive in Medusa. Read more in the [announcement](https://medusajs.com/blog/announcing-layout-composer/).

[#15721](https://github.com/medusajs/medusa/pull/15721)
[#15861](https://github.com/medusajs/medusa/pull/15861)
[#15862](https://github.com/medusajs/medusa/pull/15862)

---

### Async Payment Methods Support

Medusa now supports asynchronous payment methods, where a payment is confirmed after the initial request through provider webhooks rather than synchronously. The support spans the Payment module, the Stripe provider, core workflows, the JS SDK, and the admin dashboard, so async methods are handled consistently across the checkout and payment lifecycle.

[#15085](https://github.com/medusajs/medusa/pull/15085)

---

### Tiered Pricing for Price List Prices

Price list prices now support quantity-based tiers directly in the admin. Click a price cell in the price list edit form to define multiple price tiers per variant and currency, making it straightforward to set up bulk discounts and other quantity-based pricing strategies across regions and currencies.

https://github.com/user-attachments/assets/1521c033-aee9-4fca-a2b8-d09ea2a95e2e

[#15258](https://github.com/medusajs/medusa/pull/15258)

---

### Contextual Browser Tab Titles

The admin dashboard now sets a descriptive document title for each page, so multiple open tabs are easy to tell apart. List pages show the section name (for example "Products - Medusa") and detail pages surface the entity name (for example a product's title or an order's display id). Titles are resolved through a new `seo` resolver on each route's handle.

Custom admin pages in your own project can set their tab title the same way, by exporting a `handle` with an `seo` resolver from the route file. Return a static title, or derive one from the route's loader data via `match.data`:

```tsx
// src/admin/routes/custom/page.tsx
import { defineRouteConfig } from "@medusajs/admin-sdk"

export const handle = {
  seo: () => ({ title: "My Custom Page" }),
}

export const config = defineRouteConfig({
  label: "My Custom Page",
})

const CustomPage = () => {
  return <div>My custom page</div>
}

export default CustomPage
```

[#14426](https://github.com/medusajs/medusa/pull/14426)

## Features

- feat: drag&drop LayoutComposer, settings db persistence by [@leobenzol](https://github.com/leobenzol) in [#15721](https://github.com/medusajs/medusa/pull/15721)
- feat(payment,payment-stripe,core-flows,medusa,dashboard,js-sdk,utils,types): introduce async payment methods support by [@NicolasGorga](https://github.com/NicolasGorga) in [#15085](https://github.com/medusajs/medusa/pull/15085)
- feat(dashboard): add dynamic document titles for browser tabs by [@bqst](https://github.com/bqst) in [#14426](https://github.com/medusajs/medusa/pull/14426)
- feat(admin-shared,dashboard): apply new LayoutComposer approach across the admin dashboard by [@NicolasGorga](https://github.com/NicolasGorga) in [#15861](https://github.com/medusajs/medusa/pull/15861)
- feat(admin-shared,dashboard): use layout composer in Topbar, Sidebar and settings Sidebar by [@leobenzol](https://github.com/leobenzol) in [#15862](https://github.com/medusajs/medusa/pull/15862)
- feat(dashboard): add quantity-based pricing support for price lists by [@laaibaQasim](https://github.com/laaibaQasim) in [#15258](https://github.com/medusajs/medusa/pull/15258)

## Bugs

- fix(payment-stripe): handle async payment method check gracefully in webhook by [@NicolasGorga](https://github.com/NicolasGorga) in [#15897](https://github.com/medusajs/medusa/pull/15897)
- fix(core-flows): keep customer account-holder link on a failed payment-session init by [@Mezzle](https://github.com/Mezzle) in [#15618](https://github.com/medusajs/medusa/pull/15618)
- fix(utils): allow alias override in defineLink InputOptions to support linking the same module twice by [@kowalski21](https://github.com/kowalski21) in [#15701](https://github.com/medusajs/medusa/pull/15701)
- fix(order): make custom_display_id searchable by [@Dev-Abdullah-H](https://github.com/Dev-Abdullah-H) in [#15622](https://github.com/medusajs/medusa/pull/15622)
- fix: Product option and product option values are not translatable by [@weknowyourgame](https://github.com/weknowyourgame) in [#15881](https://github.com/medusajs/medusa/pull/15881)
- fix(core-flows,medusa): exclude gift cards from tax calc and add an option for custom gift card codes by [@scherddel](https://github.com/scherddel) in [#15419](https://github.com/medusajs/medusa/pull/15419)
- fix: move the remote joiner class to the modules SDK package by [@sradevski](https://github.com/sradevski) in [#15890](https://github.com/medusajs/medusa/pull/15890)
- fix(order): use isDefined check for unit_price in item-update action by [@Dev-Abdullah-H](https://github.com/Dev-Abdullah-H) in [#15863](https://github.com/medusajs/medusa/pull/15863)

## Chores

- chore: add package bugs metadata to published packages by [@Floofy6](https://github.com/Floofy6) in [#15683](https://github.com/medusajs/medusa/pull/15683)
- chore: remove unused test suites by [@sradevski](https://github.com/sradevski) in [#15888](https://github.com/medusajs/medusa/pull/15888)
- chore: remove legacy API tests that are no longer relevant by [@sradevski](https://github.com/sradevski) in [#15877](https://github.com/medusajs/medusa/pull/15877)

## New Contributors

- @Mezzle made their first contribution in [#15618](https://github.com/medusajs/medusa/pull/15618)
- @kowalski21 made their first contribution in [#15701](https://github.com/medusajs/medusa/pull/15701)
- @laaibaQasim made their first contribution in [#15258](https://github.com/medusajs/medusa/pull/15258)
- @weknowyourgame made their first contribution in [#15881](https://github.com/medusajs/medusa/pull/15881)
- @Floofy6 made their first contribution in [#15683](https://github.com/medusajs/medusa/pull/15683)

**Full Changelog**: [v2.17.1...v2.17.2](https://github.com/medusajs/medusa/compare/v2.17.1...v2.17.2)