> ## Documentation Index
> Fetch the complete documentation index at: https://docs.depict.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

<Warning>
  This page does not apply to installs made in 2025 or later of the Depict Shopify apps
</Warning>

Product listing pages are quite similar to search, except that there's no search field/search modal. Instead of being based on a search query, they're based on a so-called `categoryId` which is an id representing what category or collection to show.

### Why does "product listing page" mean something different in code?

Please see [naming discrepancies](/reference/glossary/naming-discrepancies) in the reference section for more information.

### The CategoryPage component

<Frame caption="A default `CategoryPage` (with customised styling)">
  <img
    src="https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=f5ff41f8554ea49e6378e5ce98c4f51f"
    style={{ width: "100%", aspectRatio: 1913/1828 }}
    ref={async element => {
    if(!element) return;

    // In prod, they have some zoom thing which breaks aspectRatio, work around that. Unfortunately this is not in the SSR'd output so there's still some CLS.
    const direct_parent = element?.parentElement;
    if(direct_parent?.matches?.("[data-rmiz-content]")) {
        Object.assign(direct_parent.style, {
            width: "100%",
            display: "flex",
            justifyContent: "center",
            alignItems: "center"
        })
    }
    const parents_parent = direct_parent?.parentElement;
    if(parents_parent?.matches?.("[aria-owns^='rmiz-modal']")) {
        parents_parent.style.width = "100%";
    }

    // Fix background color in dark mode while still having cool, transparent light mode background
    if(!window.utilishared_promise) {
        window.utilishared_promise = new Promise(resolve => {
            window.resolve_utilishared = resolve;
            const script = document.createElement("script");
            script.type = "module";
            script.append(`
        import * as utilishared from "https://esm.run/@depict-ai/utilishared@latest/latest";
        window?.resolve_utilishared(utilishared);
        `)
            document.head.append(script);
        })
    }

    const utilishared = await utilishared_promise;

    const { style } = element;
    const update_styling = () => {
        const dark = document.documentElement.classList.contains("dark");
        style.background = dark ? "white" : "";
        style.padding = dark ? "5px" : "";
        style.borderRadius = dark ? "0.75rem" : "";
    };
    const m_o = new MutationObserver(utilishared.catchify(update_styling));
    m_o.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ["class"]
    })
    update_styling();
    utilishared.observer.onremoved(element, () => m_o.disconnect());
}}
    data-og-width="1913"
    width="1913"
    data-og-height="1828"
    height="1828"
    data-path="images/category_page_overview.svg"
    data-optimize="true"
    data-opv="3"
    srcset="https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?w=280&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=5e828aa690006325a068b40af9f6e83b 280w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?w=560&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=67cb262de3a6564657f944d705194a95 560w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?w=840&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=853547e48a98e4f7e5d69ad1a38532bf 840w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?w=1100&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=a9661423af7c89cbb7cf27622feef4bd 1100w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?w=1650&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=eee90ed4aa006193475d4bcec6679255 1650w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/category_page_overview.svg?w=2500&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=2e116cc678970dd7b1e383b42847d171 2500w"
  />
</Frame>

## Additional exported components

Because you might want to have content between the BreadCrumbs, QuickLinks and the actual product listing, we also export the following components:

<Frame caption="QuickLinks">
  <img
    src="https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=407a338a14878851039376878934f73d"
    style={{ width: "100%", aspectRatio: 283/23 }}
    ref={element => {
    // In prod, they have some zoom thing which breaks aspectRatio, work around that. Unfortunately this is not in the SSR'd output so there's still some CLS.
    const direct_parent = element?.parentElement;
    if(direct_parent?.matches?.("[data-rmiz-content]")) {
        Object.assign(direct_parent.style, {
            width: "100%",
            display: "flex",
            justifyContent: "center",
            alignItems: "center"
        })
    }
    const parents_parent = direct_parent?.parentElement;
    if(parents_parent?.matches?.("[aria-owns^='rmiz-modal']")) {
        parents_parent.style.width = "100%";
    }
}}
    data-og-width="1132"
    width="1132"
    data-og-height="92"
    height="92"
    data-path="images/quicklinks.svg"
    data-optimize="true"
    data-opv="3"
    srcset="https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?w=280&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=b757bac93ea08d36bee8d4968c3d40cd 280w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?w=560&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=04c4113bc82b528e1803ef240c488934 560w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?w=840&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=6bd68d23c05ea66e1fab8ef4d43aaa06 840w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?w=1100&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=97c1bd7053341d7462ea3c13308a4601 1100w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?w=1650&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=5512e7c00b73105dcbeb4e829b5a9964 1650w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/quicklinks.svg?w=2500&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=394de7bc9c5a8e39ba440b3eace4c80b 2500w"
  />
</Frame>

<br />

<Frame caption="BreadCrumbs">
  <img
    src="https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=03bfb7e6fdc18d31766e74e0027b9578"
    style={{ width: "100%", aspectRatio: 253/29 }}
    ref={async element => {
    if(!element) return;

    // In prod, they have some zoom thing which breaks aspectRatio, work around that. Unfortunately this is not in the SSR'd output so there's still some CLS.
    const direct_parent = element?.parentElement;
    if(direct_parent?.matches?.("[data-rmiz-content]")) {
        Object.assign(direct_parent.style, {
            width: "100%",
            display: "flex",
            justifyContent: "center",
            alignItems: "center"
        })
    }
    const parents_parent = direct_parent?.parentElement;
    if(parents_parent?.matches?.("[aria-owns^='rmiz-modal']")) {
        parents_parent.style.width = "100%";
    }

    // Fix background color in dark mode while still having cool, transparent light mode background
    if(!window.utilishared_promise) {
        window.utilishared_promise = new Promise(resolve => {
            window.resolve_utilishared = resolve;
            const script = document.createElement("script");
            script.type = "module";
            script.append(`
        import * as utilishared from "https://esm.run/@depict-ai/utilishared@latest/latest";
        window?.resolve_utilishared(utilishared);
        `)
            document.head.append(script);
        })
    }

    const utilishared = await utilishared_promise;

    const { style } = element;
    const update_styling = () => {
        const dark = document.documentElement.classList.contains("dark");
        style.background = dark ? "white" : "";
        style.padding = dark ? "5px" : "";
        style.borderRadius = dark ? "0.75rem" : "";
    };
    const m_o = new MutationObserver(utilishared.catchify(update_styling));
    m_o.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ["class"]
    })
    update_styling();
    utilishared.observer.onremoved(element, () => m_o.disconnect());
}}
    data-og-width="506"
    width="506"
    data-og-height="58"
    height="58"
    data-path="images/breadcrumbs.svg"
    data-optimize="true"
    data-opv="3"
    srcset="https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?w=280&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=0de834daec8b63746a2e4dc42471890f 280w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?w=560&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=8dd159c5421ec6ef8d744fa4993d9202 560w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?w=840&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=dc7d189857b403c26f2907ca3127e983 840w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?w=1100&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=54439b93e72e307ed9cf83918d2262d5 1100w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?w=1650&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=cea19d751cb20b3446d26310b3766b07 1650w, https://mintcdn.com/depictai/oqYy6W_ukzaDVZL8/images/breadcrumbs.svg?w=2500&fit=max&auto=format&n=oqYy6W_ukzaDVZL8&q=85&s=d2d36d85c5742ac98c4ed00f5a44799b 2500w"
  />
</Frame>

See the [reference](/reference/listing-sdk/listing-page-react-sdk#the-categorypage-component) for more information.
