Skip to main content

Upgrading to 2025-10

This guide describes how to upgrade your point-of-sale UI extension to API version 2025-10 and adopt Polaris web components.


Set the API version to 2025-10 in shopify.extension.toml to use Polaris web components.

Anchor to shopify.extension.tomlshopify.extension.toml

api_version = "2025-10"

[[extensions]]
name = "your-extension"
handle = "your-extension"
type = "ui_extension"

# Contents of your existing file...

Anchor to Adjust package dependenciesAdjust package dependencies

As of 2025-10, Shopify recommends Preact for UI extensions. Update the dependencies in your package.json file and re-install.

Anchor to New dependencies with PreactNew dependencies with Preact

{
"dependencies": {
"preact": "^10.10.x",
"@preact/signals": "^2.3.x",
"@shopify/ui-extensions": "2025.10.x"
}
}

Anchor to Previous dependencies with ReactPrevious dependencies with React

{
"dependencies": {
"react": "^18.0.0",
"@shopify/ui-extensions": "2025.4.x",
"@shopify/ui-extensions-react": "2025.4.x",
"react-reconciler": "0.29.0"
},
"devDependencies": {
"@types/react": "^18.0.0"
}
}

Anchor to Previous dependencies with JavaScriptPrevious dependencies with JavaScript

{
"dependencies": {
"@shopify/ui-extensions": "2025.4.x"
}
}

Anchor to TypeScript configurationTypeScript configuration

Get full IntelliSense and auto-complete support by adding a config file for your extension at extensions/{extension-name}/tsconfig.json. You do not need to change your app's root tsconfig.json file.

{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact",
"target": "ES2020",
"checkJs": true,
"allowJs": true,
"moduleResolution": "node",
"esModuleInterop": true
}
}

{
"compilerOptions": {
"jsx": "react-jsx"
},
"include": ["./src"]
}

Anchor to Upgrade the Shopify CLIUpgrade the Shopify CLI

The new CLI adds support for building 2025-10 extensions.

The shopify app dev command runs your app and also generates a shopify.d.ts file in your extension directory, adding support for the new global shopify object.

Anchor to Support new global shopify objectSupport new global shopify object

# Upgrade to latest version of the CLI
npm install -g @shopify/cli

# Run the app to generate the type definition file
shopify app dev

Anchor to Optional ESLint configurationOptional ESLint configuration

If your app is using ESLint, update your configuration to include the new global shopify object.

module.exports = {
globals: {
shopify: 'readonly',
},
};

Instead of accessing APIs from a callback parameter, access them from the global shopify object. Here's an example of migrating API calls.

Anchor to New API calls in PreactNew API calls in Preact

import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return <s-button onClick={onButtonClick}>Print</s-button>;
}

async function onButtonClick() {
await shopify.print.print('documents/test-print');
console.log('print completed');
}

Anchor to Previous API calls in ReactPrevious API calls in React

import {
reactExtension,
Button,
useApi,
} from '@shopify/ui-extensions-react/point-of-sale';

export default reactExtension('pos.home.modal.render', () => <Extension />);

function Extension() {
const api = useApi();

async function onButtonClick(isChecked) {
await api.print.print('documents/test-print');
console.log('print completed');
}

return <Button onPress={onButtonClick} title="Print" />;
}

Anchor to Previous API calls in JavaScriptPrevious API calls in JavaScript

import {extension, Button} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root, api) => {
async function onButtonClick() {
await api.print.print('documents/test-print');
console.log('print completed');
}

root.replaceChildren(
root.createComponent(Button, {
onPress: onButtonClick,
title: 'Print',
}),
);
});

If you had previously been using React hooks, import those same hooks from a new Preact-specific package. Here's an example of migrating hooks.

import '@shopify/ui-extensions/preact';
import {render} from 'preact';
import {useState, useEffect} from 'preact/hooks';

export default function extension() {
render(<ConnectivityStatus />, document.body);
}

