{"id":43813268,"url":"https://github.com/adobe/storefront-product-listing-page","last_synced_at":"2026-02-06T00:02:53.310Z","repository":{"id":201054926,"uuid":"703956634","full_name":"adobe/storefront-product-listing-page","owner":"adobe","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-22T17:33:32.000Z","size":1575,"stargazers_count":18,"open_issues_count":15,"forks_count":37,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-05-22T17:55:57.851Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adobe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-10-12T08:48:43.000Z","updated_at":"2025-05-22T16:34:00.000Z","dependencies_parsed_at":"2024-01-09T16:57:23.732Z","dependency_job_id":"e8af1f2d-1390-48b9-91f6-dc5b43abe693","html_url":"https://github.com/adobe/storefront-product-listing-page","commit_stats":null,"previous_names":["adobe/storefront-product-listing-page"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/adobe/storefront-product-listing-page","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Fstorefront-product-listing-page","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Fstorefront-product-listing-page/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Fstorefront-product-listing-page/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Fstorefront-product-listing-page/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adobe","download_url":"https://codeload.github.com/adobe/storefront-product-listing-page/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Fstorefront-product-listing-page/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29140049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T23:14:48.546Z","status":"ssl_error","status_checked_at":"2026-02-05T23:14:35.724Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-06T00:02:47.958Z","updated_at":"2026-02-06T00:02:53.303Z","avatar_url":"https://github.com/adobe.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# storefront-product-listing-page\n\n## Product Listing Page for Adobe Commerce Storefronts using Live Search\n\nThe product listing page provides coverage for both search and browse (PLP) results and includes the faceting, sorting, and product card areas on the page. This is the recommended default storefront PLP provided by Live Search. It provides a search experience that is client side rendered and hosted with a decoupled architecture.\n\nThe PLP calls the catalog service which extends the Live Search productSearch query to return product view data. This allows the PLP to render additional product attributes like swatches with a single call.\n\nLearn more:\n\n- Live Search https://experienceleague.adobe.com/docs/commerce-merchant-services/live-search/guide-overview.html?lang=en\n- PLP https://experienceleague.adobe.com/docs/commerce-merchant-services/live-search/live-search-storefront/plp-styling.html?lang=en\n- Catalog Service https://developer.adobe.com/commerce/webapi/graphql/schema/catalog-service/\n\n## Repo containing the Live Search PLP\n\nThis repo is provided as a reference implementation only. While you’re expected to create your own customizations based on these assets, those customizations can’t be supported by Adobe.\n\nBest practices include:\n\n- forking this repo\n- periodically rebasing with develop\n\n## Setup\n\n#### Requirements\n\nNode and NPM setup: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm\n\n- Node version: **v16 or greater**\n- NPM version: **v8 or greater**\n\n[NVM](https://nodejs.org/en/download/package-manager#nvm) is a nifty tool to help toggle between enironment versions\n\n#### Install dependencies\n\nWithin the root of the project (~/storefront-product-listing-page):\n\n```sh\nnpm install\n```\n\n#### Storybook (mdx files)\n\nInstall storybook: https://storybook.js.org/docs/react/get-started/install\n\n```sh\nnpm run storybook\n```\n\n#### Local Development\n\nbuild tailwind styles and run locally\n\n```sh\nnpm run tailwind:build\nnpm run dev\n```\n\nnote: for styles to update you must run `npm run tailwind:build`\n\nAnd open `localhost:8080/v2/index.html` in your favorite browser.\n\n### Unit Testing\n\n```sh\nnpm run test\n```\n\n### Build\n\n```sh\nnpm run tailwind:build # builds tailwind styles\nnpm run build\n```\n\nsearch.js will be built to ./dist/\n\n## Example setup:\n\nimport the script:\n\n```html\n\u003cscript type=\"text/javascript\" src=\"search.js\"\u003e\u003c/script\u003e\n```\n\n### Setup the Store Details:\n\nMost of these will be passed with the extension if you have your storefront setup. The SANDBOX_KEY (api key for the sandbox env) is the only key that will need to be set within webpack.\n\n#### Store Variables needed:\n\n```sh\nENVIRONMENT_ID\nWEBSITE_CODE\nSTORE_CODE\nSTORE_VIEW_CODE\nCUSTOMER_GROUP_CODE\nAPI_KEY\nSANDBOX_KEY # input this key into webpack.dev.js \u0026 webpack.prod.js\n```\n\n- To set up sandbox keys please see here: https://experienceleague.adobe.com/docs/commerce-merchant-services/catalog-service/installation.html?lang=en\n\n#### insert into store details config\n\n```ts\nconst storeDetails = {\n  environmentId: 'ENVIRONMENT_ID',\n  websiteCode: 'WEBSITE_CODE',\n  storeCode: 'STORE_CODE',\n  storeViewCode: 'STORE_VIEW_CODE',\n  config: {\n    minQueryLength: '2',\n    pageSize: 8,\n    perPageConfig: {\n      pageSizeOptions: '12,24,36',\n      defaultPageSizeOption: '24',\n    },\n    currencySymbol: '$',\n    currencyRate: '1',\n    allowAllProducts: false,\n    currentCategoryUrlPath: \"string\",\n    /* name of category to display */\n    categoryName: '',\n    /* display search box */\n    displaySearchBox: false,\n    /* '1' will return from php escapeJs and boolean is returned if called from data-service-graphql */\n    displayOutOfStock: '',\n    /* \"\" for search || \"PAGE\" for category search */\n    displayMode: '',\n    /* add locale for translations */\n    locale: '',\n    /* enable slider for price - EXPERIMENTAL, default is false */\n    priceSlider: false,\n    /* enable multiple image carousel - EXPERIMENTAL, default is false */\n    imageCarousel: false,\n    /* add listview as an option - EXPERIMENTAL, default is false */\n    listview: false,\n    /* optimize images with Fastly */\n    optimizeImages: true,\n    imageBaseWidth: 200,\n    /* Luma specific addToCart method. Enabled with the extension */\n    resolveCartId: resolveCartId(),\n    /* Luma specific addToCart method. Enabled with the extension */\n    refreshCart: refreshCart(),\n    /* custom add to cart callback function. Called on addToCart action */\n    addToCart: (sku, options, quantity) =\u003e {},\n  },\n  context: {\n    customerGroup: 'CUSTOMER_GROUP_CODE',\n  },\n  apiKey: 'API_KEY',\n};\n```\n\nAppend LiveSearchPLP to the storefront window:\n\n```js\nconst root = document.querySelector('div.search-plp-root');\n\nsetTimeout(async () =\u003e {\n  while (typeof window.LiveSearchPLP !== 'function') {\n    console.log('waiting for window.LiveSearchPLP to be available');\n    await new Promise((resolve) =\u003e setTimeout(resolve, 500));\n  }\n  window.LiveSearchPLP({ storeDetails, root });\n}, 1000);\n```\n\nYou can see the example in [dev-template.html](./dev-template.html)\n\n### Theming and Styling\n\nWe use Tailwind to style/theme our components. Here's a good read up if you are keen: [Tailwind Docs](https://tailwindcss.com/docs/utility-first)\n\nIn addition to this themeing, we have CSS classes where storefronts can target and customize specific components of the widget. CSS classes will be used to target specific components or elements of components for a more granular approach. In short, CSS variables can create a general theme and CSS classes can target specific elements in our widget.\n\nWith Tailwind we do not write custom CSS. Instead, we use its utility classes that are generated at buildtime using a config we provide and scanning our markup (this way we don't have extra CSS we don't need). This is our [config file](./tailwind.config.js).\n\nSo how do we use CSS variables to style our components? Great question 😄\n\nLet's say as if I want to style an element with the theme's primary color. Normally, in CSS we would have done the following:\n\n```tsx\n\u003cstyle\u003e\n .primaryColor {\n    color: var(--primary-color)\n }\n\u003c/style\u003e\n\n\u003cdiv class=\"primaryColor\"\u003e\n  Yippee I am a primary color!\n\u003c/div\u003e\n```\n\nUsing Tailwind the following produces the exact same result:\n\n```tsx\n\u003cdiv class=\"text-primary\"\u003eYippee I am a primary color!\u003c/div\u003e\n```\n\nLooking at the config file you will notice that the CSS variable is `--color-primary` is mapped to the Tailwind CSS theme color key `primary`. this means anywhere in Tailwind you would use a Color key in a class you can now use the word `primary`.\n\nYou can add your own variables to [tokens.css](./src/styles/tokens.css). Furthermore, you can define your own tailwind classes using these variables in the [config file](./tailwind.config.js).\n\n### Have tailwind only apply to the nested widget\n\nNow default behavior:\n\nFollow the [tailwind nesting documentation](https://tailwindcss.com/docs/using-with-preprocessors#nesting). Your [postcss.config](./postcss.config.js) will look like this:\n\n```js\nmodule.exports = {\n  plugins: [\n    require('postcss-import'),\n    require('tailwindcss/nesting'),\n    require('autoprefixer'),\n    require('tailwindcss'),\n    require('cssnano'),\n  ],\n};\n```\n\nFrom there you should be able to nest the tailwind classes:\n\n```css\n@import 'tailwindcss/base';\n@import 'tailwindcss/components';\n@import 'tailwindcss/utilities';\n```\n\nwithin `.ds-widgets` in [token.css](./src/styles/tokens.css)\n\n```css\n.ds-widgets {\n  @import 'tailwindcss/base';\n  @import 'tailwindcss/components';\n  @import 'tailwindcss/utilities';\n\n  ...;\n}\n```\n\nSome helpful tools when developing with tailwind:\n\n- [Tailwind CSS Intellisense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n\n### Developing with React\n\nTo extend and customize this repo, you must first be familiar with react:\n\n- https://react.dev/learn\n- https://preactjs.com/guide/v10/components // we use Preact, which is just a smaller bundle version of React\n\nExample Implemention - adding a button to [ProductItem](./src/components/ProductItem/ProductItem.tsx):\n\n```tsx\nexport const ProductItem: FunctionComponent\u003cProductProps\u003e = ({\n  item,\n  currencySymbol,\n  currencyRate,\n  setRoute,\n  refineProduct,\n}: ProductProps) =\u003e {\n  ...\n\n  const handleClickButton = () =\u003e {\n    console.log('clicked the button!');\n  }\n\n  return (\n    \u003cdiv className=\"ds-sdk-product-item group relative flex flex-col max-w-sm justify-between h-full\"\u003e\n        ...\n          \u003cdiv className=\"flex flex-col\"\u003e\n            \u003cdiv className=\"ds-sdk-product-item__product-name mt-md text-sm text-primary\"\u003e\n              {htmlStringDecode(productView.name)}\n            \u003c/div\u003e\n            \u003cProductPrice\n              item={refinedProduct ?? item}\n              isBundle={isBundle}\n              isGrouped={isGrouped}\n              isGiftCard={isGiftCard}\n              isConfigurable={isConfigurable}\n              isComplexProductView={isComplexProductView}\n              discount={discount}\n              currencySymbol={currencySymbol}\n              currencyRate={currencyRate}\n            /\u003e\n            \u003cbutton onClick={handleClickButton}\u003eI am a button!\u003c/button\u003e // added a button\n          \u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/a\u003e\n\n    \u003c/div\u003e\n  );\n};\n```\n\nFor more robust examples, please see our [Examples folder](https://github.com/adobe/storefront-product-listing-page/tree/main/src/examples)\n\n## Hosting with CDN\n\nFollow the below instructions on how to host with CDN and update your Commerce store to include your new product listing page.\n\n1. In the root of this repository, install dependencies: `npm install`\n1. Create a production build of the application: `npm run build`\n1. After the previous step succeeds, it will output a `search.js` file in the `dist/` directory. This is the production-ready product listing page.\n1. Follow the instructions from your favorite frontend hosting with CDN (we use AWS S3 + Cloudfront, but there are many options to choose from) to upload the `search.js` file.\n1. The hosting platform with CDN will provide you a url where the `search.js` file will be publicly hosted for your consumption.\n1. Take the url where the `search.js` file is hosted and validate in your browser that it is working correctly by loading the url in your browser and seeing the `search.js` file returned to you.\n1. Now the Live Search extension needs to be updated to include your new url. Find the `magento-live-search` extension code in your adobe commerce code base. Locate the directory `LiveSearchProductListing`.\n1. We will be updating two files under `magento-live-search \u003e LiveSearchProductListing`: `etc/config.xml` \u0026 `etc/csp_whitelist.xml`\n1. Changes for `etc/config.xml`: change the live search url in `\u003cfrontend_url\u003e`to match the one you created with your hosting/CDN solution url above. See below.\n1. ![image](./config_xml.png)\n1. Changes for `etc/csp_whitelist.xml`: find all references to the live search SaaS product list page (`plp-widgets-ui.magento.ds.com`) and replace with your hosting/CDN solution url. See below.\n1. ![image](./csp_whitelist_xml.png)\n1. Those are all the required changes. Now redeploy your adobe commerce store code and see your new custom product listing page in your storefront.\n\n_The purpose of this project is to provide a dev-ready starting point for developers to implement the product listing page. The project, repo, and any accompanying assets included herein (“Assets”) are provided “as-is” for your use solely at your sole discretion, risk, and responsibility. By using these Assets, you agree Adobe will in no event be responsible for any use of the Assets, including but not limited to any customizations made thereto, by you or any third party. Adobe will not provide any support of any kind for any customizations made to the Assets by anyone._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadobe%2Fstorefront-product-listing-page","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadobe%2Fstorefront-product-listing-page","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadobe%2Fstorefront-product-listing-page/lists"}