The new version of UI Extensions (2025-10) does not work

I have followed the migration steps as indicated in the documentation, but I have not been able to display my UI Extensions again.

I can add the UI extensions from customise and the shopify app deploy command does not fail, but it does not show me anything, not even console.logs. Where is the issue? :frowning:

Here is the previous code for one of the UI extensions, which is, for example, a simple list of policies linklist:

import { useEffect, useState } from "react";
import {
  reactExtension,
  Link,
  Grid,
  View,
  Style,
  useApi,
  useTranslate
} from "@shopify/ui-extensions-react/checkout";

export default reactExtension("purchase.checkout.footer.render-after", () => (
  <Extension />
));

function Extension() {
  const { query, ui } = useApi();

  const [ loading, setLoading] = useState(false);
  const [policies, setPolicies] = useState([]);
  const translate = useTranslate();

  useEffect(() => {
    fetchPolicies();
  }, []);

  const fetchPolicies = async () => {
    setLoading(true);
    try {
      const { data } = await query(`
        query {
          shop {
            primaryDomain {
              url
            }
            shippingPolicy {
              title
              handle
              body
              url
            }
            privacyPolicy {
              title
              handle
              body
              url
            }
            refundPolicy {
              title
              handle
              body
              url
            }
            termsOfService {
              title
              handle
              body
              url
            }
          }
        }
      `);

      // Map policies to array with label/content
      const raw = data?.shop;

      const mapped = [
        { key: 'shippingPolicy', shop_domain: raw?.primaryDomain.url, handle: raw?.shippingPolicy?.handle ,label: raw?.shippingPolicy?.title, content: raw?.shippingPolicy?.body },
        { key: 'privacyPolicy', shop_domain: raw?.primaryDomain.url, handle: raw?.privacyPolicy?.handle ,label: raw?.privacyPolicy?.title, content: raw?.privacyPolicy?.body },
        { key: 'refundPolicy', shop_domain: raw?.primaryDomain.url, handle: raw?.refundPolicy?.handle ,label: raw?.refundPolicy?.title, content: raw?.refundPolicy?.body },
        { key: 'termsOfService', shop_domain: raw?.primaryDomain.url, handle: raw?.termsOfService?.handle ,label: raw?.termsOfService?.title, content: raw?.termsOfService?.body },
        { key: 'cookiePreferences', shop_domain: raw?.primaryDomain.url, handle: '/pages/politica-de-cookies' ,label: 'Cookie policy', content: '' },
      ].filter(p => p.content);
      setPolicies(mapped);
    } catch (error) {
      console.error("Error fetching policies", error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <Grid
      columns={Style.default(['1fr', '1fr'])
        .when({viewportInlineSize: {min: 'small'}}, ['1fr', '1fr'])
        .when({viewportInlineSize: {min: 'medium'}}, ['1fr', '1fr', '1fr'])
        .when({viewportInlineSize: {min: 'large'}}, ['1fr', '1fr', '1fr', '1fr'])}
      rows={['auto', 'auto']}
      spacing="loose"
      blockAlignment="center"
      maxInlineSize={'fill'}
      minInlineSize={'fill'}
      minBlockSize={'fill'}
    >
      {policies.map((policy) => (
        <View inlineAlignment="center">
          <Link to={policy.shop_domain + '/policies/' + policy.handle}>
            {translate(policy.key)}
          </Link>
        </View>
      ))}
    </Grid>
  );
}

and the current one with new version:

import { useEffect, useState } from "react";
import '@shopify/ui-extensions/preact';
import {render} from 'preact';
import {
  useApi,
  useTranslate
} from "@shopify/ui-extensions/checkout/preact";

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

function Extension() {
  const { query, ui } = useApi();

  const [ loading, setLoading] = useState(false);
  const [policies, setPolicies] = useState([]);
  const translate = useTranslate();

  useEffect(() => {
    fetchPolicies();
  }, []);

  const fetchPolicies = async () => {
    setLoading(true);
    try {
      const { data } = await query(`
        query {
          shop {
            primaryDomain {
              url
            }
            shippingPolicy {
              title
              handle
              body
              url
            }
            privacyPolicy {
              title
              handle
              body
              url
            }
            refundPolicy {
              title
              handle
              body
              url
            }
            termsOfService {
              title
              handle
              body
              url
            }
          }
        }
      `);

      // Map policies to array with label/content
      const raw = data?.shop;

      const mapped = [
        { key: 'shippingPolicy', shop_domain: raw?.primaryDomain.url, handle: raw?.shippingPolicy?.handle ,label: raw?.shippingPolicy?.title, content: raw?.shippingPolicy?.body },
        { key: 'privacyPolicy', shop_domain: raw?.primaryDomain.url, handle: raw?.privacyPolicy?.handle ,label: raw?.privacyPolicy?.title, content: raw?.privacyPolicy?.body },
        { key: 'refundPolicy', shop_domain: raw?.primaryDomain.url, handle: raw?.refundPolicy?.handle ,label: raw?.refundPolicy?.title, content: raw?.refundPolicy?.body },
        { key: 'termsOfService', shop_domain: raw?.primaryDomain.url, handle: raw?.termsOfService?.handle ,label: raw?.termsOfService?.title, content: raw?.termsOfService?.body },
        { key: 'cookiePreferences', shop_domain: raw?.primaryDomain.url, handle: '/pages/politica-de-cookies' ,label: 'Cookie policy', content: '' },
      ].filter(p => p.content);
      setPolicies(mapped);
    } catch (error) {
      console.error("Error fetching policies", error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <s-grid
      gridTemplateColumns="1fr auto" gap="base"
      rows={['auto', 'auto']}
      spacing="loose"
      blockAlignment="center"
      maxInlineSize={'fill'}
      minInlineSize={'fill'}
      minBlockSize={'fill'}
    >
      {policies.map((policy) => (
        <s-box inlineAlignment="center">
          <s-link to={policy.shop_domain + '/policies/' + policy.handle}>
            {translate(policy.key)}
          </s-link>
        </s-box>
      ))}
    </s-grid>
  );
}

Did you also update your package.json definition to make sure your related npm dependencies are also updated to 2025-10?

You’ll need to re-install as well if they aren’t up to date.

Hey @Dylan ,
Thanks for your reply.

Yes, they are up to date and I have run npm install again:

but it still doesn’t work :frowning:

Thanks for the screenshot @AlexPG96

But it looks like what you’re showing is an app’s npm dependencies not an extensions.

I suspect this because I’m seeing app bridge and shopify API related dependencies, not the shopify extensions specific packages.

@Dylan Yeah, because there is no package.json file in my UI Extensions. The only package.json file that exists is the application’s package.json.

The contents of the UI Extension directory would be as follows:

That might be part of the issue @AlexPG96

These components are npm packages, and they need their dependencies installed.

Based on your sample code, it sounds like you’re creating a Checkout UI Extension. I recommend either searching through your git history to find the deleted package.json in that extension directory, or generating a new checkout extension just to copy the base package.json format.

Hello @Dylan ,

As far as I know, UI Extensions do not have a package.json file, only Checkout Functions do. Likewise, I have generated a new UI Extension, which is displayed, and it generates these files:

Thanks for the screenshot, that’s helpful.

Is it possible your working in a monorepo project? I confirmed that all of my UI related extensions (Customer, Checkout, Admin) all have their own package.json’s which contain their required dependencies like @shopify/ui-extensions and @shopify/ui-extensions-react

But then again, I wonder if the new web component based Extensions don’t generate package.json’s. I still think they rely on preact but if someone from Shopify could confirm that would be great.

They still have package.json and have preact + the ui-extensions library as dependencies