Blog
Releases

Upgrading to Puck 0.21

Fede Bonel TozziFede Bonel Tozzi
Jan 14, 2026

Puck 0.21 moves all packages to the @puckeditor namespace and includes some UI and behavior updates to be aware of.

This guide covers everything you need to know to upgrade and take advantage of what’s new:

If you’d like to help test Puck 0.21, follow this guide and report any issues you encounter.

For a full overview of what’s new in Puck 0.21, check out the release blog post.

Installing Puck 0.21

All packages have moved to the @puckeditor scope:

Installing the editor

Install the latest version of the Puck editor:

npm install --save-exact @puckeditor/core@^0.21.0

Update all imports from @measured/puck to @puckeditor/core:

// Before:
import { Puck } from "@measured/puck";
import "@measured/puck/puck.css";
 
// After:
import { Puck } from "@puckeditor/core";
import "@puckeditor/core/puck.css";

Remove the @measured/puck package:

npm uninstall @measured/puck

Make sure to follow these steps for any other packages you’re using.

Breaking changes

No breaking changes were introduced in this version.

New deprecations

No deprecations were introduced in this version.

Notable changes

The default UI now includes a navigation rail

In 0.21.0, the default UI includes a left-side navigation rail where plugins can render UI. The component drawer and outline are now shown as icons in this rail.

To opt out of this navigation rail and keep the previous UI, use the legacySideBarPlugin:

// Before:
import { Puck } from "@measured/puck";
 
export function Editor() {
  return <Puck .../>;
}
 
// After:
import { Puck, legacySideBarPlugin } from "@puckeditor/core";
 
const legacySideBar = legacySideBarPlugin();
 
export function Editor() {
  return <Puck plugins={[legacySideBar]} .../>;
}

New default viewport: Full-width

The default set of viewports now includes a full-width viewport that fills the width of the canvas container without scaling the resolution.

If you prefer to keep the explicit default viewport behavior from the previous version, provide them explicitly via the viewports prop:

// Before:
import { Puck } from "@measured/puck";
 
export function Editor() {
  return <Puck .../>;
}
 
// After:
import { Puck } from "@puckeditor/core";
 
export function Editor() {
  return (
    <Puck
      viewports={[
        {
          width: 360,
          height: "auto",
          icon: "Smartphone",
          label: "Small",
        },
        {
          width: 768,
          height: "auto",
          icon: "Tablet",
          label: "Medium",
        },
        {
          width: 1280,
          height: "auto",
          icon: "Monitor",
          label: "Large",
        },
      ]}
    />
  );
}

New execution trigger for resolveData

resolveData now runs when a component is moved to a different parent.

If you only want to execute resolveData when the props change, skip this execution by checking the new move trigger:

const config = {
  Item: {
    resolveData: (data, params) => {
      if (params.trigger === "move") {
        return data; // Skip execution when component is moved
      }
 
      // ...the rest of your resolveData logic
    },
  },
};

New execution trigger for resolvePermissions

resolvePermissions now runs when a component is moved to a different parent.

This should not affect most setups, since permissions are usually independent of position, or depend on it, which you can now check using the new params.parent.

Full changelog

Check out the full changelog, including known issues, on the GitHub release.

Learn more about Puck

If you’re interested in learning more about Puck, check out the demo or read the docs. If you like what you see, please give us a star on GitHub to help others find Puck too!