function ConnectivityStatus() {
const [isConnected, setIsConnected] = useState(
shopify.connectivity.current.value.internetConnected === 'Connected',
);

useEffect(() => {
const unsubscribe = shopify.connectivity.current.subscribe(
(newConnectivity) => {
setIsConnected(newConnectivity.internetConnected === 'Connected');
},
);
return unsubscribe;
}, []);

return (
<s-text tone={isConnected ? 'success' : 'warning'}>
Status: {isConnected ? 'Online' : 'Offline'}
</s-text>
);
}

Anchor to Previous hooks in ReactPrevious hooks in React

import React from 'react';
import {
Text,
useConnectivitySubscription,
reactExtension,
} from '@shopify/ui-extensions-react/point-of-sale';

const ConnectivityStatus = () => {
const connectivity = useConnectivitySubscription();
const isConnected = connectivity.internetConnected === 'Connected';

return (
<Text color={isConnected ? 'TextSuccess' : 'TextWarning'}>
Status: {isConnected ? 'Online' : 'Offline'}
</Text>
);
};

export default reactExtension('pos.home.modal.render', () => (
<ConnectivityStatus />
));

Anchor to Migrate to Polaris web componentsMigrate to Polaris web components

Polaris web components are exposed as custom HTML elements. Update your React or JavaScript components to custom elements.

Anchor to New components in PreactNew components in Preact

/* eslint-disable react/self-closing-comp */
import '@shopify/ui-extensions/preact';
import {render} from 'preact';

export default function extension() {
render(<Extension />, document.body);
}

function Extension() {
return (
<s-stack direction="inline" gap="base">
<s-text-field label="Gift message"></s-text-field>
<s-button variant="primary">Save</s-button>
</s-stack>
);
}

Anchor to Previous components in ReactPrevious components in React

import {
reactExtension,
Stack,
TextField,
Button,
} from '@shopify/ui-extensions-react/point-of-sale';

export default reactExtension('pos.home.modal.render', () => <Extension />);

function Extension() {
return (
<Stack direction="inline" gap="200">
<TextField label="Gift message" />
<Button title="Save" variant="primary" />
</Stack>
);
}

Anchor to Previous components in JavaScriptPrevious components in JavaScript

import {
extension,
Stack,
TextField,
Button,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root, _api) => {
root.replaceChildren(
root.createComponent(Stack, {direction: 'inline', gap: '200'}, [
root.createComponent(TextField, {
label: 'Gift message',
}),
root.createComponent(Button, {title: 'Save', variant: 'primary'}),
]),
);
});

Anchor to Polaris web components mappingPolaris web components mapping

Legacy ComponentPolaris Web ComponentMigration Notes
BadgeBadgeAvailable
BannerBannerAvailable
BoxBoxAvailable
ButtonButtonAvailable
CameraScannerCameraScannerComing soon
DateFieldDateFieldAvailable
DatePickerDatePickerAvailable
DatePickerDateSpinnerAvailable, Replaces DatePicker.inputMode="spinner"
DialogModalAvailable
EmailFieldEmailFieldAvailable
HeadingHeadingAvailable
IconIconAvailable, more icons coming soon.
ImageImageAvailable
ListVirtualizedListComing soon
NavigatorRemoved.
NumberFieldNumberFieldAvailable
PinPadComing soon
POSBlockPOSBlockAvailable
POSBlockRowReplaced by POSBlock
POSReceiptBlockReplaced by POSBlock
PrintPreviewDocumentPreviewComing soon
QRCodeQRCodeComing soon
RadioButtonListChoiceListAvailable
ScreenPageAvailable
ScrollViewScrollBoxAvailable
SearchBarSearchFieldAvailable
SectionSectionAvailable
SectionHeaderUse Section.heading
SegmentedControlTabs/TabComing soon
SelectableClickableAvailable
StackStackAvailable
StepperNumberFieldUse NumberField with stepper controls
TextTextAvailable
TextAreaTextAreaAvailable
TextFieldTextFieldAvailable
TileTileAvailable
TimeFieldTimeFieldAvailable
TimePickerTimePickerAvailable

Was this page helpful?