diff --git a/packages/extensions/venia-pwa-live-search/package.json b/packages/extensions/venia-pwa-live-search/package.json
new file mode 100644
index 0000000000..116a3a1608
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "@magento/venia-pwa-live-search",
+  "version": "1.0.0",
+  "description": "Live Search PWA Studio extension.",
+  "main": "src/index.jsx",
+  "scripts": {
+    "clean": " "
+  },
+  "repository": "https://github.com/github:magento/pwa-studio",
+  "license": "MIT",
+  "dependencies": {
+    "@adobe/magento-storefront-event-collector": "^1.13.0",
+    "@adobe/magento-storefront-events-sdk": "^1.13.0",
+    "@magento/pwa-buildpack": "~11.5.3",
+    "@magento/storefront-search-as-you-type": "~1.0.4",
+    "@magento/venia-ui": "~11.5.0",
+    "currency-symbol-map": "^5.1.0"
+  },
+  "peerDependencies": {
+    "react": "^17.0.2"
+  },
+  "pwa-studio": {
+    "targets": {
+      "intercept": "src/targets/intercept"
+    }
+  }
+}
diff --git a/packages/extensions/venia-pwa-live-search/postcss.config.js b/packages/extensions/venia-pwa-live-search/postcss.config.js
new file mode 100644
index 0000000000..da813f6b23
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/postcss.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+    plugins: [require('tailwindcss/nesting')]
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/api/fragments.js b/packages/extensions/venia-pwa-live-search/src/api/fragments.js
new file mode 100644
index 0000000000..d44fb4572b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/api/fragments.js
@@ -0,0 +1,193 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+const Facet = `
+    fragment Facet on Aggregation {
+        title
+        attribute
+        buckets {
+            title
+            __typename
+            ... on CategoryView {
+                name
+                count
+                path
+            }
+            ... on ScalarBucket {
+                count
+            }
+            ... on RangeBucket {
+                from
+                to
+                count
+            }
+            ... on StatsBucket {
+                min
+                max
+            }
+        }
+    }
+`;
+
+const ProductView = `
+    fragment ProductView on ProductSearchItem {
+        productView {
+            id
+            __typename
+            sku
+            name
+            inStock
+            url
+            urlKey
+            images {
+                label
+                url
+                roles
+            }
+            ... on ComplexProductView {
+                priceRange {
+                    maximum {
+                        final {
+                            amount {
+                                value
+                                currency
+                            }
+                        }
+                        regular {
+                            amount {
+                                value
+                                currency
+                            }
+                        }
+                    }
+                    minimum {
+                        final {
+                            amount {
+                                value
+                                currency
+                            }
+                        }
+                        regular {
+                            amount {
+                                value
+                                currency
+                            }
+                        }
+                    }
+                }
+                options {
+                    id
+                    title
+                    values {
+                        title
+                        ... on ProductViewOptionValueSwatch {
+                            id
+                            inStock
+                            type
+                            value
+                        }
+                    }
+                }
+            }
+            ... on SimpleProductView {
+                price {
+                    final {
+                        amount {
+                            value
+                            currency
+                        }
+                    }
+                    regular {
+                        amount {
+                            value
+                            currency
+                        }
+                    }
+                }
+            }
+        }
+        highlights {
+            attribute
+            value
+            matched_words
+        }
+    }
+`;
+
+const Product = `
+    fragment Product on ProductSearchItem {
+        product {
+            __typename
+            sku
+            description {
+                html
+            }
+            short_description {
+                html
+            }
+            name
+            canonical_url
+            small_image {
+                url
+            }
+            image {
+                url
+            }
+            thumbnail {
+                url
+            }
+            price_range {
+                minimum_price {
+                    fixed_product_taxes {
+                        amount {
+                            value
+                            currency
+                        }
+                        label
+                    }
+                    regular_price {
+                        value
+                        currency
+                    }
+                    final_price {
+                        value
+                        currency
+                    }
+                    discount {
+                        percent_off
+                        amount_off
+                    }
+                }
+                maximum_price {
+                    fixed_product_taxes {
+                        amount {
+                            value
+                            currency
+                        }
+                        label
+                    }
+                    regular_price {
+                        value
+                        currency
+                    }
+                    final_price {
+                        value
+                        currency
+                    }
+                    discount {
+                        percent_off
+                        amount_off
+                    }
+                }
+            }
+        }
+    }
+`;
+
+export { Facet, ProductView, Product };
diff --git a/packages/extensions/venia-pwa-live-search/src/api/graphql.js b/packages/extensions/venia-pwa-live-search/src/api/graphql.js
new file mode 100644
index 0000000000..2d69845830
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/api/graphql.js
@@ -0,0 +1,26 @@
+async function getGraphQL(
+    query = '',
+    variables = {},
+    store = '',
+    baseUrl = ''
+) {
+    const graphqlEndpoint = baseUrl
+        ? `${baseUrl}/graphql`
+        : `${window.origin}/graphql`;
+
+    const response = await fetch(graphqlEndpoint, {
+        method: 'POST',
+        headers: {
+            'Content-Type': 'application/json',
+            Store: store
+        },
+        body: JSON.stringify({
+            query,
+            variables
+        })
+    });
+
+    return response.json();
+}
+
+export { getGraphQL };
diff --git a/packages/extensions/venia-pwa-live-search/src/api/mutations.js b/packages/extensions/venia-pwa-live-search/src/api/mutations.js
new file mode 100644
index 0000000000..2c6eb5edd7
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/api/mutations.js
@@ -0,0 +1,94 @@
+const CREATE_EMPTY_CART = `
+  mutation createEmptyCart($input: createEmptyCartInput) {
+    createEmptyCart(input: $input)
+  }
+`;
+
+const ADD_TO_CART = `
+  mutation addProductsToCart(
+    $cartId: String!
+    $cartItems: [CartItemInput!]!
+  ) {
+      addProductsToCart(
+        cartId: $cartId
+        cartItems: $cartItems
+      ) {
+          cart {
+            items {
+              product {
+                name
+                sku
+              }
+              quantity
+            }
+          }
+          user_errors {
+            code
+            message
+          }
+      }
+  }
+`;
+
+const ADD_TO_WISHLIST = `
+  mutation addProductsToWishlist(
+    $wishlistId: ID!
+    $wishlistItems: [WishlistItemInput!]!
+  ) {
+      addProductsToWishlist(
+        wishlistId: $wishlistId
+        wishlistItems: $wishlistItems
+      ) {
+        wishlist {
+          id
+          name
+          items_count
+          items_v2 {
+            items {
+              id
+              product {
+                uid
+                name
+                sku
+              }
+            }
+          }
+        }
+      }
+  }
+`;
+
+const REMOVE_FROM_WISHLIST = `
+  mutation removeProductsFromWishlist (
+    $wishlistId: ID!
+    $wishlistItemsIds: [ID!]!
+  ) {
+    removeProductsFromWishlist(
+      wishlistId: $wishlistId
+      wishlistItemsIds: $wishlistItemsIds
+    ) {
+        wishlist {
+          id
+          name
+          items_count
+          items_v2 {
+            items {
+              id
+              product {
+                uid
+                name
+                sku
+              }
+            }
+          }
+        }
+      }
+  }
+`;
+
+export {
+    CREATE_EMPTY_CART,
+    ADD_TO_CART,
+    ADD_TO_WISHLIST,
+    REMOVE_FROM_WISHLIST
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/api/queries.js b/packages/extensions/venia-pwa-live-search/src/api/queries.js
new file mode 100644
index 0000000000..09c5bf52da
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/api/queries.js
@@ -0,0 +1,225 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { Facet, Product, ProductView } from './fragments';
+
+const ATTRIBUTE_METADATA_QUERY = `
+    query attributeMetadata {
+        attributeMetadata {
+        sortable {
+            label
+            attribute
+            numeric
+        }
+        filterableInSearch {
+            label
+            attribute
+            numeric
+        }
+        }
+    }
+`;
+
+const QUICK_SEARCH_QUERY = `
+    query quickSearch(
+        $phrase: String!
+        $pageSize: Int = 20
+        $currentPage: Int = 1
+        $filter: [SearchClauseInput!]
+        $sort: [ProductSearchSortInput!]
+        $context: QueryContextInput
+    ) {
+        productSearch(
+            phrase: $phrase
+            page_size: $pageSize
+            current_page: $currentPage
+            filter: $filter
+            sort: $sort
+            context: $context
+        ) {
+            suggestions
+            items {
+                ...Product
+            }
+            page_info {
+                current_page
+                page_size
+                total_pages
+            }
+        }
+    }
+    ${Product}
+`;
+
+const PRODUCT_SEARCH_QUERY = `
+    query productSearch(
+        $phrase: String!
+        $pageSize: Int
+        $currentPage: Int = 1
+        $filter: [SearchClauseInput!]
+        $sort: [ProductSearchSortInput!]
+        $context: QueryContextInput
+    ) {
+        productSearch(
+            phrase: $phrase
+            page_size: $pageSize
+            current_page: $currentPage
+            filter: $filter
+            sort: $sort
+            context: $context
+        ) {
+            total_count
+            items {
+                ...Product
+                ...ProductView
+            }
+            facets {
+                ...Facet
+            }
+            page_info {
+                current_page
+                page_size
+                total_pages
+            }
+        }
+        attributeMetadata {
+            sortable {
+                label
+                attribute
+                numeric
+            }
+        }
+    }
+    ${Product}
+    ${ProductView}
+    ${Facet}
+`;
+
+const REFINE_PRODUCT_QUERY = `
+    query refineProduct(
+        $optionIds: [String!]!
+        $sku: String!
+    ) {
+        refineProduct(
+            optionIds: $optionIds
+            sku: $sku
+        ) {
+            __typename
+            id
+            sku
+            name
+            inStock
+            url
+            urlKey
+            images {
+                label
+                url
+                roles
+            }
+            ... on SimpleProductView {
+                price {
+                    final {
+                        amount {
+                            value
+                        }
+                    }
+                    regular {
+                        amount {
+                            value
+                        }
+                    }
+                }
+            }
+            ... on ComplexProductView {
+                options {
+                    id
+                    title
+                    required
+                    values {
+                        id
+                        title
+                    }
+                }
+                priceRange {
+                    maximum {
+                        final {
+                            amount {
+                                value
+                            }
+                        }
+                        regular {
+                            amount {
+                                value
+                            }
+                        }
+                    }
+                    minimum {
+                        final {
+                            amount {
+                                value
+                            }
+                        }
+                        regular {
+                            amount {
+                                value
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+`;
+
+const GET_CUSTOMER_CART = `
+    query customerCart {
+        customerCart {
+            id
+            items {
+            id
+            product {
+                name
+                sku
+            }
+            quantity
+            }
+        }
+    }
+`;
+
+const GET_CUSTOMER_WISHLISTS = `
+    query customer {
+      customer {
+        wishlists {
+          id
+          name
+          items_count
+          items_v2 {
+            items {
+            id
+              product {
+              uid
+              name
+              sku
+              }
+            }
+          }
+        }
+      }
+    }
+`;
+
+export {
+    ATTRIBUTE_METADATA_QUERY,
+    PRODUCT_SEARCH_QUERY,
+    QUICK_SEARCH_QUERY,
+    REFINE_PRODUCT_QUERY,
+    GET_CUSTOMER_CART,
+    GET_CUSTOMER_WISHLISTS
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/api/search.js b/packages/extensions/venia-pwa-live-search/src/api/search.js
new file mode 100644
index 0000000000..2cba1aa6fe
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/api/search.js
@@ -0,0 +1,222 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { v4 as uuidv4 } from 'uuid';
+
+import { updateSearchInputCtx, updateSearchResultsCtx } from '../context';
+import { SEARCH_UNIT_ID } from '../utils/constants';
+import {
+    ATTRIBUTE_METADATA_QUERY,
+    PRODUCT_SEARCH_QUERY,
+    REFINE_PRODUCT_QUERY
+} from './queries';
+
+const getHeaders = headers => {
+    return {
+        'Magento-Environment-Id': headers.environmentId,
+        'Magento-Website-Code': headers.websiteCode,
+        'Magento-Store-Code': headers.storeCode,
+        'Magento-Store-View-Code': headers.storeViewCode,
+        'X-Api-Key': headers.apiKey,
+        'X-Request-Id': headers.xRequestId,
+        'Content-Type': 'application/json',
+        'Magento-Customer-Group': headers.customerGroup
+    };
+};
+
+const getProductSearch = async ({
+    environmentId,
+    websiteCode,
+    storeCode,
+    storeViewCode,
+    apiKey,
+    apiUrl,
+    phrase,
+    pageSize = 24,
+    displayOutOfStock,
+    currentPage = 1,
+    xRequestId = uuidv4(),
+    filter = [],
+    sort = [],
+    context,
+    categorySearch = false
+}) => {
+    const variables = {
+        phrase,
+        pageSize,
+        currentPage,
+        filter,
+        sort,
+        context
+    };
+
+    // default filters if search is "catalog (category)" or "search"
+    let searchType = 'Search';
+    if (categorySearch) {
+        searchType = 'Catalog';
+    }
+
+    const defaultFilters = {
+        attribute: 'visibility',
+        in: [searchType, 'Catalog, Search']
+    };
+
+    variables.filter.push(defaultFilters); //add default visibility filter
+
+    const displayInStockOnly = displayOutOfStock != '1'; // '!=' is intentional for conversion
+
+    const inStockFilter = {
+        attribute: 'inStock',
+        eq: 'true'
+    };
+
+    if (displayInStockOnly) {
+        variables.filter.push(inStockFilter);
+    }
+
+    const headers = getHeaders({
+        environmentId,
+        websiteCode,
+        storeCode,
+        storeViewCode,
+        apiKey,
+        xRequestId,
+        customerGroup:
+            context && context.customerGroup ? context.customerGroup : ''
+    });
+
+    // ======  initialize data collection =====
+    const searchRequestId = uuidv4();
+
+    updateSearchInputCtx(
+        SEARCH_UNIT_ID,
+        searchRequestId,
+        phrase,
+        filter,
+        pageSize,
+        currentPage,
+        sort
+    );
+
+    const magentoStorefrontEvtPublish = window.magentoStorefrontEvents?.publish;
+
+    if (magentoStorefrontEvtPublish?.searchRequestSent) {
+        magentoStorefrontEvtPublish.searchRequestSent(SEARCH_UNIT_ID);
+    }
+    // ======  end of data collection =====
+
+    const response = await fetch(apiUrl, {
+        method: 'POST',
+        headers,
+        body: JSON.stringify({
+            query: PRODUCT_SEARCH_QUERY,
+            variables: { ...variables }
+        })
+    });
+
+    const results = await response.json();
+    // ======  initialize data collection =====
+    updateSearchResultsCtx(
+        SEARCH_UNIT_ID,
+        searchRequestId,
+        results?.data?.productSearch
+    );
+
+    if (magentoStorefrontEvtPublish?.searchResponseReceived) {
+        magentoStorefrontEvtPublish.searchResponseReceived(SEARCH_UNIT_ID);
+    }
+
+    if (categorySearch) {
+        magentoStorefrontEvtPublish?.categoryResultsView &&
+            magentoStorefrontEvtPublish.categoryResultsView(SEARCH_UNIT_ID);
+    } else {
+        magentoStorefrontEvtPublish?.searchResultsView &&
+            magentoStorefrontEvtPublish.searchResultsView(SEARCH_UNIT_ID);
+    }
+    // ======  end of data collection =====
+
+    return results?.data;
+};
+
+const getAttributeMetadata = async ({
+    environmentId,
+    websiteCode,
+    storeCode,
+    storeViewCode,
+    apiKey,
+    apiUrl,
+    xRequestId = uuidv4()
+}) => {
+    const headers = getHeaders({
+        environmentId,
+        websiteCode,
+        storeCode,
+        storeViewCode,
+        apiKey,
+        xRequestId,
+        customerGroup: ''
+    });
+
+    try {
+        const response = await fetch(apiUrl, {
+            method: 'POST',
+            headers,
+            body: JSON.stringify({
+                query: ATTRIBUTE_METADATA_QUERY
+            })
+        });
+        const results = await response.json();
+        return results?.data;
+    } catch (error) {
+        console.error('Metadata fetch failed:', error);
+    }
+};
+
+const refineProductSearch = async ({
+    environmentId,
+    websiteCode,
+    storeCode,
+    storeViewCode,
+    apiKey,
+    apiUrl,
+    xRequestId = uuidv4(),
+    context,
+    optionIds,
+    sku
+}) => {
+    const variables = {
+        optionIds,
+        sku
+    };
+
+    const headers = getHeaders({
+        environmentId,
+        websiteCode,
+        storeCode,
+        storeViewCode,
+        apiKey,
+        xRequestId,
+        customerGroup:
+            context && context.customerGroup ? context.customerGroup : ''
+    });
+
+    const response = await fetch(apiUrl, {
+        method: 'POST',
+        headers,
+        body: JSON.stringify({
+            query: REFINE_PRODUCT_QUERY,
+            variables: { ...variables }
+        })
+    });
+
+    const results = await response.json();
+    return results?.data;
+};
+
+export { getAttributeMetadata, getProductSearch, refineProductSearch };
diff --git a/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/AddToCartButton.jsx b/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/AddToCartButton.jsx
new file mode 100644
index 0000000000..07060b2a60
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/AddToCartButton.jsx
@@ -0,0 +1,32 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+import CartIcon from '../../icons/cart.svg';
+
+const AddToCartButton = ({ onClick }) => {
+  return (
+    <div className="ds-sdk-add-to-cart-button">
+      <button
+        className="flex items-center justify-center text-white text-sm rounded-full h-[32px] w-full p-sm"
+        style={{
+          backgroundColor: '#464646'
+        }}
+        onClick={onClick}
+      >
+        <img src={CartIcon} className="w-[24px] pr-4" />
+        {/* <CartIcon className="w-[24px] pr-4" /> */}
+        Add To Cart
+      </button>
+    </div>
+  );
+};
+
+export default AddToCartButton;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/AddToCartButton.stories.mdx b/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/AddToCartButton.stories.mdx
new file mode 100644
index 0000000000..bf49d90adf
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/AddToCartButton.stories.mdx
@@ -0,0 +1,14 @@
+import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs';
+import { action } from '@storybook/addon-actions';
+import AddToCartButton from '../AddToCartButton';
+
+<Meta
+  title="PLP/AddToCartButton"
+  component={AddToCartButton}
+  parameters={{ layout: 'centered' }}
+/>
+
+export const Template = (args) => <AddToCartButton {...args} />;
+
+# AddToCartButton
+
diff --git a/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/index.js b/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/index.js
new file mode 100644
index 0000000000..00d90f86c2
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/AddToCartButton/index.js
@@ -0,0 +1,10 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export { default } from './AddToCartButton';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Alert/Alert.jsx b/packages/extensions/venia-pwa-live-search/src/components/Alert/Alert.jsx
new file mode 100644
index 0000000000..a497f52364
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Alert/Alert.jsx
@@ -0,0 +1,155 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import Checkmark from '../../icons/checkmark.svg';
+import Error from '../../icons/error.svg';
+import Info from '../../icons/info.svg';
+import Warning from '../../icons/warning.svg';
+import X from '../../icons/x.svg';
+
+export const Alert = ({ title, type, description, url, onClick }) => {
+  return (
+    <div className="mx-auto max-w-8xl">
+      {(() => {
+        switch (type) {
+          case 'error':
+            return (
+              <div className="rounded-md bg-red-50 p-4">
+                <div className="flex items-center">
+                  <div className="flex-shrink-0 p-1">
+                    <img src={Error} className="h-5 w-5 text-red-400" aria-hidden="true" />
+                    {/* <Error
+                      className="h-5 w-5 text-red-400"
+                      aria-hidden="true"
+                    /> */}
+                  </div>
+                  <div className="ml-3">
+                    <h3 className="text-sm font-medium text-red-800">
+                      {title}
+                    </h3>
+                    {description?.length > 0 && (
+                      <div className="mt-2 text-sm text-red-700">
+                        <p>{description}</p>
+                      </div>
+                    )}
+                  </div>
+                </div>
+              </div>
+            );
+          case 'warning':
+            return (
+              <div className="rounded-md bg-yellow-50 p-4">
+                <div className="flex items-center">
+                  <div className="flex-shrink-0 p-1">
+                    <img src={Warning} className="h-5 w-5 text-yellow-400" aria-hidden="true" />
+                    {/* <Warning
+                      className="h-5 w-5 text-yellow-400"
+                      aria-hidden="true"
+                    /> */}
+                  </div>
+                  <div className="ml-3">
+                    <h3 className="text-sm font-medium text-yellow-800">
+                      {title}
+                    </h3>
+                    {description?.length > 0 && (
+                      <div className="mt-2 text-sm text-yellow-700">
+                        <p>{description}</p>
+                      </div>
+                    )}
+                  </div>
+                </div>
+              </div>
+            );
+          case 'info':
+            return (
+              <div className="rounded-md bg-blue-50 p-4">
+                <div className="flex items-center">
+                  <div className="flex-shrink-0 p-1">
+                    <img src={Info} className="h-5 w-5 text-blue-400" aria-hidden="true" />
+                    {/* <Info
+                      className="h-5 w-5 text-blue-400"
+                      aria-hidden="true"
+                    /> */}
+                  </div>
+                  <div className="ml-3 flex-1 md:flex md:justify-between">
+                    <div>
+                      <h3 className="text-sm font-medium text-blue-800">
+                        {title}
+                      </h3>
+                      {description?.length > 0 && (
+                        <div className="mt-2 text-sm text-blue-700">
+                          <p>{description}</p>
+                        </div>
+                      )}
+                    </div>
+                    {url && (
+                      <div className="mt-4 text-sm md:ml-6">
+                        <a
+                          href={url}
+                          className="whitespace-nowrap font-medium text-blue-700 hover:text-blue-600"
+                        >
+                          Details
+                          <span aria-hidden="true">&rarr;</span>
+                        </a>
+                      </div>
+                    )}
+                  </div>
+                </div>
+              </div>
+            );
+          case 'success':
+            return (
+              <div className="rounded-md bg-green-50 p-4">
+                <div className="flex items-center">
+                  <div className="flex-shrink-0 p-1">
+                  <img src={Checkmark} alt="Success" className="h-5 w-5 text-green-400" aria-hidden="true" />
+                    {/* <Checkmark
+                      className="h-5 w-5 text-green-400"
+                      aria-hidden="true"
+                    /> */}
+                  </div>
+                  <div className="ml-3">
+                    <h3 className="text-sm font-medium text-green-800">
+                      {title}
+                    </h3>
+                    {description?.length > 0 && (
+                      <div className="mt-2 text-sm text-green-700">
+                        <p>{description}</p>
+                      </div>
+                    )}
+                  </div>
+                  {onClick && (
+                    <div className="ml-auto">
+                      <div className="md:ml-6">
+                        <button
+                          type="button"
+                          className="inline-flex rounded-md bg-green-50 p-1.5 text-green-500 ring-off hover:bg-green-100 focus:outline-none focus:ring-2 focus:ring-green-600 focus:ring-offset-2 focus:ring-offset-green-50"
+                          onClick={onClick}
+                        >
+                          <span className="sr-only">Dismiss</span>
+                          <img src={X} className="h-5 w-5" aria-hidden="true" />
+                          {/* <X
+                            className="h-5 w-5"
+                            aria-hidden="true"
+                          /> */}
+                        </button>
+                      </div>
+                    </div>
+                  )}
+                </div>
+              </div>
+            );
+          default:
+            return null;
+        }
+      })()}
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Alert/index.js b/packages/extensions/venia-pwa-live-search/src/components/Alert/index.js
new file mode 100644
index 0000000000..42e633dde6
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Alert/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Alert';
+export { Alert as default } from './Alert';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/Breadcrumbs.jsx b/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/Breadcrumbs.jsx
new file mode 100644
index 0000000000..9e012c9d44
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/Breadcrumbs.jsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import Chevron from '../../icons/chevron.svg';
+
+export const Breadcrumbs = ({ pages }) => {
+  return (
+    <nav className="ds-sdk-breadcrumbs flex" aria-label="Breadcrumbs">
+      <ol role="list" className="flex column items-center space-x-2">
+        {pages.map((page, index) => (
+          <li key={page.name} className="ds-sdk-breadcrumbs__item">
+            <div className="flex items-center">
+              {index > 0 && (
+                <Chevron className="h-sm w-sm transform -rotate-90 stroke-gray-400" />
+              )}
+
+              <a
+                href={page.href}
+                className={`ml-2 text-sm font-normal hover:text-gray-900 first:ml-0 ${
+                  page.current
+                    ? 'ds-sdk-breadcrumbs__item--current text-gray-500 font-light'
+                    : 'text-black'
+                }`}
+                aria-current={page.current ? 'page' : undefined}
+              >
+                {page.name}
+              </a>
+            </div>
+          </li>
+        ))}
+      </ol>
+    </nav>
+  );
+};
+
+export default Breadcrumbs;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/MockPages.js b/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/MockPages.js
new file mode 100644
index 0000000000..a470afaf4a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/MockPages.js
@@ -0,0 +1,14 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const pages = [
+    { name: 'Category I', href: '#', current: false },
+    { name: 'Category II', href: '#', current: false },
+    { name: 'Category III', href: '#', current: true }
+];
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/index.js b/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/index.js
new file mode 100644
index 0000000000..7cc8ca16ce
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Breadcrumbs/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Breadcrumbs';
+export { Breadcrumbs as default } from './Breadcrumbs';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/ButtonShimmer.css b/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/ButtonShimmer.css
new file mode 100644
index 0000000000..19b0c55ea1
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/ButtonShimmer.css
@@ -0,0 +1,32 @@
+@keyframes placeholderShimmer {
+    0% {
+        background-position: calc(100vw + 40px);
+    }
+
+    100% {
+        background-position: calc(100vw - 40px);
+    }
+}
+
+.shimmer-animation-button {
+    background-color: #f6f7f8;
+    background-image: linear-gradient(
+        to right,
+        #f6f7f8 0%,
+        #edeef1 20%,
+        #f6f7f8 40%,
+        #f6f7f8 100%
+    );
+    background-repeat: no-repeat;
+    background-size: 100vw 4rem;
+    animation-duration: 1s;
+    animation-fill-mode: forwards;
+    animation-iteration-count: infinite;
+    animation-name: placeholderShimmer;
+    animation-timing-function: linear;
+}
+
+.ds-plp-facets__button {
+    height: 3rem;
+    width: 160px;
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/ButtonShimmer.jsx b/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/ButtonShimmer.jsx
new file mode 100644
index 0000000000..aa2a35acdd
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/ButtonShimmer.jsx
@@ -0,0 +1,23 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import '../ButtonShimmer/ButtonShimmer.css';
+import React from 'react';
+
+export const ButtonShimmer = () => {
+  return (
+    <>
+      <div className="ds-plp-facets ds-plp-facets--loading">
+        <div className="ds-plp-facets__button shimmer-animation-button" />
+      </div>
+    </>
+  );
+};
+
+//export default ButtonShimmer;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/index.js b/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/index.js
new file mode 100644
index 0000000000..42ac21f6fb
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ButtonShimmer/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './ButtonShimmer';
+export { ButtonShimmer as default } from './ButtonShimmer';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/CategoryFilters/CategoryFilters.jsx b/packages/extensions/venia-pwa-live-search/src/components/CategoryFilters/CategoryFilters.jsx
new file mode 100644
index 0000000000..925dd76aeb
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/CategoryFilters/CategoryFilters.jsx
@@ -0,0 +1,59 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { useTranslation } from '../../context/translation';
+import { Facets } from '../Facets';
+import { FilterButton } from '../FilterButton';
+
+export const CategoryFilters = ({
+  loading,
+  pageLoading,
+  totalCount,
+  facets,
+  categoryName,
+  phrase,
+  setShowFilters,
+  filterCount,
+}) => {
+  const translation = useTranslation();
+  let title = categoryName || '';
+  if (phrase) {
+    const text = translation.CategoryFilters.results;
+    title = text.replace('{phrase}', `"${phrase}"`);
+  }
+  const resultsTranslation = translation.CategoryFilters.products;
+  const results = resultsTranslation.replace('{totalCount}', `${totalCount}`);
+
+  return (
+    <div className="sm:flex ds-widgets-_actions relative max-w-[21rem] w-full h-full px-2 flex-col overflow-y-auto">
+      <div className="ds-widgets_actions_header flex justify-between items-center mb-md">
+        {title && <span> {title}</span>}
+        {!loading && <span className="text-primary text-sm">{results}</span>}
+      </div>
+
+      {!pageLoading && facets.length > 0 && (
+        <>
+          <div className="flex pb-4 w-full h-full">
+            <FilterButton
+              displayFilter={() => setShowFilters(false)}
+              type="desktop"
+              title={`${translation.Filter.hideTitle}${
+                filterCount > 0 ? ` (${filterCount})` : ''
+              }`}
+            />
+          </div>
+          <Facets searchFacets={facets} />
+        </>
+      )}
+    </div>
+  );
+};
+
+export default CategoryFilters;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/CategoryFilters/index.js b/packages/extensions/venia-pwa-live-search/src/components/CategoryFilters/index.js
new file mode 100644
index 0000000000..faaa9ce84a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/CategoryFilters/index.js
@@ -0,0 +1,10 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './CategoryFilters';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/Facets.jsx b/packages/extensions/venia-pwa-live-search/src/components/Facets/Facets.jsx
new file mode 100644
index 0000000000..fcecf52721
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/Facets.jsx
@@ -0,0 +1,50 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+import { useStore } from '../../context';
+import RangeFacet from './Range/RangeFacet';
+import ScalarFacet from './Scalar/ScalarFacet';
+import SliderDoubleControl from '../SliderDoubleControl';
+
+export const Facets = ({ searchFacets }) => {
+  const {
+    config: { priceSlider },
+  } = useStore();
+
+  return (
+    <div className="ds-plp-facets flex flex-col">
+      <form className="ds-plp-facets__list border-t border-gray-200">
+        {searchFacets?.map((facet) => {
+          const bucketType = facet?.buckets[0]?.__typename;
+          switch (bucketType) {
+            case 'ScalarBucket':
+              return <ScalarFacet key={facet.attribute} filterData={facet} />;
+            case 'RangeBucket':
+              return priceSlider ? (
+                <SliderDoubleControl filterData={facet} />
+              ) : (
+                <RangeFacet
+                  key={facet.attribute}
+                  filterData={facet}
+                />
+              );
+            case 'CategoryView':
+              return <ScalarFacet key={facet.attribute} filterData={facet} />;
+            default:
+              return null;
+          }
+        })}
+      </form>
+    </div>
+  );
+};
+
+export default Facets;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/Range/RangeFacet.js b/packages/extensions/venia-pwa-live-search/src/components/Facets/Range/RangeFacet.js
new file mode 100644
index 0000000000..ee53082011
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/Range/RangeFacet.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import useRangeFacet from '../../../hooks/useRangeFacet';
+import { InputButtonGroup } from '../../InputButtonGroup';
+
+const RangeFacet = ({ filterData }) => {
+    const { isSelected, onChange } = useRangeFacet(filterData);
+
+    return (
+        <InputButtonGroup
+            title={filterData.title}
+            attribute={filterData.attribute}
+            buckets={filterData.buckets}
+            type="radio"
+            isSelected={isSelected}
+            onChange={e => onChange(e.value)}
+        />
+    );
+};
+
+export default RangeFacet;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/Scalar/ScalarFacet.js b/packages/extensions/venia-pwa-live-search/src/components/Facets/Scalar/ScalarFacet.js
new file mode 100644
index 0000000000..5efaf3342d
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/Scalar/ScalarFacet.js
@@ -0,0 +1,29 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { InputButtonGroup } from '../../InputButtonGroup';
+import useScalarFacet from '../../../hooks/useScalarFacet';
+
+const ScalarFacet = ({ filterData }) => {
+    const { isSelected, onChange } = useScalarFacet(filterData);
+
+    return (
+        <InputButtonGroup
+            title={filterData.title}
+            attribute={filterData.attribute}
+            buckets={filterData.buckets}
+            type="checkbox"
+            isSelected={isSelected}
+            onChange={args => onChange(args.value, args.selected)}
+        />
+    );
+};
+
+export default ScalarFacet;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/SelectedFilters.js b/packages/extensions/venia-pwa-live-search/src/components/Facets/SelectedFilters.js
new file mode 100644
index 0000000000..e562153b1a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/SelectedFilters.js
@@ -0,0 +1,80 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+import React from 'react';
+import { useSearch, useProducts, useTranslation } from '../../context';
+import Pill from '../Pill';
+import { formatBinaryLabel, formatRangeLabel } from './format';
+
+const SelectedFilters = () => {
+    const searchCtx = useSearch();
+    const productsCtx = useProducts();
+    const translation = useTranslation();
+
+    return (
+        <div className="w-full h-full">
+            {searchCtx.filters?.length > 0 && (
+                <div className="ds-plp-facets__pills pb-6 sm:pb-6 flex flex-wrap mt-8 justify-start">
+                    {searchCtx.filters.map(filter => (
+                        <div key={filter.attribute}>
+                            {filter.in?.map(option => (
+                                <Pill
+                                    key={formatBinaryLabel(
+                                        filter,
+                                        option,
+                                        searchCtx.categoryNames,
+                                        productsCtx.categoryPath
+                                    )}
+                                    label={formatBinaryLabel(
+                                        filter,
+                                        option,
+                                        searchCtx.categoryNames,
+                                        productsCtx.categoryPath
+                                    )}
+                                    type="transparent"
+                                    onClick={() =>
+                                        searchCtx.updateFilterOptions(
+                                            filter,
+                                            option
+                                        )
+                                    }
+                                />
+                            ))}
+                            {filter.range && (
+                                <Pill
+                                    label={formatRangeLabel(
+                                        filter,
+                                        productsCtx.currencyRate,
+                                        productsCtx.currencySymbol
+                                    )}
+                                    type="transparent"
+                                    onClick={() => {
+                                        searchCtx.removeFilter(
+                                            filter.attribute
+                                        );
+                                    }}
+                                />
+                            )}
+                        </div>
+                    ))}
+                    <div className="py-1">
+                        <button
+                            className="ds-plp-facets__header__clear-all border-none bg-transparent hover:border-none	hover:bg-transparent
+              focus:border-none focus:bg-transparent active:border-none active:bg-transparent active:shadow-none text-sm px-4"
+                            onClick={() => searchCtx.clearFilters()}
+                        >
+                            {translation.Filter.clearAll}
+                        </button>
+                    </div>
+                </div>
+            )}
+        </div>
+    );
+};
+
+export default SelectedFilters;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/format.js b/packages/extensions/venia-pwa-live-search/src/components/Facets/format.js
new file mode 100644
index 0000000000..6794e5a861
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/format.js
@@ -0,0 +1,52 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+const formatRangeLabel = (filter, currencyRate = '1', currencySymbol = '$') => {
+    const range = filter.range;
+
+    const rate = currencyRate;
+    const symbol = currencySymbol;
+    const label = `${symbol}${
+        range?.from && parseFloat(rate) * parseInt(range.from.toFixed(0), 10)
+            ? (
+                  parseFloat(rate) * parseInt(range.from?.toFixed(0), 10)
+              )?.toFixed(2)
+            : 0
+    }${
+        range?.to && parseFloat(rate) * parseInt(range.to.toFixed(0), 10)
+            ? ` - ${symbol}${(
+                  parseFloat(rate) * parseInt(range.to.toFixed(0), 10)
+              ).toFixed(2)}`
+            : ' and above'
+    }`;
+    return label;
+};
+
+const formatBinaryLabel = (filter, option, categoryNames, categoryPath) => {
+    if (categoryPath && categoryNames) {
+        const category = categoryNames.find(
+            facet =>
+                facet.attribute === filter.attribute && facet.value === option
+        );
+
+        if (category?.name) {
+            return category.name;
+        }
+    }
+
+    const title = filter.attribute?.split('_');
+    if (option === 'yes') {
+        return title.join(' ');
+    } else if (option === 'no') {
+        return `not ${title.join(' ')}`;
+    }
+    return option;
+};
+
+export { formatBinaryLabel, formatRangeLabel };
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/index.js b/packages/extensions/venia-pwa-live-search/src/components/Facets/index.js
new file mode 100644
index 0000000000..3056ca7738
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/index.js
@@ -0,0 +1,14 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Facets';
+export { default as SelectedFilters } from './SelectedFilters';
+export * from './Range/RangeFacet';
+export * from './Scalar/ScalarFacet';
+export { Facets as default } from './Facets';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Facets/mocks.js b/packages/extensions/venia-pwa-live-search/src/components/Facets/mocks.js
new file mode 100644
index 0000000000..5cdced8573
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Facets/mocks.js
@@ -0,0 +1,119 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+const colorBuckets = [
+    {
+        count: 5,
+        title: 'Green',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 4,
+        title: 'Black',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 3,
+        title: 'Blue',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 2,
+        title: 'Gray',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 1,
+        title: 'Pink',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 0,
+        title: 'Yellow',
+        __typename: 'ScalarBucket'
+    }
+];
+
+const sizeBuckets = [
+    {
+        count: 2,
+        title: '32',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 2,
+        title: '33',
+        __typename: 'ScalarBucket'
+    },
+    {
+        count: 1,
+        title: 'L',
+        __typename: 'ScalarBucket'
+    }
+];
+
+const priceBuckets = [
+    {
+        title: '0.0-25.0',
+        __typename: 'RangeBucket',
+        from: 0,
+        to: 25,
+        count: 45
+    },
+    {
+        title: '25.0-50.0',
+        __typename: 'RangeBucket',
+        from: 25,
+        to: 50,
+        count: 105
+    },
+    {
+        title: '75.0-100.0',
+        __typename: 'RangeBucket',
+        from: 75,
+        to: 100,
+        count: 6
+    },
+    {
+        title: '200.0-225.0',
+        __typename: 'RangeBucket',
+        from: 200,
+        to: 225,
+        count: 2
+    }
+];
+
+export const mockFilters = [
+    {
+        title: 'Color',
+        attribute: 'color',
+        buckets: colorBuckets,
+        __typename: 'ScalarBucket'
+    },
+    {
+        title: 'Size',
+        attribute: 'size',
+        buckets: sizeBuckets,
+        __typename: 'ScalarBucket'
+    }
+];
+
+export const mockColorFilter = {
+    title: 'Color',
+    attribute: 'color',
+    buckets: colorBuckets,
+    __typename: 'ScalarBucket'
+};
+
+export const mockPriceFilter = {
+    title: 'Price',
+    attribute: 'price',
+    buckets: priceBuckets,
+    __typename: 'RangeBucket'
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/FacetsShimmer.css b/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/FacetsShimmer.css
new file mode 100644
index 0000000000..e80eef8239
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/FacetsShimmer.css
@@ -0,0 +1,49 @@
+@keyframes placeholderShimmer {
+    0% {
+        background-position: calc(-100vw + 40px); /* 40px offset */
+    }
+    100% {
+        background-position: calc(100vw - 40px); /* 40px offset */
+    }
+}
+
+.shimmer-animation-facet {
+    background-color: #f6f7f8;
+    background-image: linear-gradient(
+        to right,
+        #f6f7f8 0%,
+        #edeef1 20%,
+        #f6f7f8 40%,
+        #f6f7f8 100%
+    );
+    background-repeat: no-repeat;
+    background-size: 100vw 4rem;
+    animation-duration: 1s;
+    animation-fill-mode: forwards;
+    animation-iteration-count: infinite;
+    animation-name: placeholderShimmer;
+    animation-timing-function: linear;
+}
+
+.ds-sdk-input__header {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 1rem;
+    margin-top: 0.75rem;
+}
+
+.ds-sdk-input__title {
+    height: 2.5rem;
+    flex: 0 0 auto;
+    width: 50%;
+}
+
+.ds-sdk-input__item {
+    height: 2rem;
+    width: 80%;
+    margin-bottom: 0.3125rem;
+}
+
+.ds-sdk-input__item:last-child {
+    margin-bottom: 0;
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/FacetsShimmer.jsx b/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/FacetsShimmer.jsx
new file mode 100644
index 0000000000..242ad19970
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/FacetsShimmer.jsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import './FacetsShimmer.css';
+
+export const FacetsShimmer = () => {
+  return (
+    <>
+      <div className="ds-sdk-input ds-sdk-input--loading">
+        <div className="ds-sdk-input__content">
+          <div className="ds-sdk-input__header">
+            <div className="ds-sdk-input__title shimmer-animation-facet" />
+          </div>
+          <div className="ds-sdk-input__list">
+            <div className="ds-sdk-input__item shimmer-animation-facet" />
+            <div className="ds-sdk-input__item shimmer-animation-facet" />
+            <div className="ds-sdk-input__item shimmer-animation-facet" />
+            <div className="ds-sdk-input__item shimmer-animation-facet" />
+          </div>
+        </div>
+      </div>
+      <div className="ds-sdk-input__border border-t mt-md border-gray-200" />
+    </>
+  );
+};
+
+//export default FacetsShimmer;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/index.js b/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/index.js
new file mode 100644
index 0000000000..a97bbb3993
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/FacetsShimmer/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './FacetsShimmer';
+export { FacetsShimmer as default } from './FacetsShimmer';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/FilterButton/FilterButton.jsx b/packages/extensions/venia-pwa-live-search/src/components/FilterButton/FilterButton.jsx
new file mode 100644
index 0000000000..614aa30245
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/FilterButton/FilterButton.jsx
@@ -0,0 +1,40 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { useTranslation } from '../../context/translation';
+import AdjustmentsIcon from '../../icons/adjustments.svg';
+
+export const FilterButton = ({ displayFilter, type, title }) => {
+  const translation = useTranslation();
+
+  return type === 'mobile' ? (
+    <div className="ds-sdk-filter-button">
+      <button
+        className="flex items-center bg-gray-100 ring-black ring-opacity-5 rounded-md p-sm outline outline-gray-200 hover:outline-gray-800 h-[32px]"
+        onClick={displayFilter}
+      >
+        {/* <AdjustmentsIcon className="w-md" /> */}
+        <img src={AdjustmentsIcon} className={`w-md`} />
+        {translation.Filter.title}
+      </button>
+    </div>
+  ) : (
+    <div className="ds-sdk-filter-button-desktop">
+      <button
+        className="flex items-center bg-gray-100 ring-black ring-opacity-5 rounded-md p-sm text-sm h-[32px]"
+        onClick={displayFilter}
+      >
+        {title}
+      </button>
+    </div>
+  );
+};
+
+export default FilterButton;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/FilterButton/index.js b/packages/extensions/venia-pwa-live-search/src/components/FilterButton/index.js
new file mode 100644
index 0000000000..7b5bcdd180
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/FilterButton/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './FilterButton';
+export { default as FilterButton } from './FilterButton';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/Image.jsx b/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/Image.jsx
new file mode 100644
index 0000000000..674d909519
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/Image.jsx
@@ -0,0 +1,34 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { useIntersectionObserver } from '../../utils/useIntersectionObserver';
+
+export const Image = ({
+  image,
+  alt,
+  carouselIndex,
+  index,
+}) => {
+  const imageRef = useRef(null);
+  const [imageUrl, setImageUrl] = useState('');
+  const [isVisible, setIsVisible] = useState(false);
+  const entry = useIntersectionObserver(imageRef, { rootMargin: '200px' });
+
+  useEffect(() => {
+    if (!entry) return;
+
+    if (entry?.isIntersecting && index === carouselIndex) {
+      setIsVisible(true);
+      setImageUrl(entry?.target?.dataset.src || '');
+    }
+  }, [entry, carouselIndex, index, image]);
+
+  return (
+    <img
+      className={`aspect-auto w-100 h-auto ${isVisible ? 'visible' : 'invisible'}`}
+      ref={imageRef}
+      src={imageUrl}
+      data-src={typeof image === 'object' ? image.src : image}
+      srcSet={typeof image === 'object' ? image.srcset : null}
+      alt={alt}
+    />
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/ImageCarousel.jsx b/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/ImageCarousel.jsx
new file mode 100644
index 0000000000..fd0d06edd4
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/ImageCarousel.jsx
@@ -0,0 +1,103 @@
+import React, { useState } from 'react';
+import { Image } from './Image';
+
+export const ImageCarousel = ({
+  images,
+  productName,
+  carouselIndex,
+  setCarouselIndex,
+}) => {
+  const [swipeIndex, setSwipeIndex] = useState(0);
+
+  const cirHandler = (index) => {
+    setCarouselIndex(index);
+  };
+
+  const prevHandler = () => {
+    if (carouselIndex === 0) {
+      setCarouselIndex(0);
+    } else {
+      setCarouselIndex((prev) => prev - 1);
+    }
+  };
+
+  const nextHandler = () => {
+    if (carouselIndex === images.length - 1) {
+      setCarouselIndex(0);
+    } else {
+      setCarouselIndex((prev) => prev + 1);
+    }
+  };
+
+  return (
+    <div className="ds-sdk-product-image-carousel max-h-[250px] max-w-2xl m-auto">
+      <div
+        className="flex flex-nowrap overflow-hidden relative rounded-lg w-full h-full"
+        onTouchStart={(e) => setSwipeIndex(e.touches[0].clientX)}
+        onTouchEnd={(e) => {
+          const endIndex = e.changedTouches[0].clientX;
+          if (swipeIndex > endIndex) {
+            nextHandler();
+          } else if (swipeIndex < endIndex) {
+            prevHandler();
+          }
+        }}
+      >
+        <div className="overflow-hidden relative max-w-[200px]">
+          <div
+            className={`flex transition ease-out duration-40`}
+            style={{
+              transform: `translateX(-${carouselIndex * 100}%)`,
+            }}
+          >
+            {images.map((item, index) => {
+              return (
+                <Image
+                  image={item}
+                  carouselIndex={carouselIndex}
+                  index={index}
+                  key={index}
+                  alt={productName}
+                />
+              );
+            })}
+          </div>
+        </div>
+      </div>
+      {images.length > 1 && (
+        <div className="absolute z-1 flex space-x-3 -translate-x-1/2 bottom-0 left-1/2 pb-2 ">
+          {images.map((_item, index) => {
+            return (
+              <span
+                key={index}
+                style={
+                  carouselIndex === index
+                    ? {
+                        width: `12px`,
+                        height: `12px`,
+                        borderRadius: `50%`,
+                        border: `1px solid black`,
+                        cursor: `pointer`,
+                        backgroundColor: `#252525`,
+                      }
+                    : {
+                        width: `12px`,
+                        height: `12px`,
+                        borderRadius: `50%`,
+                        border: `1px solid silver`,
+                        cursor: `pointer`,
+                        backgroundColor: `silver`,
+                      }
+                }
+                onClick={(e) => {
+                  e.preventDefault();
+                  cirHandler(index);
+                }}
+              />
+            );
+          })}
+        </div>
+      )}
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/index.js b/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/index.js
new file mode 100644
index 0000000000..7df3a738ce
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ImageCarousel/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './ImageCarousel';
+export { ImageCarousel as default } from './ImageCarousel';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/InputButtonGroup/InputButtonGroup.jsx b/packages/extensions/venia-pwa-live-search/src/components/InputButtonGroup/InputButtonGroup.jsx
new file mode 100644
index 0000000000..600151a420
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/InputButtonGroup/InputButtonGroup.jsx
@@ -0,0 +1,120 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useState } from 'react';
+
+import { useProducts, useTranslation } from '../../context';
+import PlusIcon from '../../icons/plus.svg';
+import { BOOLEAN_NO, BOOLEAN_YES } from '../../utils/constants';
+import { LabelledInput } from '../LabelledInput';
+
+const numberOfOptionsShown = 5;
+
+const InputButtonGroup = ({
+  title,
+  attribute,
+  buckets,
+  isSelected,
+  onChange,
+  type,
+  inputGroupTitleSlot
+}) => {
+  const translation = useTranslation();
+  const productsCtx = useProducts();
+
+  const [showMore, setShowMore] = useState(buckets.length < numberOfOptionsShown);
+
+  const numberOfOptions = showMore ? buckets.length : numberOfOptionsShown;
+
+  const onInputChange = (title, e) => {
+    onChange({
+      value: title,
+      selected: e?.target?.checked
+    });
+  };
+
+  const formatLabel = (title, bucket) => {
+    if (bucket.__typename === 'RangeBucket') {
+      const currencyRate = productsCtx.currencyRate || '1';
+      const currencySymbol = productsCtx.currencySymbol || '$';
+      const from = bucket?.from
+        ? (parseFloat(currencyRate) * parseInt(bucket.from.toFixed(0), 10)).toFixed(2)
+        : 0;
+      const to = bucket?.to
+        ? ` - ${currencySymbol}${(
+            parseFloat(currencyRate) * parseInt(bucket.to.toFixed(0), 10)
+          ).toFixed(2)}`
+        : translation.InputButtonGroup.priceRange;
+      return `${currencySymbol}${from}${to}`;
+    } else if (bucket.__typename === 'CategoryView') {
+      return productsCtx.categoryPath ? (bucket.name !== undefined && bucket.name !== null ? bucket.name : bucket.title) : bucket.title;
+    } else if (bucket.title === BOOLEAN_YES) {
+      return title;
+    } else if (bucket.title === BOOLEAN_NO) {
+      const excludedMessageTranslation = translation.InputButtonGroup.priceExcludedMessage;
+      const excludedMessage = excludedMessageTranslation.replace('{title}', `${title}`);
+      return excludedMessage;
+    }
+    return bucket.title;
+  };
+
+  return (
+    <div className="ds-sdk-input pt-md">
+      {inputGroupTitleSlot ? (
+        inputGroupTitleSlot(title)
+      ) : (
+        <label className="ds-sdk-input__label text-base font-normal text-gray-900">
+          {title}
+        </label>
+      )}
+      <fieldset className="ds-sdk-input__options mt-md">
+        <div className="space-y-4">
+          {buckets.slice(0, numberOfOptions).map((option) => {
+            if (!option.title) {
+              return null;
+            }
+            const checked = isSelected(option.title);
+            const noShowPriceBucketCount = option.__typename === 'RangeBucket';
+            return (
+              <LabelledInput
+                key={formatLabel(title, option)}
+                name={`${option.title}-${attribute}`}
+                attribute={attribute}
+                label={formatLabel(title, option)}
+                checked={!!checked}
+                value={option.title}
+                count={noShowPriceBucketCount ? null : option.count}
+                onChange={(e) => onInputChange(option.title, e)}
+                type={type}
+              />
+            );
+          })}
+          {!showMore && buckets.length > numberOfOptionsShown && (
+            <div
+              className="ds-sdk-input__fieldset__show-more flex items-center text-gray-700 cursor-pointer"
+              onClick={() => setShowMore(true)}
+            >
+              <img src={PlusIcon} height="16px" width="16px" className="h-md w-md fill-gray-500" />
+              {/* <PlusIcon className="h-md w-md fill-gray-500" /> */}
+              <button
+                type="button"
+                className="ml-sm font-light cursor-pointer border-none bg-transparent hover:border-none hover:bg-transparent focus:border-none focus:bg-transparent active:border-none active:bg-transparent active:shadow-none text-sm"
+              >
+                {translation.InputButtonGroup.showmore}
+              </button>
+            </div>
+          )}
+        </div>
+      </fieldset>
+      <div className="ds-sdk-input__border border-t mt-md border-gray-200" />
+    </div>
+  );
+};
+
+export default InputButtonGroup;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/InputButtonGroup/index.js b/packages/extensions/venia-pwa-live-search/src/components/InputButtonGroup/index.js
new file mode 100644
index 0000000000..9444af2603
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/InputButtonGroup/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './InputButtonGroup';
+export { default as InputButtonGroup } from './InputButtonGroup';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/LabelledInput/LabelledInput.jsx b/packages/extensions/venia-pwa-live-search/src/components/LabelledInput/LabelledInput.jsx
new file mode 100644
index 0000000000..adc2aa6642
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/LabelledInput/LabelledInput.jsx
@@ -0,0 +1,51 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+export const LabelledInput = ({
+  type,
+  checked,
+  onChange,
+  name,
+  label,
+  attribute,
+  value,
+  count,
+}) => {
+  return (
+    <div className="ds-sdk-labelled-input flex items-center">
+      <input
+        id={name}
+        name={
+          type === 'checkbox'
+            ? `checkbox-group-${attribute}`
+            : `radio-group-${attribute}`
+        }
+        type={type}
+        className="ds-sdk-labelled-input__input focus:ring-0 h-md w-md border-0 cursor-pointer accent-gray-600 min-w-[16px]"
+        checked={checked}
+        aria-checked={checked}
+        onChange={onChange}
+        value={value}
+      />
+      <label
+        htmlFor={name}
+        className="ds-sdk-labelled-input__label ml-sm block-display text-sm font-light text-gray-700 cursor-pointer"
+      >
+        {label}
+        {count != null && (
+          <span className="text-[12px] font-light text-gray-700 ml-1">
+            {`(${count})`}
+          </span>
+        )}
+      </label>
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/LabelledInput/index.js b/packages/extensions/venia-pwa-live-search/src/components/LabelledInput/index.js
new file mode 100644
index 0000000000..434ce5feb8
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/LabelledInput/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './LabelledInput';
+export { LabelledInput as default } from './LabelledInput';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Loading/Loading.jsx b/packages/extensions/venia-pwa-live-search/src/components/Loading/Loading.jsx
new file mode 100644
index 0000000000..fdeabddd66
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Loading/Loading.jsx
@@ -0,0 +1,32 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import LoadingIcon from '../../icons/loading.svg';
+
+export const Loading = ({ label }) => {
+  const isMobile = typeof window !== 'undefined' &&
+    window.matchMedia('only screen and (max-width: 768px)').matches;
+
+  return (
+    <div
+      className={`ds-sdk-loading flex h-screen justify-center items-center ${
+        isMobile ? 'loading-spinner-on-mobile' : ''
+      }`}
+    >
+      <div className="ds-sdk-loading__spinner bg-gray-100 rounded-full p-xs flex w-fit my-lg outline-gray-200">
+        {/* <LoadingIcon className="inline-block mr-xs ml-xs w-md animate-spin fill-primary" /> */}
+        <img src={LoadingIcon} className={`inline-block mr-xs ml-xs w-md animate-spin fill-primary`} />
+        <span className="ds-sdk-loading__spinner-label p-xs">{label}</span>
+      </div>
+    </div>
+  );
+};
+
+export default Loading;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Loading/index.js b/packages/extensions/venia-pwa-live-search/src/components/Loading/index.js
new file mode 100644
index 0000000000..3f75fa5d8a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Loading/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Loading';
+export { default } from './Loading';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/NoResults/NoResults.jsx b/packages/extensions/venia-pwa-live-search/src/components/NoResults/NoResults.jsx
new file mode 100644
index 0000000000..aaf9872b38
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/NoResults/NoResults.jsx
@@ -0,0 +1,55 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+export const NoResults = ({ heading, subheading, isError }) => {
+  return (
+    <div className="ds-sdk-no-results__page">
+      {isError ? (
+        <svg
+          xmlns="http://www.w3.org/2000/svg"
+          className="h-28 w-28 my-0 mx-auto stroke-gray-400"
+          fill="none"
+          viewBox="0 0 24 24"
+          stroke="currentColor"
+          strokeWidth="2"
+        >
+          <path
+            strokeLinecap="round"
+            strokeLinejoin="round"
+            d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
+          />
+        </svg>
+      ) : (
+        <svg
+          xmlns="http://www.w3.org/2000/svg"
+          className="h-28 w-28 my-0 mx-auto stroke-gray-400"
+          fill="none"
+          viewBox="0 0 24 24"
+          strokeWidth="1.5"
+        >
+          <path
+            strokeLinecap="round"
+            strokeLinejoin="round"
+            d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
+          />
+        </svg>
+      )}
+      <h1 className="ds-sdk-no-results__page__heading text-2xl text-center text-gray-600">
+        {heading}
+      </h1>
+      <h3 className="ds-sdk-no-results__page__subheading text-lg text-center text-gray-500">
+        {subheading}
+      </h3>
+    </div>
+  );
+};
+
+export default NoResults;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/NoResults/index.js b/packages/extensions/venia-pwa-live-search/src/components/NoResults/index.js
new file mode 100644
index 0000000000..31616cb314
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/NoResults/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './NoResults';
+export { default } from './NoResults';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Pagination/Pagination.jsx b/packages/extensions/venia-pwa-live-search/src/components/Pagination/Pagination.jsx
new file mode 100644
index 0000000000..b4dec62c49
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Pagination/Pagination.jsx
@@ -0,0 +1,105 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useEffect } from 'react';
+
+import { useProducts } from '../../context';
+import { ELLIPSIS, usePagination } from '../../hooks/usePagination';
+import Chevron from '../../icons/chevron.svg';
+
+export const Pagination = ({ onPageChange, totalPages, currentPage }) => {
+  const productsCtx = useProducts();
+  const paginationRange = usePagination({
+    currentPage,
+    totalPages,
+  });
+
+  useEffect(() => {
+    const { currentPage: ctxCurrentPage, totalPages: ctxTotalPages } = productsCtx;
+    if (ctxCurrentPage > ctxTotalPages) {
+      onPageChange(ctxTotalPages);
+    }
+  }, []); // Only run on mount
+
+  const onPrevious = () => {
+    if (currentPage > 1) {
+      onPageChange(currentPage - 1);
+    }
+  };
+
+  const onNext = () => {
+    if (currentPage < totalPages) {
+      onPageChange(currentPage + 1);
+    }
+  };
+
+  return (
+    <ul className="ds-plp-pagination flex justify-center items-center mt-2 mb-6 list-none">
+      <img src={Chevron} className={`h-sm w-sm transform rotate-90 ${
+          currentPage === 1
+            ? 'stroke-gray-400 cursor-not-allowed'
+            : 'stroke-gray-600 cursor-pointer'
+        }`}
+        onClick={onPrevious}
+      /> 
+      {/* <Chevron
+        className={`h-sm w-sm transform rotate-90 ${
+          currentPage === 1
+            ? 'stroke-gray-400 cursor-not-allowed'
+            : 'stroke-gray-600 cursor-pointer'
+        }`}
+        onClick={onPrevious}
+      /> */}
+
+      {paginationRange?.map((page) => {
+        if (page === ELLIPSIS) {
+          return (
+            <li
+              key={`ellipsis-${Math.random()}`}
+              className="ds-plp-pagination__dots text-gray-500 mx-sm my-auto"
+            >
+              ...
+            </li>
+          );
+        }
+
+        return (
+          <li
+            key={page}
+            className={`ds-plp-pagination__item flex items-center cursor-pointer text-center text-gray-500 my-auto mx-sm ${
+              currentPage === page
+                ? 'ds-plp-pagination__item--current text-black font-medium underline underline-offset-4 decoration-black'
+                : ''
+            }`}
+            onClick={() => onPageChange(page)}
+          >
+            {page}
+          </li>
+        );
+      })}
+      <img src={Chevron} className={`h-sm w-sm transform -rotate-90 ${
+          currentPage === totalPages
+            ? 'stroke-gray-400 cursor-not-allowed'
+            : 'stroke-gray-600 cursor-pointer'
+        }`}
+        onClick={onNext}
+      />
+      {/* <Chevron
+        className={`h-sm w-sm transform -rotate-90 ${
+          currentPage === totalPages
+            ? 'stroke-gray-400 cursor-not-allowed'
+            : 'stroke-gray-600 cursor-pointer'
+        }`}
+        onClick={onNext}
+      /> */}
+    </ul>
+  );
+};
+
+export default Pagination;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Pagination/index.js b/packages/extensions/venia-pwa-live-search/src/components/Pagination/index.js
new file mode 100644
index 0000000000..daa25f6bc9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Pagination/index.js
@@ -0,0 +1,10 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Pagination';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/PerPagePicker/PerPagePicker.jsx b/packages/extensions/venia-pwa-live-search/src/components/PerPagePicker/PerPagePicker.jsx
new file mode 100644
index 0000000000..5f2fed8015
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/PerPagePicker/PerPagePicker.jsx
@@ -0,0 +1,114 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useEffect, useRef } from 'react';
+import { useAccessibleDropdown } from '../../hooks/useAccessibleDropdown';
+import Chevron from '../../icons/chevron.svg';
+
+export const PerPagePicker = ({ value, pageSizeOptions, onChange }) => {
+  const pageSizeButton = useRef(null);
+  const pageSizeMenu = useRef(null);
+
+  const selectedOption = pageSizeOptions.find((e) => e.value === value);
+
+  const {
+    isDropdownOpen,
+    setIsDropdownOpen,
+    activeIndex,
+    setActiveIndex,
+    select,
+    setIsFocus,
+    listRef,
+  } = useAccessibleDropdown({
+    options: pageSizeOptions,
+    value,
+    onChange,
+  });
+
+  useEffect(() => {
+    const menuRef = pageSizeMenu.current;
+    const handleBlur = () => {
+      setIsFocus(false);
+      setIsDropdownOpen(false);
+    };
+
+    const handleFocus = () => {
+      if (menuRef?.parentElement?.querySelector(':hover') !== menuRef) {
+        setIsFocus(false);
+        setIsDropdownOpen(false);
+      }
+    };
+
+    menuRef?.addEventListener('blur', handleBlur);
+    menuRef?.addEventListener('focusin', handleFocus);
+    menuRef?.addEventListener('focusout', handleFocus);
+
+    return () => {
+      menuRef?.removeEventListener('blur', handleBlur);
+      menuRef?.removeEventListener('focusin', handleFocus);
+      menuRef?.removeEventListener('focusout', handleFocus);
+    };
+  }, []);
+
+  return (
+    <div
+      ref={pageSizeMenu}
+      className="ds-sdk-per-page-picker ml-2 mr-2 relative inline-block text-left bg-gray-100 rounded-md outline outline-1 outline-gray-200 hover:outline-gray-600 h-[32px]"
+    >
+      <button
+        className="group flex justify-center items-center font-normal text-sm text-gray-700 rounded-md hover:cursor-pointer border-none bg-transparent hover:border-none hover:bg-transparent focus:border-none focus:bg-transparent active:border-none active:bg-transparent active:shadow-none h-full w-full px-sm"
+        ref={pageSizeButton}
+        onClick={() => setIsDropdownOpen(!isDropdownOpen)}
+        onFocus={() => setIsFocus(false)}
+        onBlur={() => setIsFocus(false)}
+      >
+        {selectedOption ? `${selectedOption.label}` : '24'}
+        <img src={Chevron} className={`flex-shrink-0 m-auto ml-sm h-md w-md stroke-1 stroke-gray-600 ${
+            isDropdownOpen ? '' : 'rotate-180'
+          }`} />
+        {/* <Chevron
+          className={`flex-shrink-0 m-auto ml-sm h-md w-md stroke-1 stroke-gray-600 ${
+            isDropdownOpen ? '' : 'rotate-180'
+          }`}
+        /> */}
+      </button>
+
+      {isDropdownOpen && (
+        <ul
+          ref={listRef}
+          className="ds-sdk-per-page-picker__items origin-top-right absolute hover:cursor-pointer right-0 w-full rounded-md shadow-2xl bg-white ring-1 ring-black ring-opacity-5 focus:outline-none mt-2 z-20"
+        >
+          {pageSizeOptions.map((option, i) => (
+            <li
+              key={i}
+              aria-selected={option.value === selectedOption?.value}
+              onMouseOver={() => setActiveIndex(i)}
+              className={`py-xs hover:bg-gray-100 hover:text-gray-900 ${
+                i === activeIndex ? 'bg-gray-100 text-gray-900' : ''
+              }`}
+            >
+              <a
+                className={`ds-sdk-per-page-picker__items--item block-display px-md py-sm text-sm mb-0
+                  no-underline active:no-underline focus:no-underline hover:no-underline
+                  hover:text-gray-900 ${
+                    option.value === selectedOption?.value
+                      ? 'ds-sdk-per-page-picker__items--item-selected font-semibold text-gray-900'
+                      : 'font-normal text-gray-800'
+                  }`}
+                onClick={() => select(option.value)}
+              >
+                {option.label}
+              </a>
+            </li>
+          ))}
+        </ul>
+      )}
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/PerPagePicker/index.js b/packages/extensions/venia-pwa-live-search/src/components/PerPagePicker/index.js
new file mode 100644
index 0000000000..de37ed2343
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/PerPagePicker/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export { PerPagePicker } from './PerPagePicker';
+export { PerPagePicker as default } from './PerPagePicker';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Pill/Pill.jsx b/packages/extensions/venia-pwa-live-search/src/components/Pill/Pill.jsx
new file mode 100644
index 0000000000..ed38f3e78d
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Pill/Pill.jsx
@@ -0,0 +1,34 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import CloseIcon from '../../icons/plus.svg';
+
+const defaultIcon = (
+  <img src={CloseIcon} className="h-[12px] w-[12px] rotate-45 inline-block ml-sm cursor-pointer fill-gray-700" />
+  // <CloseIcon className="h-[12px] w-[12px] rotate-45 inline-block ml-sm cursor-pointer fill-gray-700" />
+);
+
+export const Pill = ({ label, onClick, CTA = defaultIcon, type }) => {
+  const containerClasses =
+    type === 'transparent'
+      ? 'ds-sdk-pill inline-flex justify-content items-center rounded-full w-fit min-h-[32px] px-4 py-1'
+      : 'ds-sdk-pill inline-flex justify-content items-center bg-gray-100 rounded-full w-fit outline outline-gray-200 min-h-[32px] px-4 py-1';
+
+  return (
+    <div key={label} className={containerClasses}>
+      <span className="ds-sdk-pill__label font-normal text-sm">{label}</span>
+      <span className="ds-sdk-pill__cta" onClick={onClick}>
+        {CTA}
+      </span>
+    </div>
+  );
+};
+
+export default Pill;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Pill/index.js b/packages/extensions/venia-pwa-live-search/src/components/Pill/index.js
new file mode 100644
index 0000000000..4f317a03d9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Pill/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Pill';
+export { default } from './Pill';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Pill/mock.js b/packages/extensions/venia-pwa-live-search/src/components/Pill/mock.js
new file mode 100644
index 0000000000..52a8d7a392
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Pill/mock.js
@@ -0,0 +1,23 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const CTA = (
+    <svg
+        xmlns="http://www.w3.org/2000/svg"
+        className="h-5 w-5 inline-block ml-2 cursor-pointer mb-0.5"
+        viewBox="0 0 20 20"
+        fill="currentColor"
+    >
+        <path
+            fillRule="evenodd"
+            d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z"
+            clipRule="evenodd"
+        />
+    </svg>
+);
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/ProductCardShimmer.css b/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/ProductCardShimmer.css
new file mode 100644
index 0000000000..b83865a456
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/ProductCardShimmer.css
@@ -0,0 +1,72 @@
+.ds-sdk-product-item--shimmer {
+    margin: 0.625rem auto;
+    box-shadow: rgba(149, 157, 165, 0.2) 0px 0.5rem 1.5rem;
+    padding: 1.25rem;
+    width: 22rem;
+}
+
+@keyframes placeholderShimmer {
+    0% {
+        background-position: calc(-100vw + 40px);
+    }
+    100% {
+        background-position: calc(100vw - 40px);
+    }
+}
+
+.shimmer-animation-card {
+    background-color: #f6f7f8;
+    background-image: linear-gradient(
+        to right,
+        #f6f7f8 0%,
+        #edeef1 20%,
+        #f6f7f8 40%,
+        #f6f7f8 100%
+    );
+    background-repeat: no-repeat;
+    background-size: 100vw 4rem;
+    animation-duration: 1s;
+    animation-fill-mode: forwards;
+    animation-iteration-count: infinite;
+    animation-name: placeholderShimmer;
+    animation-timing-function: linear;
+}
+
+.ds-sdk-product-item__banner {
+    height: 22rem;
+    background-size: 100vw 22rem;
+    border-radius: 0.3125rem;
+    margin-bottom: 0.75rem;
+}
+
+.ds-sdk-product-item__header {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 0.3125rem;
+}
+
+.ds-sdk-product-item__title {
+    height: 2.5rem;
+    flex: 0 0 auto;
+    width: 5vw;
+}
+
+.ds-sdk-product-item__list {
+    height: 2rem;
+    width: 6vw;
+    margin-bottom: 0.3125rem;
+}
+
+.ds-sdk-product-item__list:last-child {
+    margin-bottom: 0;
+}
+
+.ds-sdk-product-item__info {
+    height: 2rem;
+    width: 7vw;
+    margin-bottom: 0.3125rem;
+}
+
+.ds-sdk-product-item__info:last-child {
+    margin-bottom: 0;
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/ProductCardShimmer.jsx b/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/ProductCardShimmer.jsx
new file mode 100644
index 0000000000..26945d5d11
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/ProductCardShimmer.jsx
@@ -0,0 +1,28 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import './ProductCardShimmer.css';
+
+export const ProductCardShimmer = () => {
+  return (
+    <div className="ds-sdk-product-item ds-sdk-product-item--shimmer">
+      <div className="ds-sdk-product-item__banner shimmer-animation-card" />
+      <div className="ds-sdk-product-item__content">
+        <div className="ds-sdk-product-item__header">
+          <div className="ds-sdk-product-item__title shimmer-animation-card" />
+        </div>
+        <div className="ds-sdk-product-item__list shimmer-animation-card" />
+        <div className="ds-sdk-product-item__info shimmer-animation-card" />
+      </div>
+    </div>
+  );
+};
+
+export default ProductCardShimmer;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/index.js b/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/index.js
new file mode 100644
index 0000000000..e3d7b8d566
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductCardShimmer/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './ProductCardShimmer';
+export { default } from './ProductCardShimmer';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductItem/MockData.js b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/MockData.js
new file mode 100644
index 0000000000..048c44e916
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/MockData.js
@@ -0,0 +1,508 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const sampleProductNoImage = {
+    product: {
+        __typename: 'SimpleProduct',
+        id: 21,
+        uid: '21',
+        name: 'Sprite Foam Yoga Brick',
+        sku: '24-WG084',
+        description: {
+            html:
+                '<p>Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul> '
+        },
+        short_description: null,
+        attribute_set_id: null,
+        meta_title: null,
+        meta_keyword: null,
+        meta_description: null,
+        image: null,
+        small_image: null,
+        thumbnail: null,
+        new_from_date: null,
+        new_to_date: null,
+        created_at: null,
+        updated_at: null,
+        price_range: {
+            minimum_price: {
+                fixed_product_taxes: null,
+                regular_price: { value: 8, currency: 'USD' },
+                final_price: { value: 5, currency: 'USD' },
+                discount: null
+            },
+            maximum_price: {
+                fixed_product_taxes: null,
+                regular_price: { value: 5, currency: 'USD' },
+                final_price: { value: 5, currency: 'USD' },
+                discount: null
+            }
+        },
+        gift_message_available: null,
+        canonical_url:
+            '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html',
+        media_gallery: null,
+        custom_attributes: null,
+        add_to_cart_allowed: null
+    },
+    productView: {
+        __typename: 'SimpleProduct',
+        id: 21,
+        uid: '21',
+        name: 'Sprite Foam Yoga Brick',
+        sku: '24-WG084',
+        description: {
+            html:
+                '<p>Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul> '
+        },
+        short_description: null,
+        attribute_set_id: null,
+        meta_title: null,
+        meta_keyword: null,
+        meta_description: null,
+        images: null,
+        new_from_date: null,
+        new_to_date: null,
+        created_at: null,
+        updated_at: null,
+        price: {
+            final: {
+                amount: {
+                    value: 5,
+                    currency: 'USD'
+                },
+                adjustments: null
+            },
+            regular: {
+                amount: {
+                    value: 5,
+                    currency: 'USD'
+                },
+                adjustments: null
+            }
+        },
+        priceRange: {
+            maximum: {
+                final: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                },
+                regular: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                }
+            },
+            minimum: {
+                final: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                },
+                regular: {
+                    amount: {
+                        value: 8,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                }
+            }
+        },
+        gift_message_available: null,
+        url:
+            'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html',
+        urlKey: 'sprite-foam-yoga-brick',
+        media_gallery: null,
+        custom_attributes: null,
+        add_to_cart_allowed: null,
+        options: null
+    },
+    highlights: [
+        {
+            attribute: 'name',
+            value: 'Sprite Foam <em>Yoga</em> Brick',
+            matched_words: []
+        },
+        {
+            attribute: 'description',
+            value:
+                '<p>Our top-selling <em>yoga</em> prop, the 4-inch, high-quality Sprite Foam <em>Yoga</em> Brick is popular among <em>yoga</em> novices and studio professionals alike. An essential <em>yoga</em> accessory, the <em>yoga</em> brick is a critical tool for finding balance and alignment in many common <em>yoga</em> poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul>',
+            matched_words: []
+        }
+    ]
+};
+
+export const sampleProductDiscounted = {
+    product: {
+        __typename: 'SimpleProduct',
+        id: 21,
+        uid: '21',
+        name: 'Sprite Foam Yoga Brick',
+        sku: '24-WG084',
+        description: {
+            html:
+                '<p>Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul> '
+        },
+        short_description: null,
+        attribute_set_id: null,
+        meta_title: null,
+        meta_keyword: null,
+        meta_description: null,
+        image: {
+            url:
+                '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+            label: null,
+            position: null,
+            disabled: null
+        },
+        small_image: {
+            url:
+                '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+            label: null,
+            position: null,
+            disabled: null
+        },
+        thumbnail: {
+            url:
+                '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+            label: null,
+            position: null,
+            disabled: null
+        },
+        new_from_date: null,
+        new_to_date: null,
+        created_at: null,
+        updated_at: null,
+        price_range: {
+            minimum_price: {
+                fixed_product_taxes: null,
+                regular_price: { value: 8, currency: 'USD' },
+                final_price: { value: 5, currency: 'USD' },
+                discount: null
+            },
+            maximum_price: {
+                fixed_product_taxes: null,
+                regular_price: { value: 5, currency: 'USD' },
+                final_price: { value: 5, currency: 'USD' },
+                discount: null
+            }
+        },
+        gift_message_available: null,
+        canonical_url:
+            '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html',
+        media_gallery: null,
+        custom_attributes: null,
+        add_to_cart_allowed: null
+    },
+    productView: {
+        __typename: 'SimpleProduct',
+        id: 21,
+        uid: '21',
+        name: 'Sprite Foam Yoga Brick',
+        sku: '24-WG084',
+        description: {
+            html:
+                '<p>Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul> '
+        },
+        short_description: null,
+        attribute_set_id: null,
+        meta_title: null,
+        meta_keyword: null,
+        meta_description: null,
+        images: [
+            {
+                url:
+                    'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+                label: null,
+                position: null,
+                disabled: null,
+                roles: ['thumbnail']
+            },
+            {
+                url:
+                    'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+                label: null,
+                position: null,
+                disabled: null,
+                roles: ['thumbnail']
+            },
+            {
+                url:
+                    'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+                label: null,
+                position: null,
+                disabled: null,
+                roles: ['thumbnail']
+            }
+        ],
+        new_from_date: null,
+        new_to_date: null,
+        created_at: null,
+        updated_at: null,
+        price: {
+            final: {
+                amount: {
+                    value: 5,
+                    currency: 'USD'
+                },
+                adjustments: null
+            },
+            regular: {
+                amount: {
+                    value: 5,
+                    currency: 'USD'
+                },
+                adjustments: null
+            }
+        },
+        priceRange: {
+            maximum: {
+                final: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                },
+                regular: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                }
+            },
+            minimum: {
+                final: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                },
+                regular: {
+                    amount: {
+                        value: 8,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                }
+            }
+        },
+        gift_message_available: null,
+        url:
+            'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html',
+        urlKey: 'sprite-foam-yoga-brick',
+        media_gallery: null,
+        custom_attributes: null,
+        add_to_cart_allowed: null,
+        options: null
+    },
+    highlights: [
+        {
+            attribute: 'name',
+            value: 'Sprite Foam <em>Yoga</em> Brick',
+            matched_words: []
+        },
+        {
+            attribute: 'description',
+            value:
+                '<p>Our top-selling <em>yoga</em> prop, the 4-inch, high-quality Sprite Foam <em>Yoga</em> Brick is popular among <em>yoga</em> novices and studio professionals alike. An essential <em>yoga</em> accessory, the <em>yoga</em> brick is a critical tool for finding balance and alignment in many common <em>yoga</em> poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul>',
+            matched_words: []
+        }
+    ]
+};
+
+export const sampleProductNotDiscounted = {
+    product: {
+        __typename: 'SimpleProduct',
+        id: 21,
+        uid: '21',
+        name: 'Sprite Foam Yoga Brick',
+        sku: '24-WG084',
+        description: {
+            html:
+                '<p>Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul> '
+        },
+        short_description: null,
+        attribute_set_id: null,
+        meta_title: null,
+        meta_keyword: null,
+        meta_description: null,
+        image: {
+            url:
+                '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+            label: null,
+            position: null,
+            disabled: null
+        },
+        small_image: {
+            url:
+                '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+            label: null,
+            position: null,
+            disabled: null
+        },
+        thumbnail: {
+            url:
+                '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+            label: null,
+            position: null,
+            disabled: null
+        },
+        new_from_date: null,
+        new_to_date: null,
+        created_at: null,
+        updated_at: null,
+        price_range: {
+            minimum_price: {
+                fixed_product_taxes: null,
+                regular_price: { value: 5, currency: 'USD' },
+                final_price: { value: 5, currency: 'USD' },
+                discount: null
+            },
+            maximum_price: {
+                fixed_product_taxes: null,
+                regular_price: { value: 8, currency: 'USD' },
+                final_price: { value: 8, currency: 'USD' },
+                discount: null
+            }
+        },
+        gift_message_available: null,
+        canonical_url:
+            '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html',
+        media_gallery: null,
+        custom_attributes: null,
+        add_to_cart_allowed: null
+    },
+    productView: {
+        __typename: 'SimpleProduct',
+        id: 21,
+        uid: '21',
+        name: 'Sprite Foam Yoga Brick',
+        sku: '24-WG084',
+        description: {
+            html:
+                '<p>Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul> '
+        },
+        short_description: null,
+        attribute_set_id: null,
+        meta_title: null,
+        meta_keyword: null,
+        meta_description: null,
+        images: [
+            {
+                url:
+                    'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+                label: null,
+                position: null,
+                disabled: null,
+                roles: ['thumbnail']
+            },
+            {
+                url:
+                    'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+                label: null,
+                position: null,
+                disabled: null,
+                roles: ['thumbnail']
+            },
+            {
+                url:
+                    'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg',
+                label: null,
+                position: null,
+                disabled: null,
+                roles: ['thumbnail']
+            }
+        ],
+        new_from_date: null,
+        new_to_date: null,
+        created_at: null,
+        updated_at: null,
+        price: {
+            final: {
+                amount: {
+                    value: 5,
+                    currency: 'USD'
+                },
+                adjustments: null
+            },
+            regular: {
+                amount: {
+                    value: 5,
+                    currency: 'USD'
+                },
+                adjustments: null
+            }
+        },
+        priceRange: {
+            maximum: {
+                final: {
+                    amount: {
+                        value: 8,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                },
+                regular: {
+                    amount: {
+                        value: 8,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                }
+            },
+            minimum: {
+                final: {
+                    amount: {
+                        value: 5,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                },
+                regular: {
+                    amount: {
+                        value: 8,
+                        currency: 'USD'
+                    },
+                    adjustments: null
+                }
+            }
+        },
+        gift_message_available: null,
+        url:
+            'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html',
+        urlKey: 'sprite-foam-yoga-brick',
+        media_gallery: null,
+        custom_attributes: null,
+        add_to_cart_allowed: null,
+        options: null
+    },
+    highlights: [
+        {
+            attribute: 'name',
+            value: 'Sprite Foam <em>Yoga</em> Brick',
+            matched_words: []
+        },
+        {
+            attribute: 'description',
+            value:
+                '<p>Our top-selling <em>yoga</em> prop, the 4-inch, high-quality Sprite Foam <em>Yoga</em> Brick is popular among <em>yoga</em> novices and studio professionals alike. An essential <em>yoga</em> accessory, the <em>yoga</em> brick is a critical tool for finding balance and alignment in many common <em>yoga</em> poses. Choose from 5 color options.</p>\n<ul>\n<li>Standard Large Size: 4" x 6" x 9".\n<li>Beveled edges for ideal contour grip.\n<li>Durable and soft, scratch-proof foam.\n<li>Individually wrapped.\n<li>Ten color choices.\n</ul>',
+            matched_words: []
+        }
+    ]
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductItem.css b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductItem.css
new file mode 100644
index 0000000000..b1a7d1b0eb
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductItem.css
@@ -0,0 +1,84 @@
+.grid-container {
+    display: grid;
+    gap: 1px;
+    height: auto;
+    grid-template-columns: auto 1fr 1fr;
+    border-top: 2px solid #e5e7eb;
+    padding: 10px;
+    grid-template-areas:
+        'product-image product-details product-price'
+        'product-image product-description product-description'
+        'product-image product-ratings product-add-to-cart';
+}
+
+.product-image {
+    grid-area: product-image;
+    width: fit-content;
+}
+
+.product-details {
+    white-space: nowrap;
+    grid-area: product-details;
+}
+
+.product-price {
+    grid-area: product-price;
+    display: grid;
+    width: 100%;
+    height: 100%;
+    justify-content: end;
+}
+
+.product-description {
+    grid-area: product-description;
+}
+
+.product-description:hover {
+    text-decoration: underline;
+}
+
+.product-ratings {
+    grid-area: product-ratings;
+}
+
+.product-add-to-cart {
+    grid-area: product-add-to-cart;
+    display: grid;
+    justify-content: end;
+}
+
+@media screen and (max-width: 767px) {
+    .grid-container {
+        display: grid;
+        gap: 10px;
+        height: auto;
+        border-top: 2px solid #e5e7eb;
+        padding: 10px;
+        grid-template-areas:
+            'product-image  product-image product-image'
+            'product-details product-details product-details'
+            'product-price product-price product-price'
+            'product-description product-description product-description'
+            'product-ratings product-ratings product-ratings'
+            'product-add-to-cart product-add-to-cart product-add-to-cart';
+    }
+
+    .product-image {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: auto;
+    }
+
+    .product-price {
+        justify-content: start;
+    }
+
+    .product-add-to-cart {
+        justify-content: center;
+    }
+
+    .product-details {
+        justify-content: center;
+    }
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductItem.jsx b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductItem.jsx
new file mode 100644
index 0000000000..b01c79b0c9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductItem.jsx
@@ -0,0 +1,347 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useState } from 'react';
+import '../ProductItem/ProductItem.css';
+
+import { useCart, useProducts, useSensor, useStore } from '../../context';
+import NoImage from '../../icons/NoImage.svg';
+import {
+  generateOptimizedImages,
+  getProductImageURLs,
+} from '../../utils/getProductImage';
+import { htmlStringDecode } from '../../utils/htmlStringDecode';
+import AddToCartButton from '../AddToCartButton';
+import { ImageCarousel } from '../ImageCarousel';
+import { SwatchButtonGroup } from '../SwatchButtonGroup';
+import ProductPrice from './ProductPrice';
+import { SEARCH_UNIT_ID } from '../../utils/constants';
+import { sanitizeRefinedImages } from '../../utils/modifyResults';
+import { useResultsModifier } from '../../context/resultsModifierContext';
+
+const ProductItem = ({
+  item,
+  currencySymbol,
+  currencyRate,
+  setRoute,
+  refineProduct,
+  setCartUpdated,
+  setItemAdded,
+  setError,
+  addToCart,
+}) => {
+  const { product, productView } = item;
+  const [carouselIndex, setCarouselIndex] = useState(0);
+  const [selectedSwatch, setSelectedSwatch] = useState('');
+  const [imagesFromRefinedProduct, setImagesFromRefinedProduct] = useState(null);
+  const [refinedProduct, setRefinedProduct] = useState();
+  const [isHovering, setIsHovering] = useState(false);
+  const { addToCartGraphQL, refreshCart } = useCart();
+  const { viewType } = useProducts();
+  const {
+    config: { optimizeImages, imageBaseWidth, imageCarousel, listview },
+  } = useStore();
+
+  const { screenSize } = useSensor();
+
+  const handleMouseOver = () => {
+    setIsHovering(true);
+  };
+
+  const handleMouseOut = () => {
+    setIsHovering(false);
+  };
+
+  const { baseUrl, baseUrlWithoutProtocol } = useResultsModifier();
+
+  const handleSelection = async (optionIds, sku) => {
+    const data = await refineProduct(optionIds, sku);
+    setSelectedSwatch(optionIds[0]);
+    setImagesFromRefinedProduct(sanitizeRefinedImages(data.refineProduct.images, baseUrl, baseUrlWithoutProtocol, true));
+    setRefinedProduct(data);
+    setCarouselIndex(0);
+  };
+
+  const isSelected = (id) => {
+    const selected = selectedSwatch ? selectedSwatch === id : false;
+    return selected;
+  };
+
+  const productImageArray = imagesFromRefinedProduct
+    ? getProductImageURLs(imagesFromRefinedProduct.length ? imagesFromRefinedProduct : [], imageCarousel ? 3 : 1)
+    : getProductImageURLs(
+        productView.images && productView.images.length ? productView.images : [],
+        imageCarousel ? 3 : 1, // number of images to display in carousel
+        product.image && product.image.url ? product.image.url : undefined
+      );
+    
+
+  let optimizedImageArray = [];
+  
+  if (optimizeImages) {
+    optimizedImageArray = generateOptimizedImages(
+      productImageArray,
+      imageBaseWidth !== undefined && imageBaseWidth !== null ? imageBaseWidth : 200
+    );
+  }
+
+  const discount = refinedProduct
+    ? refinedProduct.refineProduct?.priceRange?.minimum?.regular?.amount
+        ?.value >
+      refinedProduct.refineProduct?.priceRange?.minimum?.final?.amount?.value
+    : product?.price_range?.minimum_price?.regular_price?.value >
+        product?.price_range?.minimum_price?.final_price?.value ||
+      productView?.price?.regular?.amount?.value >
+        productView?.price?.final?.amount?.value;
+
+  const isSimple = product?.__typename === 'SimpleProduct';
+  const isComplexProductView = productView?.__typename === 'ComplexProductView';
+  const isBundle = product?.__typename === 'BundleProduct';
+  const isGrouped = product?.__typename === 'GroupedProduct';
+  const isGiftCard = product?.__typename === 'GiftCardProduct';
+  const isConfigurable = product?.__typename === 'ConfigurableProduct';
+
+  const onProductClick = () => {
+    window.magentoStorefrontEvents?.publish.searchProductClick(
+      SEARCH_UNIT_ID,
+      product?.sku
+    );
+  };
+
+  const productUrl = setRoute
+    ? setRoute({ sku: productView?.sku, urlKey: productView?.urlKey })
+    : product?.canonical_url;
+
+  const handleAddToCart = async () => {
+    setError(false);
+    if (isSimple) {
+      if (addToCart) {
+        await addToCart(productView.sku, [], 1);
+      } else {
+        const response = await addToCartGraphQL(productView.sku);
+
+        if (
+          response?.errors ||
+          response?.data?.addProductsToCart?.user_errors.length > 0
+        ) {
+          setError(true);
+          return;
+        }
+
+        setItemAdded(product.name);
+        refreshCart && refreshCart();
+        setCartUpdated(true);
+      }
+    } else if (productUrl) {
+      window.open(productUrl, '_self');
+    }
+  };
+
+  if (listview && viewType === 'listview') {
+    return (
+      <>
+        <div className="grid-container">
+          <div
+            className={`product-image ds-sdk-product-item__image relative rounded-md overflow-hidden}`}
+          >
+            <a
+              href={productUrl}
+              onClick={onProductClick}
+              className="!text-primary hover:no-underline hover:text-primary"
+            >
+              {/* Image */}
+              {productImageArray.length ? (
+                <ImageCarousel
+                  images={
+                    optimizedImageArray.length
+                      ? optimizedImageArray
+                      : productImageArray
+                  }
+                  productName={product.name}
+                  carouselIndex={carouselIndex}
+                  setCarouselIndex={setCarouselIndex}
+                />
+              ) : (
+                <img src={NoImage} className={`max-h-[250px] max-w-[200px] pr-5 m-auto object-cover object-center lg:w-full`} />
+                // <NoImage
+                //   className={`max-h-[250px] max-w-[200px] pr-5 m-auto object-cover object-center lg:w-full`}
+                // />
+              )}
+            </a>
+          </div>
+          <div className="product-details">
+            <div className="flex flex-col w-1/3">
+              {/* Product name */}
+              <a
+                href={productUrl}
+                onClick={onProductClick}
+                className="!text-primary hover:no-underline hover:text-primary"
+              >
+                <div className="ds-sdk-product-item__product-name mt-xs text-sm text-primary">
+                  {product.name !== null && htmlStringDecode(product.name)}
+                </div>
+                <div className="ds-sdk-product-item__product-sku mt-xs text-sm text-primary">
+                  SKU:
+                  {product.sku !== null && htmlStringDecode(product.sku)}
+                </div>
+              </a>
+
+              {/* Swatch */}
+              {!screenSize.mobile &&
+                productView?.options &&
+                  productView.options?.length > 0 && (
+                <div className="ds-sdk-product-item__product-swatch flex flex-row mt-sm text-sm text-primary pb-6">
+                  {productView?.options?.map(
+                    (swatches) =>
+                      swatches.id === 'color' && (
+                        <SwatchButtonGroup
+                          key={`${productView?.sku}-${option.id}`}
+                          isSelected={isSelected}
+                          swatches={swatches.values && swatches.values.length ? swatches.values : []}
+                          showMore={onProductClick}
+                          productUrl={productUrl}
+                          onClick={handleSelection}
+                          sku={productView?.sku}
+                        />
+                      )
+                  )}
+                </div>
+              )}
+              
+            </div>
+          </div>
+          <div className="product-price">
+            <a
+              href={productUrl}
+              onClick={onProductClick}
+              className="!text-primary hover:no-underline hover:text-primary"
+            >
+              <ProductPrice
+                item={refinedProduct !== undefined && refinedProduct !== null ? refinedProduct : item}
+                isBundle={isBundle}
+                isGrouped={isGrouped}
+                isGiftCard={isGiftCard}
+                isConfigurable={isConfigurable}
+                isComplexProductView={isComplexProductView}
+                discount={discount}
+                currencySymbol={currencySymbol}
+                currencyRate={currencyRate}
+              />
+            </a>
+          </div>
+          <div className="product-description text-sm text-primary mt-xs">
+            <a
+              href={productUrl}
+              onClick={onProductClick}
+              className="!text-primary hover:no-underline hover:text-primary"
+            >
+              {product.short_description?.html ? (
+                <>
+                  <span
+                    dangerouslySetInnerHTML={{
+                      __html: product.short_description.html,
+                    }}
+                  />
+                </>
+              ) : (
+                <span />
+              )}
+            </a>
+          </div>
+
+          <div className="product-ratings" />
+          <div className="product-add-to-cart">
+            <div className="pb-4 h-[38px] w-96">
+              <AddToCartButton onClick={handleAddToCart} />
+            </div>
+          </div>
+        </div>
+      </>
+    );
+  }
+
+  return (
+    <div
+      className="ds-sdk-product-item group relative flex flex-col max-w-sm justify-between h-full hover:border-[1.5px] border-solid hover:shadow-lg border-offset-2 p-5"
+      style={{
+        'borderColor': '#D5D5D5',
+      }}
+      onMouseEnter={handleMouseOver}
+      onMouseLeave={handleMouseOut}
+    >
+      <a
+        href={productUrl}
+        onClick={onProductClick}
+        className="!text-primary hover:no-underline hover:text-primary"
+      >
+        <div className="ds-sdk-product-item__main relative flex flex-col justify-between h-full">
+          <div className="ds-sdk-product-item__image relative w-full h-full rounded-md overflow-hidden">
+            {productImageArray.length ? (
+              <ImageCarousel
+                images={
+                  optimizedImageArray.length
+                    ? optimizedImageArray
+                    : productImageArray
+                }
+                productName={product.name}
+                carouselIndex={carouselIndex}
+                setCarouselIndex={setCarouselIndex}
+              />
+            ) : (
+              <img src={NoImage} className={`max-h-[45rem] w-full object-cover object-center lg:w-full`} />
+              // <NoImage
+              //   className={`max-h-[45rem] w-full object-cover object-center lg:w-full`}
+              // />
+            )}
+          </div>
+          <div className="flex flex-row">
+            <div className="flex flex-col">
+              <div className="ds-sdk-product-item__product-name mt-md text-sm text-primary">
+                {product.name !== null && htmlStringDecode(product.name)}
+              </div>
+              <ProductPrice
+                item={refinedProduct !== undefined && refinedProduct !== null ? refinedProduct : item}
+                isBundle={isBundle}
+                isGrouped={isGrouped}
+                isGiftCard={isGiftCard}
+                isConfigurable={isConfigurable}
+                isComplexProductView={isComplexProductView}
+                discount={discount}
+                currencySymbol={currencySymbol}
+                currencyRate={currencyRate}
+              />
+            </div>
+          </div>
+        </div>
+      </a>
+
+      {!screenSize.mobile && productView?.options && productView.options?.length > 0 && (
+        <div className="ds-sdk-product-item__product-swatch mt-sm text-sm text-primary pb-6">
+          {productView?.options.map((option) => (
+            <SwatchButtonGroup
+              key={`${productView?.sku}-${option.id}`}
+              isSelected={isSelected}
+              swatches={option.values && option.values.length ? option.values : []}
+              showMore={onProductClick}
+              productUrl={productUrl}
+              onClick={handleSelection}
+              sku={productView?.sku}
+            />
+          ))}
+        </div>
+      )}
+
+      <div className="ds-sdk-product-item__add-to-cart py-2">
+        <AddToCartButton onClick={handleAddToCart} />
+      </div>
+    </div>
+  );
+};
+
+export default ProductItem;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductPrice.jsx b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductPrice.jsx
new file mode 100644
index 0000000000..b86ab72466
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/ProductPrice.jsx
@@ -0,0 +1,181 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useContext } from 'react';
+import { TranslationContext } from '../../context/translation';
+import { getProductPrice } from '../../utils/getProductPrice';
+
+const ProductPrice = ({
+  isComplexProductView,
+  item,
+  isBundle,
+  isGrouped,
+  isGiftCard,
+  isConfigurable,
+  discount,
+  currencySymbol,
+  currencyRate
+}) => {
+  const translation = useContext(TranslationContext);
+  let price;
+
+  if ('product' in item) {
+    price = 
+      item && item.product && item.product.price_range && item.product.price_range.minimum_price && item.product.price_range.minimum_price.final_price 
+      ? item.product.price_range.minimum_price.final_price : item && item.product && item.product.price_range && item.product.price_range.minimum_price && item.product.price_range.minimum_price.regular_price 
+       ? item.product.price_range.minimum_price.regular_price : undefined;
+  } else {
+    price = 
+      item && item.refineProduct && item.refineProduct.priceRange && item.refineProduct.priceRange.minimum && item.refineProduct.priceRange.minimum.final 
+      ? item.refineProduct.priceRange.minimum.final 
+      : item && item.refineProduct && item.refineProduct.price && item.refineProduct.price.final 
+        ? item.refineProduct.price.final : undefined;
+  }
+
+  const getBundledPrice = (item, currencySymbol, currencyRate) => {
+    const bundlePriceTranslationOrder =
+      translation.ProductCard.bundlePrice.split(' ');
+    return bundlePriceTranslationOrder.map((word, index) =>
+      word === '{fromBundlePrice}' ? (
+        `${getProductPrice(item, currencySymbol, currencyRate, false, true)} `
+      ) : word === '{toBundlePrice}' ? (
+        getProductPrice(item, currencySymbol, currencyRate, true, true)
+      ) : (
+        <span className="text-gray-500 text-xs font-normal mr-xs" key={index}>
+          {word}
+        </span>
+      )
+    );
+  };
+
+  const getPriceFormat = (item, currencySymbol, currencyRate, isGiftCard) => {
+    const priceTranslation = isGiftCard
+      ? translation.ProductCard.from
+      : translation.ProductCard.startingAt;
+    const startingAtTranslationOrder = priceTranslation.split('{productPrice}');
+    return startingAtTranslationOrder.map((word, index) =>
+      word === '' ? (
+        getProductPrice(item, currencySymbol, currencyRate, false, true)
+      ) : (
+        <span className="text-gray-500 text-xs font-normal mr-xs" key={index}>
+          {word}
+        </span>
+      )
+    );
+  };
+
+  const getDiscountedPrice = (discount) => {
+    const discountPrice = discount ? (
+      <>
+        <span className="line-through pr-2">
+          {getProductPrice(item, currencySymbol, currencyRate, false, false)}
+        </span>
+        <span className="text-secondary">
+          {getProductPrice(item, currencySymbol, currencyRate, false, true)}
+        </span>
+      </>
+    ) : (
+      getProductPrice(item, currencySymbol, currencyRate, false, true)
+    );
+    const discountedPriceTranslation = translation.ProductCard.asLowAs;
+    const discountedPriceTranslationOrder =
+      discountedPriceTranslation.split('{discountPrice}');
+    return discountedPriceTranslationOrder.map((word, index) =>
+      word === '' ? (
+        discountPrice
+      ) : (
+        <span className="text-gray-500 text-xs font-normal mr-xs" key={index}>
+          {word}
+        </span>
+      )
+    );
+  };
+
+  return (
+    <>
+      {price && (
+        <div className="ds-sdk-product-price">
+          {!isBundle &&
+            !isGrouped &&
+            !isConfigurable &&
+            !isComplexProductView &&
+            discount && (
+              <p className="ds-sdk-product-price--discount mt-xs text-sm font-medium text-gray-900 my-auto">
+                <span className="line-through pr-2">
+                  {getProductPrice(
+                    item,
+                    currencySymbol,
+                    currencyRate,
+                    false,
+                    false
+                  )}
+                </span>
+                <span className="text-secondary">
+                  {getProductPrice(
+                    item,
+                    currencySymbol,
+                    currencyRate,
+                    false,
+                    true
+                  )}
+                </span>
+              </p>
+            )}
+
+          {!isBundle &&
+            !isGrouped &&
+            !isGiftCard &&
+            !isConfigurable &&
+            !isComplexProductView &&
+            !discount && (
+              <p className="ds-sdk-product-price--no-discount mt-xs text-sm font-medium text-gray-900 my-auto">
+                {getProductPrice(
+                  item,
+                  currencySymbol,
+                  currencyRate,
+                  false,
+                  true
+                )}
+              </p>
+            )}
+
+          {isBundle && (
+            <div className="ds-sdk-product-price--bundle">
+              <p className="mt-xs text-sm font-medium text-gray-900 my-auto">
+                {getBundledPrice(item, currencySymbol, currencyRate)}
+              </p>
+            </div>
+          )}
+
+          {isGrouped && (
+            <p className="ds-sdk-product-price--grouped mt-xs text-sm font-medium text-gray-900 my-auto">
+              {getPriceFormat(item, currencySymbol, currencyRate, false)}
+            </p>
+          )}
+
+          {isGiftCard && (
+            <p className="ds-sdk-product-price--gift-card mt-xs text-sm font-medium text-gray-900 my-auto">
+              {getPriceFormat(item, currencySymbol, currencyRate, true)}
+            </p>
+          )}
+
+          {!isGrouped &&
+            !isBundle &&
+            (isConfigurable || isComplexProductView) && (
+              <p className="ds-sdk-product-price--configurable mt-xs text-sm font-medium text-gray-900 my-auto">
+                {getDiscountedPrice(discount)}
+              </p>
+            )}
+        </div>
+      )}
+    </>
+  );
+};
+
+export default ProductPrice;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductItem/index.js b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/index.js
new file mode 100644
index 0000000000..1a7c1ae8bd
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductItem/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+//export * from './ProductItem';
+export { default as ProductItem } from './ProductItem';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductList/MockData.js b/packages/extensions/venia-pwa-live-search/src/components/ProductList/MockData.js
new file mode 100644
index 0000000000..c37efa0e1c
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductList/MockData.js
@@ -0,0 +1,190 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+const SimpleProduct = {
+    product: {
+        sku: '24-WG088',
+        name: 'Sprite Foam Roller',
+        canonical_url:
+            'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/sprite-foam-roller.html'
+    },
+    productView: {
+        __typename: 'SimpleProductView',
+        sku: '24-WG088',
+        name: 'Sprite Foam Roller',
+        url:
+            'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/sprite-foam-roller.html',
+        urlKey: 'sprite-foam-roller',
+        images: [
+            {
+                label: 'Image',
+                url:
+                    'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/l/u/luma-foam-roller.jpg'
+            }
+        ],
+        price: {
+            final: {
+                amount: {
+                    value: 19.0,
+                    currency: 'USD'
+                }
+            },
+            regular: {
+                amount: {
+                    value: 19.0,
+                    currency: 'USD'
+                }
+            }
+        }
+    },
+    highlights: [
+        {
+            attribute: 'name',
+            value: '<em>Sprite</em> Foam Roller',
+            matched_words: []
+        }
+    ]
+};
+
+const ComplexProduct = {
+    product: {
+        sku: 'MSH06',
+        name: 'Lono Yoga Short',
+        canonical_url:
+            'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/lono-yoga-short.html'
+    },
+    productView: {
+        __typename: 'ComplexProductView',
+        sku: 'MSH06',
+        name: 'Lono Yoga Short',
+        url:
+            'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/lono-yoga-short.html',
+        urlKey: 'lono-yoga-short',
+        images: [
+            {
+                label: '',
+                url:
+                    'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_main_2.jpg'
+            },
+            {
+                label: '',
+                url:
+                    'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_alt1_2.jpg'
+            },
+            {
+                label: '',
+                url:
+                    'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_back_2.jpg'
+            }
+        ],
+        priceRange: {
+            maximum: {
+                final: {
+                    amount: {
+                        value: 32.0,
+                        currency: 'USD'
+                    }
+                },
+                regular: {
+                    amount: {
+                        value: 32.0,
+                        currency: 'USD'
+                    }
+                }
+            },
+            minimum: {
+                final: {
+                    amount: {
+                        value: 32.0,
+                        currency: 'USD'
+                    }
+                },
+                regular: {
+                    amount: {
+                        value: 32.0,
+                        currency: 'USD'
+                    }
+                }
+            }
+        },
+        options: [
+            {
+                id: 'size',
+                title: 'Size',
+                values: [
+                    {
+                        title: '32',
+                        id: 'Y29uZmlndXJhYmxlLzE4Ni8xODQ=',
+                        type: 'TEXT',
+                        value: '32'
+                    },
+                    {
+                        title: '33',
+                        id: 'Y29uZmlndXJhYmxlLzE4Ni8xODU=',
+                        type: 'TEXT',
+                        value: '33'
+                    },
+                    {
+                        title: '34',
+                        id: 'Y29uZmlndXJhYmxlLzE4Ni8xODY=',
+                        type: 'TEXT',
+                        value: '34'
+                    },
+                    {
+                        title: '36',
+                        id: 'Y29uZmlndXJhYmxlLzE4Ni8xODc=',
+                        type: 'TEXT',
+                        value: '36'
+                    }
+                ]
+            },
+            {
+                id: 'color',
+                title: 'Color',
+                values: [
+                    {
+                        title: 'Blue',
+                        id: 'Y29uZmlndXJhYmxlLzkzLzU5',
+                        type: 'COLOR_HEX',
+                        value: '#1857f7'
+                    },
+                    {
+                        title: 'Red',
+                        id: 'Y29uZmlndXJhYmxlLzkzLzY3',
+                        type: 'COLOR_HEX',
+                        value: '#ff0000'
+                    },
+                    {
+                        title: 'Gray',
+                        id: 'Y29uZmlndXJhYmxlLzkzLzYx',
+                        type: 'COLOR_HEX',
+                        value: '#8f8f8f'
+                    }
+                ]
+            }
+        ]
+    },
+    highlights: [
+        {
+            attribute: 'name',
+            value: 'Lono <em>Yoga</em> Short',
+            matched_words: []
+        }
+    ]
+};
+
+export const products = [
+    SimpleProduct,
+    SimpleProduct,
+    SimpleProduct,
+    SimpleProduct,
+    SimpleProduct,
+    SimpleProduct,
+    ComplexProduct
+];
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductList/ProductList.jsx b/packages/extensions/venia-pwa-live-search/src/components/ProductList/ProductList.jsx
new file mode 100644
index 0000000000..921d3a6333
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductList/ProductList.jsx
@@ -0,0 +1,127 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useEffect, useState, useMemo } from 'react';
+import './product-list.css';
+
+import { Alert } from '../../components/Alert';
+import { useProducts, useStore } from '../../context';
+import { ProductItem } from '../ProductItem';
+import { classNames } from '../../utils/dom';
+import { sanitizeProducts } from '../../utils/modifyResults';
+import { useResultsModifier } from '../../context/resultsModifierContext';
+
+
+const ProductList = ({ products, numberOfColumns, showFilters }) => {
+  const productsCtx = useProducts();
+  const {
+    currencySymbol,
+    currencyRate,
+    setRoute,
+    refineProduct,
+    refreshCart,
+    addToCart,
+  } = productsCtx;
+
+  const [cartUpdated, setCartUpdated] = useState(false);
+  const [itemAdded, setItemAdded] = useState('');
+  const { viewType } = useProducts();
+  const [error, setError] = useState(false);
+
+  const {
+    config: { listview },
+  } = useStore();
+
+  const { baseUrl, baseUrlWithoutProtocol } = useResultsModifier();
+  
+  const sanitizedProducts = useMemo(() => sanitizeProducts(products, baseUrl, baseUrlWithoutProtocol), [products]);  
+  
+  const className = showFilters
+    ? 'ds-sdk-product-list bg-body max-w-full pl-3 pb-2xl sm:pb-24'
+    : 'ds-sdk-product-list bg-body w-full mx-auto pb-2xl sm:pb-24';
+
+  useEffect(() => {
+    if (refreshCart) refreshCart();
+  }, [itemAdded]);
+
+  return (
+    <div
+      className={classNames(
+        'ds-sdk-product-list bg-body pb-2xl sm:pb-24',
+        className
+      )}
+    >
+      {cartUpdated && (
+        <div className="mt-8">
+          <Alert
+            title={`You added ${itemAdded} to your shopping cart.`}
+            type="success"
+            description=""
+            onClick={() => setCartUpdated(false)}
+          />
+        </div>
+      )}
+      {error && (
+        <div className="mt-8">
+          <Alert
+            title="Something went wrong trying to add an item to your cart."
+            type="error"
+            description=""
+            onClick={() => setError(false)}
+          />
+        </div>
+      )}
+
+      {listview && viewType === 'listview' ? (
+        <div className="w-full">
+          <div className="ds-sdk-product-list__list-view-default mt-md grid grid-cols-none pt-[15px] w-full gap-[10px]">
+            {sanitizedProducts?.map((product) => (
+              <ProductItem
+                key={product?.productView?.id}
+                item={product}
+                currencySymbol={currencySymbol}
+                currencyRate={currencyRate}
+                setRoute={setRoute}
+                refineProduct={refineProduct}
+                setCartUpdated={setCartUpdated}
+                setItemAdded={setItemAdded}
+                addToCart={addToCart}
+                setError={setError}
+              />
+            ))}
+          </div>
+        </div>
+      ) : (
+        <div
+          style={{
+            gridTemplateColumns: `repeat(${numberOfColumns}, minmax(0, 1fr))`,
+          }}
+          className="ds-sdk-product-list__grid mt-md grid gap-y-8 gap-x-2xl xl:gap-x-8"
+        >
+          {sanitizedProducts?.map((product) => (
+            <ProductItem
+              key={product?.productView?.id}
+              item={product}
+              currencySymbol={currencySymbol}
+              currencyRate={currencyRate}
+              setRoute={setRoute}
+              refineProduct={refineProduct}
+              setCartUpdated={setCartUpdated}
+              setItemAdded={setItemAdded}
+              addToCart={addToCart}
+              setError={setError}
+            />
+          ))}
+        </div>
+      )}
+    </div>
+  );
+};
+
+export default ProductList;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductList/index.js b/packages/extensions/venia-pwa-live-search/src/components/ProductList/index.js
new file mode 100644
index 0000000000..97bfb73160
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductList/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export { default as ProductList } from './ProductList';
+export * from './ProductList';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ProductList/product-list.css b/packages/extensions/venia-pwa-live-search/src/components/ProductList/product-list.css
new file mode 100644
index 0000000000..ccf520bbf5
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ProductList/product-list.css
@@ -0,0 +1,18 @@
+/* https://cssguidelin.es/#bem-like-naming */
+.sfsdk-product-list {
+}
+
+/* Extra small devices (phones, 600px and down) */
+/* @media only screen and (max-width: 600px) { } */
+
+/* Small devices (portrait tablets and large phones, 600px and up) */
+/* @media only screen and (min-width: 600px) { } */
+
+/* Medium devices (landscape tablets, 768px and up) */
+/* @media only screen and (min-width: 768px) { } */
+
+/* Large devices (laptops/desktops, 992px and up) */
+/* @media only screen and (min-width: 992px) { } */
+
+/* Extra large devices (large laptops and desktops, 1200px and up) */
+/* @media only screen and (min-width: 1200px) { } */
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SearchBar/SearchBar.jsx b/packages/extensions/venia-pwa-live-search/src/components/SearchBar/SearchBar.jsx
new file mode 100644
index 0000000000..5e8799aee1
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SearchBar/SearchBar.jsx
@@ -0,0 +1,33 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+export const SearchBar = ({
+  phrase,
+  onKeyPress,
+  placeholder,
+  onClear, // included for completeness, though unused in this component
+  ...rest
+}) => {
+  return (
+    <div className="relative ds-sdk-search-bar">
+      <input
+        id="search"
+        type="text"
+        value={phrase}
+        onKeyPress={onKeyPress}
+        className="border border-gray-300 text-gray-800 text-sm block-display p-xs pr-lg ds-sdk-search-bar__input"
+        placeholder={placeholder}
+        autoComplete="off"
+        {...rest}
+      />
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SearchBar/index.js b/packages/extensions/venia-pwa-live-search/src/components/SearchBar/index.js
new file mode 100644
index 0000000000..982c66f7cb
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SearchBar/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './SearchBar';
+export { SearchBar as default } from './SearchBar';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Shimmer/Shimmer.css b/packages/extensions/venia-pwa-live-search/src/components/Shimmer/Shimmer.css
new file mode 100644
index 0000000000..18ef81a5e7
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Shimmer/Shimmer.css
@@ -0,0 +1,82 @@
+.card {
+    width: 250px;
+    margin: 10px auto;
+    box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
+    padding: 20px;
+}
+@keyframes placeholderShimmer {
+    0% {
+        background-position: -468px 0;
+    }
+
+    100% {
+        background-position: 468px 0;
+    }
+}
+
+.shimmer-animation {
+    background-color: #f6f7f8;
+    background-image: linear-gradient(
+        to right,
+        #f6f7f8 0%,
+        #edeef1 20%,
+        #f6f7f8 40%,
+        #f6f7f8 100%
+    );
+    background-repeat: no-repeat;
+    background-size: 800px 104px;
+    animation-duration: 1s;
+    animation-fill-mode: forwards;
+    animation-iteration-count: infinite;
+    animation-name: placeholderShimmer;
+    animation-timing-function: linear;
+}
+
+.loader {
+    &-shimmer {
+        &-banner {
+            height: 22rem;
+            background-size: 800px 22rem;
+            border-radius: 5px;
+            margin-bottom: 12px;
+        }
+
+        &-header {
+            display: flex;
+            justify-content: space-between;
+            margin-bottom: 5px;
+        }
+
+        &-title {
+            height: 25px;
+            flex: 0 0 auto;
+            width: 120px;
+        }
+
+        &-rating {
+            height: 25px;
+            flex: 0 0 auto;
+            width: 70px;
+        }
+
+        &-list {
+            height: 20px;
+            width: 190px;
+            margin-bottom: 5px;
+
+            &:last-child {
+                margin-bottom: 0;
+            }
+        }
+
+        &-info {
+            height: 20px;
+            width: 220px;
+            margin-bottom: 5px;
+
+            &:last-child {
+                margin-bottom: 0;
+            }
+        }
+    }
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Shimmer/Shimmer.jsx b/packages/extensions/venia-pwa-live-search/src/components/Shimmer/Shimmer.jsx
new file mode 100644
index 0000000000..8ab82e2e9e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Shimmer/Shimmer.jsx
@@ -0,0 +1,66 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { useSensor } from '../../context'; // Adjust relative path if needed
+
+import ButtonShimmer from '../ButtonShimmer';
+import FacetsShimmer from '../FacetsShimmer';
+import ProductCardShimmer from '../ProductCardShimmer';
+
+const Shimmer = () => {
+  const productCardArray = Array.from({ length: 8 });
+  const facetsArray = Array.from({ length: 4 });
+  const { screenSize } = useSensor();
+  const numberOfColumns = screenSize.columns;
+
+  return (
+    <div className="ds-widgets bg-body py-2">
+      <div className="flex">
+        <div className="sm:flex ds-widgets-_actions relative max-w-[21rem] w-full h-full px-2 flex-col overflow-y-auto">
+          <div className="ds-widgets_actions_header flex justify-between items-center mb-md" />
+          <div className="flex pb-4 w-full h-full">
+            <div className="ds-sdk-filter-button-desktop">
+              <button className="flex items-center bg-gray-100 ring-black ring-opacity-5 rounded-md p-sm text-sm h-[32px]">
+                <ButtonShimmer />
+              </button>
+            </div>
+          </div>
+          <div className="ds-plp-facets flex flex-col">
+            <form className="ds-plp-facets__list border-t border-gray-200">
+              {facetsArray.map((_, index) => (
+                <FacetsShimmer key={index} />
+              ))}
+            </form>
+          </div>
+        </div>
+        <div className="ds-widgets_results flex flex-col items-center pt-16 w-full h-full">
+          <div className="flex flex-col max-w-5xl lg:max-w-7xl ml-auto w-full h-full">
+            <div className="flex justify-end mb-[1px]">
+              <ButtonShimmer />
+            </div>
+          </div>
+          <div
+            className="ds-sdk-product-list__grid mt-md grid-cols-1 gap-y-8 gap-x-md sm:grid-cols-2 md:grid-cols-3 xl:gap-x-4 pl-8"
+            style={{
+              display: 'grid',
+              gridTemplateColumns: `repeat(${numberOfColumns}, minmax(0, 1fr))`,
+            }}
+          >
+            {productCardArray.map((_, index) => (
+              <ProductCardShimmer key={index} />
+            ))}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default Shimmer;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Shimmer/index.js b/packages/extensions/venia-pwa-live-search/src/components/Shimmer/index.js
new file mode 100644
index 0000000000..9fcd7f008b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Shimmer/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Shimmer';
+export { default } from './Shimmer';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Slider/Slider.css b/packages/extensions/venia-pwa-live-search/src/components/Slider/Slider.css
new file mode 100644
index 0000000000..337274817b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Slider/Slider.css
@@ -0,0 +1,61 @@
+.slider-container {
+    margin: 0 auto;
+    position: relative;
+    padding-top: 20px;
+}
+
+.range-slider {
+    appearance: none;
+    width: 100%;
+    height: 10px;
+    border-radius: 5px;
+    background: linear-gradient(to right, #dddddd 0%, #cccccc 100%);
+    outline: none;
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+}
+
+.range-slider::-webkit-slider-thumb {
+    appearance: none;
+    width: 20px;
+    height: 20px;
+    border-radius: 50%;
+    background: #ffffff;
+    cursor: pointer;
+}
+
+.range-slider::-moz-range-thumb {
+    appearance: none;
+    width: 20px;
+    height: 20px;
+    border-radius: 50%;
+    background: #ffffff;
+    cursor: pointer;
+}
+
+.selected-price {
+    position: absolute;
+    top: -5px;
+    left: 50%;
+    transform: translateX(-50%);
+    padding: 5px 10px;
+    border-radius: 5px;
+    font-size: 14px;
+    font-weight: 600;
+    color: #333;
+    text-align: center;
+}
+
+.price-range-display {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 0px;
+}
+
+.min-price,
+.max-price {
+    font-size: 14px;
+    font-weight: 600;
+    color: #333;
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Slider/Slider.jsx b/packages/extensions/venia-pwa-live-search/src/components/Slider/Slider.jsx
new file mode 100644
index 0000000000..1cb496ea0b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Slider/Slider.jsx
@@ -0,0 +1,103 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useEffect, useState } from 'react';
+
+import '../Slider/Slider.css';
+
+import { useProducts, useSearch } from '../../context';
+import useSliderFacet from '../../hooks/useSliderFacet';
+
+export const Slider = ({ filterData }) => {
+  const productsCtx = useProducts();
+  const [isFirstRender, setIsFirstRender] = useState(true);
+  const preSelectedToPrice = productsCtx.variables.filter?.find(
+    (obj) => obj.attribute === 'price'
+  )?.range?.to;
+
+  const searchCtx = useSearch();
+
+  const [selectedPrice, setSelectedPrice] = useState(
+    !preSelectedToPrice
+      ? filterData.buckets[filterData.buckets.length - 1].to
+      : preSelectedToPrice
+  );
+
+  const { onChange } = useSliderFacet(filterData);
+
+  useEffect(() => {
+    if (
+      searchCtx?.filters?.length === 0 ||
+      !searchCtx?.filters?.find((obj) => obj.attribute === 'price')
+    ) {
+      setSelectedPrice(filterData.buckets[filterData.buckets.length - 1].to);
+    }
+  }, [searchCtx]);
+
+  useEffect(() => {
+    if (!isFirstRender) {
+      setSelectedPrice(filterData.buckets[filterData.buckets.length - 1].to);
+    }
+    setIsFirstRender(false);
+  }, [filterData.buckets]);
+
+  const handleSliderChange = (event) => {
+    onChange(filterData.buckets[0].from, parseInt(event.target.value, 10));
+  };
+
+  const handleNewPrice = (event) => {
+    setSelectedPrice(parseInt(event.target.value, 10));
+  };
+
+  const formatLabel = (price) => {
+    const currencyRate = productsCtx.currencyRate || '1';
+    const currencySymbol = productsCtx.currencySymbol || '$';
+
+    const value =
+      price && parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)
+        ? (parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)).toFixed(2)
+        : 0;
+
+    return `${currencySymbol}${value}`;
+  };
+
+  return (
+    <>
+      <p className="pt-md">{filterData.title}</p>
+      <div className="ds-sdk-slider slider-container">
+        <input
+          type="range"
+          id="price-range"
+          className="w-full h-3 bg-gray-200 rounded-lg appearance-none cursor-pointer range-lg dark:bg-gray-700"
+          min={filterData.buckets[0].from}
+          max={filterData.buckets[filterData.buckets.length - 1].to}
+          value={selectedPrice}
+          onChange={handleNewPrice}
+          onMouseUp={handleSliderChange}
+          onTouchEnd={handleSliderChange}
+          onKeyUp={handleSliderChange}
+        />
+        <span className="selected-price">{formatLabel(selectedPrice)}</span>
+        <div className="price-range-display">
+          <span className="min-price">
+            {formatLabel(filterData.buckets[0].from)}
+          </span>
+          <span className="max-price">
+            {formatLabel(
+              filterData.buckets[filterData.buckets.length - 1].to
+            )}
+          </span>
+        </div>
+      </div>
+      <div className="ds-sdk-input__border border-t mt-md border-gray-200" />
+    </>
+  );
+};
+
+export default Slider;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/Slider/index.jsx b/packages/extensions/venia-pwa-live-search/src/components/Slider/index.jsx
new file mode 100644
index 0000000000..53fdae587f
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/Slider/index.jsx
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './Slider';
+export { default } from './Slider';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/SliderDoubleControl.css b/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/SliderDoubleControl.css
new file mode 100644
index 0000000000..a579cc8276
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/SliderDoubleControl.css
@@ -0,0 +1,83 @@
+.range_container {
+    display: flex;
+    flex-direction: column;
+    width: auto;
+    margin-top: 10px;
+    margin-bottom: 20px;
+}
+
+.sliders_control {
+    position: relative;
+}
+
+.form_control {
+    display: none;
+}
+
+input[type='range']::-webkit-slider-thumb {
+    -webkit-appearance: none;
+    pointer-events: all;
+    width: 12px;
+    height: 12px;
+    background-color: #383838;
+    border-radius: 50%;
+    box-shadow: 0 0 0 1px #c6c6c6;
+    cursor: pointer;
+}
+
+input[type='range']::-moz-range-thumb {
+    -webkit-appearance: none;
+    pointer-events: all;
+    width: 12px;
+    height: 12px;
+    background-color: #383838;
+    border-radius: 50%;
+    box-shadow: 0 0 0 1px #c6c6c6;
+    cursor: pointer;
+}
+
+input[type='range']::-webkit-slider-thumb:hover {
+    background: #383838;
+}
+
+input[type='number'] {
+    color: #8a8383;
+    width: 50px;
+    height: 30px;
+    font-size: 20px;
+    border: none;
+}
+
+input[type='number']::-webkit-inner-spin-button,
+input[type='number']::-webkit-outer-spin-button {
+    opacity: 1;
+}
+
+input[type='range'] {
+    -webkit-appearance: none;
+    appearance: none;
+    height: 2px;
+    width: 100%;
+    position: absolute;
+    background-color: #c6c6c6;
+    pointer-events: none;
+}
+
+.fromSlider {
+    height: 0;
+    z-index: 1;
+}
+
+.toSlider {
+    z-index: 2;
+}
+
+.price-range-display {
+    text-wrap: nowrap;
+    font-size: 0.8em;
+}
+
+.fromSlider,
+.toSlider {
+    box-shadow: none !important;
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/SliderDoubleControl.jsx b/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/SliderDoubleControl.jsx
new file mode 100644
index 0000000000..a663d94867
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/SliderDoubleControl.jsx
@@ -0,0 +1,220 @@
+import React, { useEffect, useState } from 'react';
+import './SliderDoubleControl.css';
+
+import { useProducts, useSearch } from '../../context';
+import useSliderFacet from '../../hooks/useSliderFacet';
+
+export const SliderDoubleControl = ({ filterData }) => {
+  const productsCtx = useProducts();
+  const searchCtx = useSearch();
+  const min = filterData.buckets[0].from;
+  const max = filterData.buckets[filterData.buckets.length - 1].to;
+
+  const preSelectedToPrice = productsCtx.variables.filter?.find(
+    obj => obj.attribute === 'price'
+  )?.range?.to;
+  const preSelectedFromPrice = productsCtx.variables.filter?.find(
+    obj => obj.attribute === 'price'
+  )?.range?.from;
+
+  const [minVal, setMinVal] = useState(
+    preSelectedFromPrice !== null && preSelectedFromPrice !== undefined ? preSelectedFromPrice : min
+  );
+  const [maxVal, setMaxVal] = useState(
+    preSelectedToPrice !== null && preSelectedToPrice !== undefined ? preSelectedToPrice : max
+  );
+  
+  const { onChange } = useSliderFacet(filterData);
+
+  const fromSliderId = `fromSlider_${filterData.attribute}`;
+  const toSliderId = `toSlider_${filterData.attribute}`;
+  const fromInputId = `fromInput_${filterData.attribute}`;
+  const toInputId = `toInput_${filterData.attribute}`;
+
+  useEffect(() => {
+    if (
+      searchCtx?.filters?.length === 0 ||
+      !searchCtx?.filters?.find(obj => obj.attribute === filterData.attribute)
+    ) {
+      setMinVal(min);
+      setMaxVal(max);
+    }
+  }, [searchCtx]);
+
+  useEffect(() => {
+    const getParsed = (fromEl, toEl) => [
+      parseInt(fromEl.value, 10),
+      parseInt(toEl.value, 10)
+    ];
+
+    const fillSlider = (from, to, sliderColor, rangeColor, controlSlider) => {
+      const rangeDistance = to.max - to.min;
+      const fromPosition = from.value - to.min;
+      const toPosition = to.value - to.min;
+      controlSlider.style.background = `linear-gradient(
+        to right,
+        ${sliderColor} 0%,
+        ${sliderColor} ${(fromPosition / rangeDistance) * 100}%,
+        ${rangeColor} ${(fromPosition / rangeDistance) * 100}%,
+        ${rangeColor} ${(toPosition / rangeDistance) * 100}%,
+        ${sliderColor} ${(toPosition / rangeDistance) * 100}%,
+        ${sliderColor} 100%)`;
+    };
+
+    const controlFromSlider = (fromSlider, toSlider, fromInput) => {
+      const [from, to] = getParsed(fromSlider, toSlider);
+      fillSlider(fromSlider, toSlider, '#C6C6C6', '#383838', toSlider);
+      if (from > to) {
+        setMinVal(to);
+        fromSlider.value = to;
+        fromInput.value = to;
+      } else {
+        fromInput.value = from;
+      }
+    };
+
+    const controlToSlider = (fromSlider, toSlider, toInput) => {
+      const [from, to] = getParsed(fromSlider, toSlider);
+      fillSlider(fromSlider, toSlider, '#C6C6C6', '#383838', toSlider);
+      if (from <= to) {
+        toSlider.value = to;
+        toInput.value = to;
+      } else {
+        setMaxVal(from);
+        toInput.value = from;
+        toSlider.value = from;
+      }
+    };
+
+    const controlFromInput = (fromSlider, fromInput, toInput, controlSlider) => {
+      const [from, to] = getParsed(fromInput, toInput);
+      fillSlider(fromInput, toInput, '#C6C6C6', '#383838', controlSlider);
+      if (from > to) {
+        fromSlider.value = to;
+        fromInput.value = to;
+      } else {
+        fromSlider.value = from;
+      }
+    };
+
+    const controlToInput = (toSlider, fromInput, toInput, controlSlider) => {
+      const [from, to] = getParsed(fromInput, toInput);
+      fillSlider(fromInput, toInput, '#C6C6C6', '#383838', controlSlider);
+      if (from <= to) {
+        toSlider.value = to;
+        toInput.value = to;
+      } else {
+        toInput.value = from;
+      }
+    };
+
+    const fromSlider = document.getElementById(fromSliderId);
+    const toSlider = document.getElementById(toSliderId);
+    const fromInput = document.getElementById(fromInputId);
+    const toInput = document.getElementById(toInputId);
+
+    if (!fromSlider || !toSlider || !fromInput || !toInput) return;
+
+    fillSlider(fromSlider, toSlider, '#C6C6C6', '#383838', toSlider);
+
+    fromSlider.oninput = () => controlFromSlider(fromSlider, toSlider, fromInput);
+    toSlider.oninput = () => controlToSlider(fromSlider, toSlider, toInput);
+    fromInput.oninput = () =>
+      controlFromInput(fromSlider, fromInput, toInput, toSlider);
+    toInput.oninput = () =>
+      controlToInput(toSlider, fromInput, toInput, toSlider);
+  }, [minVal, maxVal]);
+
+  const formatLabel = (price) => {
+    const currencyRate = productsCtx.currencyRate || 1;
+    const currencySymbol = productsCtx.currencySymbol || '$';
+    const label = `${currencySymbol}${
+      price ? (parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)).toFixed(2) : 0
+    }`;
+    return label;
+  };
+
+  return (
+    <div className="ds-sdk-input pt-md">
+      <label className="ds-sdk-input__label text-base font-normal text-gray-900">
+        {filterData.title}
+      </label>
+
+      <div className="ds-sdk-slider range_container">
+        <div className="sliders_control">
+          <input
+            className="ds-sdk-slider__from fromSlider"
+            id={fromSliderId}
+            type="range"
+            value={minVal}
+            min={min}
+            max={max}
+            onInput={({ target }) => setMinVal(Math.round(Number(target.value)))}
+            onMouseUp={() => onChange(minVal, maxVal)}
+            onTouchEnd={() => onChange(minVal, maxVal)}
+            onKeyUp={() => onChange(minVal, maxVal)}
+          />
+          <input
+            className="ds-sdk-slider__to toSlider"
+            id={toSliderId}
+            type="range"
+            value={maxVal}
+            min={min}
+            max={max}
+            onInput={({ target }) => setMaxVal(Math.round(Number(target.value)))}
+            onMouseUp={() => onChange(minVal, maxVal)}
+            onTouchEnd={() => onChange(minVal, maxVal)}
+            onKeyUp={() => onChange(minVal, maxVal)}
+          />
+        </div>
+
+        <div className="form_control">
+          <div className="form_control_container">
+            <div className="form_control_container__time">Min</div>
+            <input
+              className="form_control_container__time__input"
+              type="number"
+              id={fromInputId}
+              value={minVal}
+              min={min}
+              max={max}
+              onInput={({ target }) => setMinVal(Math.round(Number(target.value)))}
+              onMouseUp={() => onChange(minVal, maxVal)}
+              onTouchEnd={() => onChange(minVal, maxVal)}
+              onKeyUp={() => onChange(minVal, maxVal)}
+            />
+          </div>
+          <div className="form_control_container">
+            <div className="form_control_container__time">Max</div>
+            <input
+              className="form_control_container__time__input"
+              type="number"
+              id={toInputId}
+              value={maxVal}
+              min={min}
+              max={max}
+              onInput={({ target }) => setMaxVal(Math.round(Number(target.value)))}
+              onMouseUp={() => onChange(minVal, maxVal)}
+              onTouchEnd={() => onChange(minVal, maxVal)}
+              onKeyUp={() => onChange(minVal, maxVal)}
+            />
+          </div>
+        </div>
+      </div>
+
+      <div className={`price-range-display__${filterData.attribute} pb-3`}>
+        <span className="ml-sm block-display text-sm font-light text-gray-700">
+          Between{' '}
+          <span className="min-price text-gray-900 font-semibold">
+            {formatLabel(minVal)}
+          </span>{' '}
+          and{' '}
+          <span className="max-price text-gray-900 font-semibold">
+            {formatLabel(maxVal)}
+          </span>
+        </span>
+      </div>
+      <div className="ds-sdk-input__border border-t mt-md border-gray-200" />
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/index.js b/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/index.js
new file mode 100644
index 0000000000..1b85d041c9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SliderDoubleControl/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './SliderDoubleControl';
+export { SliderDoubleControl as default } from './SliderDoubleControl';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SortDropdown/SortDropdown.jsx b/packages/extensions/venia-pwa-live-search/src/components/SortDropdown/SortDropdown.jsx
new file mode 100644
index 0000000000..8badf5f563
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SortDropdown/SortDropdown.jsx
@@ -0,0 +1,126 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useEffect, useRef } from 'react';
+import { useTranslation } from '../../context/translation';
+import { useAccessibleDropdown } from '../../hooks/useAccessibleDropdown';
+import Chevron from '../../icons/chevron.svg';
+import SortIcon from '../../icons/sort.svg';
+
+export const SortDropdown = ({ value, sortOptions, onChange }) => {
+  const sortOptionButton = useRef(null);
+  const sortOptionMenu = useRef(null);
+
+  const selectedOption = sortOptions.find(e => e.value === value);
+
+  const translation = useTranslation();
+  const sortOptionTranslation = translation.SortDropdown.option;
+  const sortOption = sortOptionTranslation.replace(
+    '{selectedOption}',
+    `${selectedOption?.label}`
+  );
+
+  const {
+    isDropdownOpen,
+    setIsDropdownOpen,
+    activeIndex,
+    setActiveIndex,
+    select,
+    setIsFocus,
+    listRef
+  } = useAccessibleDropdown({
+    options: sortOptions,
+    value,
+    onChange
+  });
+
+  useEffect(() => {
+    const menuRef = sortOptionMenu.current;
+
+    const handleBlur = () => {
+      setIsFocus(false);
+      setIsDropdownOpen(false);
+    };
+
+    const handleFocus = () => {
+      if (menuRef?.parentElement?.querySelector(':hover') !== menuRef) {
+        setIsFocus(false);
+        setIsDropdownOpen(false);
+      }
+    };
+
+    menuRef?.addEventListener('blur', handleBlur);
+    menuRef?.addEventListener('focusin', handleFocus);
+    menuRef?.addEventListener('focusout', handleFocus);
+
+    return () => {
+      menuRef?.removeEventListener('blur', handleBlur);
+      menuRef?.removeEventListener('focusin', handleFocus);
+      menuRef?.removeEventListener('focusout', handleFocus);
+    };
+  }, [sortOptionMenu]);
+
+  return (
+    <div
+      ref={sortOptionMenu}
+      className="ds-sdk-sort-dropdown relative inline-block text-left bg-gray-100 rounded-md outline outline-1 outline-gray-200 hover:outline-gray-600 h-[32px] z-99"
+    >
+      <button
+        className="group flex justify-center items-center font-normal text-sm text-gray-700 rounded-md hover:cursor-pointer border-none bg-transparent hover:border-none hover:bg-transparent focus:border-none focus:bg-transparent active:border-none active:bg-transparent active:shadow-none h-full w-full px-sm"
+        ref={sortOptionButton}
+        onClick={() => setIsDropdownOpen(!isDropdownOpen)}
+        onFocus={() => setIsFocus(false)}
+        onBlur={() => setIsFocus(false)}
+      >
+        <img src={SortIcon} className="h-md w-md mr-sm stroke-gray-600 m-auto" height="32px" width="32px" />
+        {/* <SortIcon className="h-md w-md mr-sm stroke-gray-600 m-auto" /> */}
+        {selectedOption ? sortOption : translation.SortDropdown.title}
+        <img src={Chevron} className={`flex-shrink-0 m-auto ml-sm h-md w-md stroke-1 stroke-gray-600 ${
+            isDropdownOpen ? '' : 'rotate-180'
+          }`} height="32px" width="32px" />
+        {/* <Chevron
+          className={`flex-shrink-0 m-auto ml-sm h-md w-md stroke-1 stroke-gray-600 ${
+            isDropdownOpen ? '' : 'rotate-180'
+          }`}
+        /> */}
+      </button>
+      {isDropdownOpen && (
+        <ul
+          ref={listRef}
+          tabIndex={-1}
+          className="ds-sdk-sort-dropdown__items origin-top-right absolute hover:cursor-pointer right-0 w-full rounded-md shadow-2xl bg-white ring-1 ring-black ring-opacity-5 focus:outline-none mt-2 z-20"
+        >
+          {sortOptions.map((option, i) => (
+            <li
+              key={i}
+              aria-selected={option.value === selectedOption?.value}
+              onMouseOver={() => setActiveIndex(i)}
+              className={`py-xs hover:bg-gray-100 hover:text-gray-900 ${
+                i === activeIndex ? 'bg-gray-100 text-gray-900' : ''
+              }`}
+            >
+              <a
+                className={`ds-sdk-sort-dropdown__items--item block-display px-md py-sm text-sm mb-0
+                no-underline active:no-underline focus:no-underline hover:no-underline
+                hover:text-gray-900 ${
+                  option.value === selectedOption?.value
+                    ? 'ds-sdk-sort-dropdown__items--item-selected font-semibold text-gray-900'
+                    : 'font-normal text-gray-800'
+                }`}
+                onClick={() => select(option.value)}
+              >
+                {option.label}
+              </a>
+            </li>
+          ))}
+        </ul>
+      )}
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SortDropdown/index.js b/packages/extensions/venia-pwa-live-search/src/components/SortDropdown/index.js
new file mode 100644
index 0000000000..2bf7705621
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SortDropdown/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './SortDropdown';
+export { SortDropdown as default } from './SortDropdown';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SwatchButton/SwatchButton.jsx b/packages/extensions/venia-pwa-live-search/src/components/SwatchButton/SwatchButton.jsx
new file mode 100644
index 0000000000..cf8469c569
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SwatchButton/SwatchButton.jsx
@@ -0,0 +1,72 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+export const SwatchButton = ({ id, value, type, checked, onClick }) => {
+  const outlineColor = checked
+    ? 'border-black'
+    : type === 'COLOR_HEX'
+    ? 'border-transparent'
+    : 'border-gray';
+
+  if (type === 'COLOR_HEX') {
+    const color = value.toLowerCase();
+    const className = `min-w-[32px] rounded-full p-sm border border-[1.5px] ${outlineColor} h-[32px] outline-transparent`;
+    const isWhite = color === '#ffffff' || color === '#fff';
+    return (
+      <div className={`ds-sdk-swatch-button_${id}`}>
+        <button
+          key={id}
+          className={className}
+          style={{
+            backgroundColor: color,
+            border: !checked && isWhite ? '1px solid #ccc' : undefined,
+          }}
+          onClick={onClick}
+          aria-checked={checked}
+        />
+      </div>
+    );
+  }
+
+  if (type === 'IMAGE' && value) {
+    const className = `object-cover object-center min-w-[32px] rounded-full p-sm border border-[1.5px] ${outlineColor} h-[32px] outline-transparent`;
+    const style = {
+      background: `url(${value}) no-repeat center`,
+      backgroundSize: 'initial',
+    };
+    return (
+      <div className={`ds-sdk-swatch-button_${value}`}>
+        <button
+          key={id}
+          className={className}
+          style={style}
+          onClick={onClick}
+          aria-checked={checked}
+        />
+      </div>
+    );
+  }
+
+  // Assume TEXT type
+  const className = `flex items-center bg-white rounded-full p-sm border border-[1.5px]h-[32px] ${outlineColor} outline-transparent`;
+  return (
+    <div className={`ds-sdk-swatch-button_${value}`}>
+      <button
+        key={id}
+        className={className}
+        onClick={onClick}
+        aria-checked={checked}
+      >
+        {value}
+      </button>
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SwatchButton/index.js b/packages/extensions/venia-pwa-live-search/src/components/SwatchButton/index.js
new file mode 100644
index 0000000000..98febefcb2
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SwatchButton/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './SwatchButton';
+export { SwatchButton as default } from './SwatchButton';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SwatchButtonGroup/SwatchButtonGroup.jsx b/packages/extensions/venia-pwa-live-search/src/components/SwatchButtonGroup/SwatchButtonGroup.jsx
new file mode 100644
index 0000000000..816aa5968b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SwatchButtonGroup/SwatchButtonGroup.jsx
@@ -0,0 +1,86 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { SwatchButton } from '../SwatchButton';
+
+const MAX_SWATCHES = 5;
+
+export const SwatchButtonGroup = ({
+  isSelected,
+  swatches,
+  showMore,
+  productUrl,
+  onClick,
+  sku
+}) => {
+  const moreSwatches = swatches.length > MAX_SWATCHES;
+  const numberOfOptions = moreSwatches ? MAX_SWATCHES - 1 : swatches.length;
+
+  return (
+    <div className="ds-sdk-product-item__product-swatch-group flex column items-center space-x-2">
+      {moreSwatches ? (
+        <div className="flex">
+          {swatches.slice(0, numberOfOptions).map((swatch) => {
+            const checked = isSelected(swatch.id);
+            return (
+              swatch &&
+              swatch.type === 'COLOR_HEX' && (
+                <div
+                  key={swatch.id}
+                  className="ds-sdk-product-item__product-swatch-item mr-2 text-sm text-primary"
+                >
+                  <SwatchButton
+                    id={swatch.id}
+                    value={swatch.value}
+                    type={swatch.type}
+                    checked={!!checked}
+                    onClick={() => onClick([swatch.id], sku)}
+                  />
+                </div>
+              )
+            );
+          })}
+          <a href={productUrl} className="hover:no-underline">
+            <div className="ds-sdk-product-item__product-swatch-item text-sm text-primary">
+              <SwatchButton
+                id="show-more"
+                value={`+${swatches.length - numberOfOptions}`}
+                type="TEXT"
+                checked={false}
+                onClick={showMore}
+              />
+            </div>
+          </a>
+        </div>
+      ) : (
+        swatches.slice(0, numberOfOptions).map((swatch) => {
+          const checked = isSelected(swatch.id);
+          return (
+            swatch &&
+            swatch.type === 'COLOR_HEX' && (
+              <div
+                key={swatch.id}
+                className="ds-sdk-product-item__product-swatch-item text-sm text-primary"
+              >
+                <SwatchButton
+                  id={swatch.id}
+                  value={swatch.value}
+                  type={swatch.type}
+                  checked={!!checked}
+                  onClick={() => onClick([swatch.id], sku)}
+                />
+              </div>
+            )
+          );
+        })
+      )}
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/SwatchButtonGroup/index.js b/packages/extensions/venia-pwa-live-search/src/components/SwatchButtonGroup/index.js
new file mode 100644
index 0000000000..98ef05462f
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/SwatchButtonGroup/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './SwatchButtonGroup';
+export { SwatchButtonGroup as default } from './SwatchButtonGroup';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ViewSwitcher/ViewSwitcher.jsx b/packages/extensions/venia-pwa-live-search/src/components/ViewSwitcher/ViewSwitcher.jsx
new file mode 100644
index 0000000000..48cddf4708
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ViewSwitcher/ViewSwitcher.jsx
@@ -0,0 +1,46 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { useProducts } from '../../context';
+import { handleViewType } from '../../utils/handleUrlFilters';
+
+import GridView from '../../icons/gridView.svg';
+import ListView from '../../icons/listView.svg';
+
+const ViewSwitcher = () => {
+  const { viewType, setViewType } = useProducts();
+
+  const handleClick = (newViewType) => {
+    handleViewType(newViewType);
+    setViewType(newViewType);
+  };
+
+  return (
+    <div className="flex justify-between">
+      <button
+        className={`flex items-center ${
+          viewType === 'gridview' ? 'bg-gray-100' : ''
+        } ring-black ring-opacity-5 p-sm text-sm h-[32px] border border-gray-300`}
+        onClick={() => handleClick('gridview')}
+      >
+        <GridView className="h-[20px] w-[20px]" />
+      </button>
+      <button
+        className={`flex items-center ${
+          viewType === 'listview' ? 'bg-gray-100' : ''
+        } ring-black ring-opacity-5 p-sm text-sm h-[32px] border border-gray-300`}
+        onClick={() => handleClick('listview')}
+      >
+        <ListView className="h-[20px] w-[20px]" />
+      </button>
+    </div>
+  );
+};
+
+export default ViewSwitcher;
diff --git a/packages/extensions/venia-pwa-live-search/src/components/ViewSwitcher/index.js b/packages/extensions/venia-pwa-live-search/src/components/ViewSwitcher/index.js
new file mode 100644
index 0000000000..c3977268d2
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/ViewSwitcher/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './ViewSwitcher';
+export { default } from './ViewSwitcher';
diff --git a/packages/extensions/venia-pwa-live-search/src/components/WishlistButton/WishlistButton.jsx b/packages/extensions/venia-pwa-live-search/src/components/WishlistButton/WishlistButton.jsx
new file mode 100644
index 0000000000..1d5cab1b97
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/WishlistButton/WishlistButton.jsx
@@ -0,0 +1,67 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+
+import { useWishlist } from '../../context';
+import EmptyHeart from '../../icons/emptyHeart.svg';
+import FilledHeart from '../../icons/filledHeart.svg';
+import { classNames } from '../../utils/dom';
+
+export const WishlistButton = ({ type, productSku }) => {
+  const { isAuthorized, wishlist, addItemToWishlist, removeItemFromWishlist } =
+    useWishlist();
+
+  const wishlistItemStatus = wishlist?.items_v2?.items.find(
+    (ws) => ws.product.sku === productSku
+  );
+  const isWishlistItem = !!wishlistItemStatus;
+
+  const heart = isWishlistItem ? <FilledHeart /> : <EmptyHeart />;
+
+  const preventBubbleUp = (e) => {
+    e.stopPropagation();
+    e.preventDefault();
+  };
+
+  const handleAddWishlist = (e) => {
+    preventBubbleUp(e);
+    const selectedWishlistId = wishlist?.id;
+    if (isAuthorized) {
+      addItemToWishlist(selectedWishlistId, {
+        sku: productSku,
+        quantity: 1,
+      });
+    } else {
+      // FIXME: Update this for AEM/CIF compatibility if needed
+      window.location.href = `${window.origin}/customer/account/login/`;
+    }
+  };
+
+  const handleRemoveWishlist = (e) => {
+    preventBubbleUp(e);
+    if (!wishlistItemStatus) return;
+    removeItemFromWishlist(wishlist?.id, wishlistItemStatus.id);
+  };
+
+  return (
+    <div
+      className={classNames(
+        `ds-sdk-wishlist-${type}-button mt-[-2px]`,
+        type !== 'inLineWithName'
+          ? 'w-[30px] absolute top-0 right-0'
+          : 'w-[24px]'
+      )}
+    >
+      <div onClick={isWishlistItem ? handleRemoveWishlist : handleAddWishlist}>
+        {heart}
+      </div>
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/components/WishlistButton/index.js b/packages/extensions/venia-pwa-live-search/src/components/WishlistButton/index.js
new file mode 100644
index 0000000000..dbf14fe055
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/components/WishlistButton/index.js
@@ -0,0 +1,11 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './WishlistButton';
+export { default } from './WishlistButton';
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/App.jsx b/packages/extensions/venia-pwa-live-search/src/containers/App.jsx
new file mode 100644
index 0000000000..b23542dde0
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/App.jsx
@@ -0,0 +1,145 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useState } from 'react';
+import { FilterButton } from '../components/FilterButton';
+import Loading from '../components/Loading';
+import Shimmer from '../components/Shimmer';
+
+import { CategoryFilters } from '../components/CategoryFilters';
+import { SelectedFilters } from '../components/Facets';
+import {
+  useProducts,
+  useSearch,
+  useSensor,
+  useStore,
+  useTranslation
+} from '../context';
+import ProductsContainer from './ProductsContainer';
+import { ProductsHeader } from './ProductsHeader';
+
+const App = () => {
+  const searchCtx = useSearch();
+  const productsCtx = useProducts();
+  const { screenSize } = useSensor();
+  const translation = useTranslation();
+  const { displayMode } = useStore().config;
+  const [showFilters, setShowFilters] = useState(true);
+
+  const loadingLabel = translation.Loading.title;
+
+  let title = productsCtx.categoryName || '';
+  if (productsCtx.variables.phrase) {
+    const text = translation.CategoryFilters.results;
+    title = text.replace('{phrase}', `"${productsCtx.variables.phrase !== null && productsCtx.variables.phrase !== undefined ? productsCtx.variables.phrase : ''}"`);
+
+  }
+
+  const getResults = (totalCount) => {
+    const resultsTranslation = translation.CategoryFilters.products;
+    return resultsTranslation.replace('{totalCount}', `${totalCount}`);
+  };
+
+  return (
+    <>
+      {!(displayMode === 'PAGE') &&
+        (!screenSize.mobile && showFilters && productsCtx.facets.length > 0 ? (
+          <div className="ds-widgets bg-body py-2 px-2">
+            <div className="flex">
+              <CategoryFilters
+                loading={productsCtx.loading}
+                pageLoading={productsCtx.pageLoading}
+                facets={productsCtx.facets}
+                totalCount={productsCtx.totalCount}
+                categoryName={productsCtx.categoryName !== null && productsCtx.categoryName !== undefined ? productsCtx.categoryName : ''}
+                phrase={productsCtx.variables.phrase !== null && productsCtx.variables.phrase !== undefined ? productsCtx.variables.phrase : ''}
+                showFilters={showFilters}
+                setShowFilters={setShowFilters}
+                filterCount={searchCtx.filterCount}
+              />
+              <div
+                className={`ds-widgets_results flex flex-col items-center ${
+                  productsCtx.categoryName ? 'pt-16' : 'pt-28'
+                } w-full h-full`}
+              >
+                <ProductsHeader
+                  facets={productsCtx.facets}
+                  totalCount={productsCtx.totalCount}
+                  screenSize={screenSize}
+                />
+                <SelectedFilters />
+                <ProductsContainer showFilters={showFilters} />
+              </div>
+            </div>
+          </div>
+        ) : (
+          <div className="ds-widgets bg-body py-2 px-2">
+            <div className="flex flex-col">
+              <div className="flex flex-col items-center w-full h-full">
+                <div className="justify-start w-full h-full">
+                  <div className="hidden sm:flex ds-widgets-_actions relative max-w-[21rem] w-full h-full px-2 flex-col overflow-y-auto">
+                    <div className="ds-widgets_actions_header flex justify-between items-center mb-md">
+                      {title && <span>{title}</span>}
+                      {!productsCtx.loading && (
+                        <span className="text-primary text-sm">
+                          {getResults(productsCtx.totalCount)}
+                        </span>
+                      )}
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <div className="ds-widgets_results flex flex-col items-center w-full h-full">
+                <div className="flex w-full h-full">
+                  {!screenSize.mobile &&
+                    !productsCtx.loading &&
+                    productsCtx.facets.length > 0 && (
+                      <div className="flex w-full h-full">
+                        <FilterButton
+                          displayFilter={() => setShowFilters(true)}
+                          type="desktop"
+                          title={`${translation.Filter.showTitle}${
+                            searchCtx.filterCount > 0
+                              ? ` (${searchCtx.filterCount})`
+                              : ''
+                          }`}
+                        />
+                      </div>
+                    )}
+                </div>
+                {productsCtx.loading ? (
+                  screenSize.mobile ? (
+                    <Loading label={loadingLabel} />
+                  ) : (
+                    <Shimmer />
+                  )
+                ) : (
+                  <>
+                    <div className="flex w-full h-full">
+                      <ProductsHeader
+                        facets={productsCtx.facets}
+                        totalCount={productsCtx.totalCount}
+                        screenSize={screenSize}
+                      />
+                    </div>
+                    <SelectedFilters />
+                    <ProductsContainer
+                      showFilters={showFilters && productsCtx.facets.length > 0}
+                    />
+                  </>
+                )}
+              </div>
+            </div>
+          </div>
+        ))}
+    </>
+  );
+};
+
+export default App;
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchPLPLoader.jsx b/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchPLPLoader.jsx
new file mode 100644
index 0000000000..691089a3f8
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchPLPLoader.jsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import LiveSearchPLP from '../index';
+import { useLiveSearchPLPConfig } from '../hooks/useLiveSearchPLPConfig';
+import { ResultsModifierProvider } from '../context/resultsModifierContext';
+
+export const LiveSearchPLPLoader = ({categoryId}) => {
+  const { config, loading, error } = useLiveSearchPLPConfig({categoryId});
+
+  if (loading) {
+    return <div></div>;
+  }
+  
+  if (error || !config) {
+    return <div>Error loading Live Search configuration</div>;
+  }
+
+  return (
+    <ResultsModifierProvider baseUrl={config?.baseUrl} baseUrlWithoutProtocol={config?.baseUrlwithoutProtocol}>
+      <LiveSearchPLP storeDetails={config} />
+    </ResultsModifierProvider>
+  );
+};
+
+export default LiveSearchPLPLoader;
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchPopoverLoader.jsx b/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchPopoverLoader.jsx
new file mode 100644
index 0000000000..b01b8e9bac
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchPopoverLoader.jsx
@@ -0,0 +1,190 @@
+import React, { useEffect, useState, useCallback, useMemo } from 'react';
+import { useHistory } from 'react-router-dom';
+import { useAutocomplete, Popover, LiveSearch } from '@magento/storefront-search-as-you-type';
+import { Form } from 'informed';
+import TextInput from '@magento/venia-ui/lib/components/TextInput';
+import { useStyle } from '@magento/venia-ui/lib/classify';
+import defaultClasses from '../styles/searchBar.module.css';
+import autoCompleteClasses from '../styles/autocomplete.module.css';
+import { useLiveSearchPopoverConfig } from '../hooks/useLiveSearchPopoverConfig';
+import { Search as SearchIcon } from 'react-feather';
+
+const LiveSearchPopoverLoader = () => {
+    const classes = useStyle(defaultClasses);
+    const history = useHistory();
+    const [isPopoverVisible, setPopoverVisible] = useState(false);
+
+    const {
+        storeDetails,
+        configReady,
+        storeLoading,
+        customerLoading,
+        storeError
+    } = useLiveSearchPopoverConfig();
+
+    const liveSearch = useMemo(() => {
+        if (!storeDetails || Object.keys(storeDetails).length === 0) return null;
+        return new LiveSearch(storeDetails);
+    }, [JSON.stringify(storeDetails)]);
+
+    const {
+    performSearch,
+    minQueryLength,
+    currencySymbol
+} = liveSearch ? liveSearch : {
+    performSearch: () => Promise.resolve({}),
+    minQueryLength: 3,
+    currencySymbol: '$'
+};
+
+
+    const {
+        formProps,
+        formRef,
+        inputProps,
+        inputRef,
+        results,
+        resultsRef,
+        loading: searchLoading,
+        searchTerm
+    } = useAutocomplete(performSearch, minQueryLength);
+
+    const transformResults = originalResults => {
+        if (!originalResults?.data?.productSearch?.items) return originalResults;
+
+        const cleanUrl = url =>
+                url?.replace(storeDetails.baseUrlwithoutProtocol, '');
+        
+        const transformedItems = originalResults.data.productSearch.items.map(item => {
+            const product = item.product;
+            if (!product) return item;
+
+            return {
+                ...item,
+                product: {
+                    ...product,
+                    canonical_url: cleanUrl(product.canonical_url),
+                    image: { ...product.image, url: cleanUrl(product.image?.url) },
+                    small_image: { ...product.small_image, url: cleanUrl(product.small_image?.url) },
+                    thumbnail: { ...product.thumbnail, url: cleanUrl(product.thumbnail?.url) }
+                }
+            };
+        });
+
+        return {
+            ...originalResults,
+            data: {
+                ...originalResults.data,
+                productSearch: {
+                    ...originalResults.data.productSearch,
+                    items: transformedItems
+                }
+            }
+        };
+    };
+
+    const modifiedResults = transformResults(results);
+    inputRef.current = document.getElementById('search_query');
+    formRef.current = document.getElementById('search-autocomplete-form');
+
+    const getSearchStatusMessage = () => {
+        if (!searchTerm) return 'Search for a product';
+
+        if (searchTerm.length < minQueryLength) {
+            return `Search term must be at least ${minQueryLength} characters`;
+        }
+
+        if (searchLoading) {
+            return 'Fetching results...';
+        }
+
+        if (
+            searchTerm.length >= minQueryLength &&
+            !searchLoading &&
+            modifiedResults?.data?.productSearch?.items?.length === 0
+        ) {
+            return 'No results were found.';
+        }
+
+        return null;
+    };
+
+    const searchStatusMessage = getSearchStatusMessage();
+
+    useEffect(() => {
+        if (searchTerm.length >= minQueryLength) {
+            setPopoverVisible(true);
+        }
+    }, [searchTerm, minQueryLength]);
+
+    const handleSubmit = useCallback(
+        event => {
+            const query = inputRef.current?.value;
+            if (query) {
+                setPopoverVisible(false);
+                history.push(`/search.html?query=${query}`);
+            }
+        },
+        [history, inputRef]
+    );
+
+    if (!configReady) return null; // Or a loading spinner
+
+    return (
+        <Form
+            autoComplete="off"
+            className={classes.form}
+            id="search-autocomplete-form"
+            {...formProps}
+            action="/search.html"
+            onSubmit={handleSubmit}
+        >
+            <div className={classes.search}>
+                <TextInput
+                    id="search_query"
+                    before={<SearchIcon />}
+                    field="query"
+                    data-cy="SearchField-textInput"
+                    {...inputProps}
+                />
+                <div data-cy="Autocomplete-root" className={autoCompleteClasses.root_visible}>
+                    {searchStatusMessage && (
+                        <label
+                            id="search_query_label"
+                            data-cy="Autocomplete-message"
+                            className={classes.message}
+                        >
+                            {searchStatusMessage}
+                        </label>
+                    )}
+                    <div
+                        id="search_autocomplete"
+                        className={`${classes.suggestions} ${classes.popover}`}
+                    >
+                        {searchTerm &&
+                        !searchLoading &&
+                        results &&
+                        isPopoverVisible && (
+                            <Popover
+                                active={searchTerm.length >= minQueryLength}
+                                response={modifiedResults}
+                                formRef={formRef}
+                                resultsRef={resultsRef}
+                                inputRef={inputRef}
+                                pageSize={storeDetails.config.pageSize}
+                                currencySymbol={currencySymbol}
+                                currencyRate={storeDetails.config.currencyRate}
+                                minQueryLengthHit={
+                                    searchTerm.length >= minQueryLength
+                                }
+                                searchRoute={storeDetails.searchRoute}
+                            />
+                        )}
+                    </div>
+                </div>
+            </div>
+        </Form>
+    );
+};
+
+export default LiveSearchPopoverLoader;
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchSRLPLoader.jsx b/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchSRLPLoader.jsx
new file mode 100644
index 0000000000..5c026b1177
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/LiveSearchSRLPLoader.jsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import LiveSearchPLP from '../index';
+import { useLiveSearchSRLPConfig } from '../hooks/useLiveSearchSRLPConfig';
+import { ResultsModifierProvider } from '../context/resultsModifierContext';
+
+export const LiveSearchSRLPLoader = () => {
+  const { config, loading, error } = useLiveSearchSRLPConfig();
+
+  if (loading) {
+    return <div></div>;
+  }
+ 
+  if (error || !config) {
+    return <div>Error loading Live Search configuration</div>;
+  }
+
+  return (
+    <ResultsModifierProvider baseUrl={config?.baseUrl} baseUrlWithoutProtocol={config?.baseUrlwithoutProtocol}>
+      <LiveSearchPLP storeDetails={config} />
+    </ResultsModifierProvider>
+  );
+};
+
+export default LiveSearchSRLPLoader;
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/ProductListingPage.jsx b/packages/extensions/venia-pwa-live-search/src/containers/ProductListingPage.jsx
new file mode 100644
index 0000000000..169cb56d6e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/ProductListingPage.jsx
@@ -0,0 +1,66 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React from 'react';
+import { validateStoreDetailsKeys } from '../utils/validateStoreDetails';
+
+import '../styles/global.css';
+
+import {
+  AttributeMetadataProvider,
+  CartProvider,
+  ProductsContextProvider,
+  SearchProvider,
+  StoreContextProvider,
+} from '../context';
+import Resize from '../context/displayChange';
+import Translation from '../context/translation';
+import { getUserViewHistory } from '../utils/getUserViewHistory';
+import App from './App';
+
+/**
+ * A plug-and-play React component that provides the full Live Search PLP context.
+ * @param {object} props
+ * @param {object} props.storeDetails - Store configuration data (must include context).
+ */
+const ProductListingPage = ({ storeDetails }) => {
+  if (!storeDetails) {
+    throw new Error("LiveSearchPLP's storeDetails prop was not provided");
+  }
+
+  const userViewHistory = getUserViewHistory();
+
+  const updatedStoreDetails = {
+    ...storeDetails,
+    context: {
+      ...storeDetails.context,
+      userViewHistory,
+    },
+  };
+
+  return (
+    <StoreContextProvider {...validateStoreDetailsKeys(updatedStoreDetails)}>
+      <AttributeMetadataProvider>
+        <SearchProvider>
+          <Resize>
+            <Translation>
+              <ProductsContextProvider>
+                <CartProvider>
+                  <App />
+                </CartProvider>
+              </ProductsContextProvider>
+            </Translation>
+          </Resize>
+        </SearchProvider>
+      </AttributeMetadataProvider>
+    </StoreContextProvider>
+  );
+};
+
+export default ProductListingPage;
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/ProductsContainer.jsx b/packages/extensions/venia-pwa-live-search/src/containers/ProductsContainer.jsx
new file mode 100644
index 0000000000..a7f23ce7d5
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/ProductsContainer.jsx
@@ -0,0 +1,145 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useEffect } from 'react';
+import { ProductCardShimmer } from '../components/ProductCardShimmer';
+import { useProducts, useSensor, useTranslation } from '../context';
+import { handleUrlPageSize, handleUrlPagination } from '../utils/handleUrlFilters';
+
+import { Alert } from '../components/Alert';
+import { Pagination } from '../components/Pagination';
+import { PerPagePicker } from '../components/PerPagePicker';
+import { ProductList } from '../components/ProductList';
+
+const ProductsContainer = ({ showFilters }) => {
+  const productsCtx = useProducts();
+  const { screenSize } = useSensor();
+
+  const {
+    variables,
+    items,
+    setCurrentPage,
+    currentPage,
+    setPageSize,
+    pageSize,
+    totalPages,
+    totalCount,
+    minQueryLength,
+    minQueryLengthReached,
+    pageSizeOptions,
+    loading,
+  } = productsCtx;
+
+  const translation = useTranslation();
+
+  const goToPage = (page) => {
+    if (typeof page === 'number') {
+      setCurrentPage(page);
+      handleUrlPagination(page);
+    }
+  };
+
+  const onPageSizeChange = (pageSizeOption) => {
+    setPageSize(pageSizeOption);
+    handleUrlPageSize(pageSizeOption);
+  };
+
+  const getPageSizeTranslation = (pageSize, pageSizeOptions) => {
+    const pageSizeTranslation = translation.ProductContainers.pagePicker;
+    const pageSizeTranslationOrder = pageSizeTranslation.split(' ');
+
+    return pageSizeTranslationOrder.map((word, index) =>
+      word === '{pageSize}' ? (
+        <PerPagePicker
+          key={index}
+          pageSizeOptions={pageSizeOptions}
+          value={pageSize}
+          onChange={onPageSizeChange}
+        />
+      ) : (
+        `${word} `
+      )
+    );
+  };
+
+  useEffect(() => {
+    if (currentPage < 1) {
+      goToPage(1);
+    }
+  }, []);
+
+  const productCardArray = Array.from({ length: 8 });
+
+  if (!minQueryLengthReached) {
+    const templateMinQueryText = translation.ProductContainers.minquery;
+    const title = templateMinQueryText
+      .replace('{variables.phrase}', variables.phrase)
+      .replace('{minQueryLength}', minQueryLength);
+
+    return (
+      <div className="ds-sdk-min-query__page mx-auto max-w-8xl py-12 px-4 sm:px-6 lg:px-8">
+        <Alert title={title} type="warning" description="" />
+      </div>
+    );
+  }
+
+  if (!totalCount) {
+    return (
+      <div className="ds-sdk-no-results__page mx-auto max-w-8xl py-12 px-4 sm:px-6 lg:px-8">
+        <Alert
+          title={translation.ProductContainers.noresults}
+          type="warning"
+          description=""
+        />
+      </div>
+    );
+  }
+
+  return (
+    <>
+      {loading ? (
+        <div
+          style={{
+            gridTemplateColumns: `repeat(${screenSize.columns}, minmax(0, 1fr))`,
+          }}
+          className="ds-sdk-product-list__grid mt-md grid grid-cols-1 gap-y-8 gap-x-md sm:grid-cols-2 md:grid-cols-3 xl:gap-x-4 pl-8"
+        >
+          {productCardArray.map((_, index) => (
+            <ProductCardShimmer key={index} />
+          ))}
+        </div>
+      ) : (
+        <ProductList
+          products={items}
+          numberOfColumns={screenSize.columns}
+          showFilters={showFilters}
+        />
+      )}
+
+      <div
+        className={`flex flex-row justify-between max-w-full ${
+          showFilters ? 'mx-auto' : 'mr-auto'
+        } w-full h-full`}
+      >
+        <div>
+          {getPageSizeTranslation(pageSize, pageSizeOptions)}
+        </div>
+        {totalPages > 1 && (
+          <Pagination
+            currentPage={currentPage}
+            totalPages={totalPages}
+            onPageChange={goToPage}
+          />
+        )}
+      </div>
+    </>
+  );
+};
+
+export default ProductsContainer;
diff --git a/packages/extensions/venia-pwa-live-search/src/containers/ProductsHeader.jsx b/packages/extensions/venia-pwa-live-search/src/containers/ProductsHeader.jsx
new file mode 100644
index 0000000000..bd55f6ce1e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/containers/ProductsHeader.jsx
@@ -0,0 +1,123 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { useCallback, useEffect, useState } from 'react';
+
+import ViewSwitcher from '../components/ViewSwitcher';
+import Facets from '../components/Facets';
+import { FilterButton } from '../components/FilterButton';
+import { SearchBar } from '../components/SearchBar';
+import { SortDropdown } from '../components/SortDropdown';
+
+import {
+  useAttributeMetadata,
+  useProducts,
+  useSearch,
+  useStore,
+  useTranslation,
+} from '../context';
+
+import { getValueFromUrl, handleUrlSort } from '../utils/handleUrlFilters';
+import {
+  defaultSortOptions,
+  generateGQLSortInput,
+  getSortOptionsfromMetadata,
+} from '../utils/sort';
+
+export const ProductsHeader = ({ facets, totalCount, screenSize }) => {
+  const searchCtx = useSearch();
+  const storeCtx = useStore();
+  const attributeMetadata = useAttributeMetadata();
+  const productsCtx = useProducts();
+  const translation = useTranslation();
+
+  const [showMobileFacet, setShowMobileFacet] = useState(
+    !!productsCtx.variables.filter?.length
+  );
+  const [sortOptions, setSortOptions] = useState(defaultSortOptions());
+
+  const getSortOptions = useCallback(() => {
+    setSortOptions(
+      getSortOptionsfromMetadata(
+        attributeMetadata?.sortable,
+        storeCtx?.config?.displayOutOfStock,
+        storeCtx?.config?.currentCategoryUrlPath,
+        translation
+      )
+    );
+  }, [storeCtx, translation, attributeMetadata]);
+
+  useEffect(() => {
+    getSortOptions();
+  }, [getSortOptions]);
+
+  const defaultSortOption = storeCtx.config?.currentCategoryUrlPath
+    ? 'position_ASC'
+    : 'relevance_DESC';
+
+  const sortFromUrl = getValueFromUrl('product_list_order');
+  const sortByDefault = sortFromUrl ? sortFromUrl : defaultSortOption;
+
+  const [sortBy, setSortBy] = useState(sortByDefault);
+
+  const onSortChange = (sortOption) => {
+    setSortBy(sortOption);
+    searchCtx.setSort(generateGQLSortInput(sortOption));
+    handleUrlSort(sortOption);
+  };
+
+  return (
+    <div className="flex flex-col max-w-5xl lg:max-w-full ml-auto w-full h-full">
+      <div
+        className={`flex gap-x-2.5 mb-[1px] ${
+          screenSize.mobile ? 'justify-between' : 'justify-end'
+        }`}
+      >
+        <div>
+          {screenSize.mobile ? (
+            totalCount > 0 && (
+              <div className="pb-4">
+                <FilterButton
+                  displayFilter={() => setShowMobileFacet(!showMobileFacet)}
+                  type="mobile"
+                />
+              </div>
+            )
+          ) : (
+            storeCtx.config.displaySearchBox && (
+              <SearchBar
+                phrase={searchCtx.phrase}
+                onKeyPress={(e) => {
+                  if (e.key === 'Enter') {
+                    searchCtx.setPhrase(e.target.value);
+                  }
+                }}
+                onClear={() => searchCtx.setPhrase('')}
+                placeholder={translation.SearchBar.placeholder}
+              />
+            )
+          )}
+        </div>
+        {totalCount > 0 && (
+          <>
+            {storeCtx?.config?.listview && <ViewSwitcher />}
+            <SortDropdown
+              sortOptions={sortOptions}
+              value={sortBy}
+              onChange={onSortChange}
+            />
+          </>
+        )}
+      </div>
+      {screenSize.mobile && showMobileFacet && (
+        <Facets searchFacets={facets} />
+      )}
+    </div>
+  );
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/context/attributeMetadata.js b/packages/extensions/venia-pwa-live-search/src/context/attributeMetadata.js
new file mode 100644
index 0000000000..5d624b06dc
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/attributeMetadata.js
@@ -0,0 +1,63 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext, useEffect, useState } from 'react';
+import { getAttributeMetadata } from '../api/search';
+import { useStore } from './store';
+
+// Remove the interface and type annotations since we're using JavaScript
+const AttributeMetadataContext = createContext({
+    sortable: [],
+    filterableInSearch: []
+});
+
+const AttributeMetadataProvider = ({ children }) => {
+    const [attributeMetadata, setAttributeMetadata] = useState({
+        sortable: [],
+        filterableInSearch: null
+    });
+
+    const storeCtx = useStore();
+
+    useEffect(() => {
+        const fetchData = async () => {
+            const data = await getAttributeMetadata({
+                ...storeCtx,
+                apiUrl: storeCtx.apiUrl
+            });
+            if (data?.attributeMetadata) {
+                setAttributeMetadata({
+                    sortable: data.attributeMetadata.sortable,
+                    filterableInSearch: data.attributeMetadata.filterableInSearch.map(
+                        attribute => attribute.attribute
+                    )
+                });
+            }
+        };
+
+        fetchData();
+    }, [storeCtx]); // Added storeCtx as dependency to handle any changes to the context
+
+    const attributeMetadataContext = {
+        ...attributeMetadata
+    };
+
+    return (
+        <AttributeMetadataContext.Provider value={attributeMetadataContext}>
+            {children}
+        </AttributeMetadataContext.Provider>
+    );
+};
+
+const useAttributeMetadata = () => {
+    const attributeMetadataCtx = useContext(AttributeMetadataContext);
+    return attributeMetadataCtx;
+};
+
+export { AttributeMetadataProvider, useAttributeMetadata };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/cart.js b/packages/extensions/venia-pwa-live-search/src/context/cart.js
new file mode 100644
index 0000000000..afd0d6bee6
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/cart.js
@@ -0,0 +1,97 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext, useState } from 'react';
+import { getGraphQL } from '../api/graphql';
+import { ADD_TO_CART } from '../api/mutations';
+import { GET_CUSTOMER_CART } from '../api/queries';
+import { useProducts } from './products';
+import { useStore } from './store';
+
+// Removed TypeScript interface and type annotations
+
+const CartContext = createContext({});
+
+const useCart = () => {
+    return useContext(CartContext);
+};
+
+const CartProvider = ({ children }) => {
+    const [cart, setCart] = useState({ cartId: '' });
+    const { refreshCart, resolveCartId } = useProducts();
+    const { storeViewCode, config } = useStore();
+
+    const initializeCustomerCart = async () => {
+        let cartId = '';
+        if (!resolveCartId) {
+            const customerResponse = await getGraphQL(
+                GET_CUSTOMER_CART,
+                {},
+                storeViewCode,
+                config && config.baseUrl
+            );
+
+            cartId =
+                customerResponse &&
+                customerResponse.data &&
+                customerResponse.data.customerCart &&
+                customerResponse.data.customerCart.id
+                    ? customerResponse.data.customerCart.id
+                    : '';
+        } else {
+            const resolvedCartId = await resolveCartId();
+            cartId = resolvedCartId != null ? resolvedCartId : '';
+        }
+
+        setCart({ ...cart, cartId });
+        return cartId;
+    };
+
+    const addToCartGraphQL = async sku => {
+        let cartId = cart.cartId;
+        if (!cartId) {
+            cartId = await initializeCustomerCart();
+        }
+        const cartItems = [
+            {
+                quantity: 1,
+                sku
+            }
+        ];
+
+        const variables = {
+            cartId,
+            cartItems
+        };
+
+        const response = await getGraphQL(
+            ADD_TO_CART,
+            variables,
+            storeViewCode,
+            config?.baseUrl
+        );
+
+        return response;
+    };
+
+    const cartContext = {
+        cart,
+        initializeCustomerCart,
+        addToCartGraphQL,
+        refreshCart
+    };
+
+    return (
+        <CartContext.Provider value={cartContext}>
+            {children}
+        </CartContext.Provider>
+    );
+};
+
+export { CartProvider, useCart };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/displayChange.js b/packages/extensions/venia-pwa-live-search/src/context/displayChange.js
new file mode 100644
index 0000000000..2acd6de219
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/displayChange.js
@@ -0,0 +1,90 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext, useState, useEffect } from 'react';
+import { PRODUCT_COLUMNS } from '../utils/constants';
+
+// Removed TypeScript interfaces
+
+const DefaultScreenSizeObject = {
+    mobile: false,
+    tablet: false,
+    desktop: false,
+    columns: PRODUCT_COLUMNS.desktop
+};
+
+const useSensor = () => {
+    const { screenSize } = useContext(ResizeChangeContext);
+
+    const [result, setResult] = useState(DefaultScreenSizeObject);
+
+    useEffect(() => {
+        const size = screenSize ? screenSize : DefaultScreenSizeObject;
+        setResult(size);
+    }, [screenSize]);
+
+    return { screenSize: result };
+};
+
+export const ResizeChangeContext = createContext({});
+
+const getColumn = screenSize => {
+    if (screenSize.desktop) {
+        return PRODUCT_COLUMNS.desktop;
+    }
+    if (screenSize.tablet) {
+        return PRODUCT_COLUMNS.tablet;
+    }
+    if (screenSize.mobile) {
+        return PRODUCT_COLUMNS.mobile;
+    }
+    // Fallback just in case
+    return PRODUCT_COLUMNS.desktop;
+};
+
+const Resize = ({ children }) => {
+    const detectDevice = () => {
+        const result = { ...DefaultScreenSizeObject };
+
+        result.mobile = window.matchMedia(
+            'screen and (max-width: 767px)'
+        ).matches;
+        result.tablet = window.matchMedia(
+            'screen and (min-width: 768px) and (max-width: 960px)'
+        ).matches;
+        result.desktop = window.matchMedia(
+            'screen and (min-width: 961px)'
+        ).matches;
+        result.columns = getColumn(result);
+        return result;
+    };
+
+    const [screenSize, setScreenSize] = useState(detectDevice());
+
+    useEffect(() => {
+        window.addEventListener('resize', handleResize);
+        return () => {
+            window.removeEventListener('resize', handleResize);
+        };
+    });
+
+    const handleResize = () => {
+        setScreenSize({ ...screenSize, ...detectDevice() });
+    };
+
+    return (
+        <ResizeChangeContext.Provider value={{ screenSize }}>
+            {children}
+        </ResizeChangeContext.Provider>
+    );
+};
+
+export default Resize;
+
+export { useSensor };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/events.js b/packages/extensions/venia-pwa-live-search/src/context/events.js
new file mode 100644
index 0000000000..a2db2fc9c2
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/events.js
@@ -0,0 +1,160 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import mse from '@adobe/magento-storefront-events-sdk';
+
+const updateSearchInputCtx = (
+    searchUnitId,
+    searchRequestId,
+    phrase,
+    filters,
+    pageSize,
+    currentPage,
+    sort
+) => {
+    if (!mse) {
+        // don't break search if events are broken/not loading
+        return;
+    }
+
+    const searchInputResult = mse.context.getSearchInput();
+    const searchInputCtx =
+        searchInputResult !== null && searchInputResult !== undefined
+            ? searchInputResult
+            : { units: [] };
+
+    const searchInputUnit = {
+        searchUnitId,
+        searchRequestId,
+        queryTypes: ['products', 'suggestions'],
+        phrase,
+        pageSize,
+        currentPage,
+        filter: filters,
+        sort
+    };
+
+    const searchInputUnitIndex = searchInputCtx.units.findIndex(
+        unit => unit.searchUnitId === searchUnitId
+    );
+
+    if (searchInputUnitIndex < 0) {
+        searchInputCtx.units.push(searchInputUnit);
+    } else {
+        searchInputCtx.units[searchInputUnitIndex] = searchInputUnit;
+    }
+
+    mse.context.setSearchInput(searchInputCtx);
+};
+
+const updateSearchResultsCtx = (searchUnitId, searchRequestId, results) => {
+    const mse = window.magentoStorefrontEvents;
+    if (!mse) {
+        return;
+    }
+
+    const searchResultsResult = mse.context.getSearchResults();
+    const searchResultsCtx =
+        searchResultsResult !== null && searchResultsResult !== undefined
+            ? searchResultsResult
+            : { units: [] };
+
+    const searchResultUnitIndex = searchResultsCtx.units.findIndex(
+        unit => unit.searchUnitId === searchUnitId
+    );
+
+    const searchResultUnit = {
+        searchUnitId,
+        searchRequestId,
+        products: createProducts(results.items),
+        categories: [],
+        suggestions: createSuggestions(results.suggestions),
+        page: results?.page_info?.current_page || 1,
+        perPage: results?.page_info?.page_size || 20,
+        facets: createFacets(results.facets)
+    };
+
+    if (searchResultUnitIndex < 0) {
+        searchResultsCtx.units.push(searchResultUnit);
+    } else {
+        searchResultsCtx.units[searchResultUnitIndex] = searchResultUnit;
+    }
+
+    mse.context.setSearchResults(searchResultsCtx);
+};
+
+const createProducts = items => {
+    if (!items) {
+        return [];
+    }
+
+    return items.map((item, index) => ({
+        name: item && item.product && item.product.name,
+        sku: item && item.product && item.product.sku,
+        url:
+            item &&
+            item.product &&
+            item.product.canonical_url !== undefined &&
+            item.product.canonical_url !== null
+                ? item.product.canonical_url
+                : '',
+        imageUrl:
+            item &&
+            item.productView &&
+            Array.isArray(item.productView.images) &&
+            item.productView.images.length
+                ? item.productView.images[0].url !== undefined &&
+                  item.productView.images[0].url !== null
+                    ? item.productView.images[0].url
+                    : ''
+                : '',
+        price:
+            item &&
+            item.productView &&
+            item.productView.price &&
+            item.productView.price.final &&
+            item.productView.price.final.amount &&
+            item.productView.price.final.amount.value !== undefined &&
+            item.productView.price.final.amount.value !== null
+                ? item.productView.price.final.amount.value
+                : item &&
+                  item.product &&
+                  item.product.price_range &&
+                  item.product.price_range.minimum_price &&
+                  item.product.price_range.minimum_price.final_price &&
+                  item.product.price_range.minimum_price.final_price.value,
+        rank: index
+    }));
+};
+
+const createSuggestions = items => {
+    if (!items) {
+        return [];
+    }
+
+    return items.map((suggestion, index) => ({
+        suggestion,
+        rank: index
+    }));
+};
+
+const createFacets = items => {
+    if (!items) {
+        return [];
+    }
+
+    return items.map(item => ({
+        attribute: item?.attribute,
+        title: item?.title,
+        type: item?.type || 'PINNED',
+        buckets: item?.buckets.map(bucket => bucket)
+    }));
+};
+
+export { updateSearchInputCtx, updateSearchResultsCtx };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/index.js b/packages/extensions/venia-pwa-live-search/src/context/index.js
new file mode 100644
index 0000000000..8406a5d26f
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/index.js
@@ -0,0 +1,19 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export * from './attributeMetadata';
+export * from './store';
+export * from './widgetConfig';
+export * from './search';
+export * from './products';
+export * from './displayChange';
+export * from './events';
+export * from './translation';
+export * from './cart';
+export * from './wishlist';
diff --git a/packages/extensions/venia-pwa-live-search/src/context/products.jsx b/packages/extensions/venia-pwa-live-search/src/context/products.jsx
new file mode 100644
index 0000000000..f999207b36
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/products.jsx
@@ -0,0 +1,314 @@
+import React, { useContext, useEffect, useMemo, useState, createContext } from 'react';
+
+import { getProductSearch, refineProductSearch } from '../api/search';
+import {
+  CATEGORY_SORT_DEFAULT,
+  DEFAULT_MIN_QUERY_LENGTH,
+  DEFAULT_PAGE_SIZE,
+  DEFAULT_PAGE_SIZE_OPTIONS,
+  SEARCH_SORT_DEFAULT,
+} from '../utils/constants';
+import { moveToTop } from '../utils/dom';
+import {
+  getFiltersFromUrl,
+  getValueFromUrl,
+  handleUrlPagination,
+} from '../utils/handleUrlFilters';
+import { useAttributeMetadata } from './attributeMetadata';
+import { useSearch } from './search';
+import { useStore } from './store';
+import { useTranslation } from './translation';
+
+const ProductsContext = createContext({
+  variables: { phrase: '' },
+  loading: false,
+  items: [],
+  setItems: () => {},
+  currentPage: 1,
+  setCurrentPage: () => {},
+  pageSize: DEFAULT_PAGE_SIZE,
+  setPageSize: () => {},
+  totalCount: 0,
+  setTotalCount: () => {},
+  totalPages: 0,
+  setTotalPages: () => {},
+  facets: [],
+  setFacets: () => {},
+  categoryName: '',
+  setCategoryName: () => {},
+  currencySymbol: '',
+  setCurrencySymbol: () => {},
+  currencyRate: '',
+  setCurrencyRate: () => {},
+  minQueryLength: DEFAULT_MIN_QUERY_LENGTH,
+  minQueryLengthReached: false,
+  setMinQueryLengthReached: () => {},
+  pageSizeOptions: [],
+  setRoute: undefined,
+  refineProduct: () => {},
+  pageLoading: false,
+  setPageLoading: () => {},
+  categoryPath: undefined,
+  viewType: '',
+  setViewType: () => {},
+  listViewType: '',
+  setListViewType: () => {},
+  resolveCartId: () => Promise.resolve(''),
+  refreshCart: () => {},
+  addToCart: () => Promise.resolve(),
+});
+
+const ProductsContextProvider = ({ children }) => {
+  const urlValue = getValueFromUrl('p');
+  const pageDefault = urlValue ? Number(urlValue) : 1;
+
+  const searchCtx = useSearch();
+  const storeCtx = useStore();
+  const attributeMetadataCtx = useAttributeMetadata();
+
+  const pageSizeValue = getValueFromUrl('page_size');
+  const defaultPageSizeOption =
+    Number(storeCtx?.config?.perPageConfig?.defaultPageSizeOption) ||
+    DEFAULT_PAGE_SIZE;
+  const pageSizeDefault = pageSizeValue
+    ? Number(pageSizeValue)
+    : defaultPageSizeOption;
+
+  const translation = useTranslation();
+  const showAllLabel = translation.ProductContainers.showAll;
+
+  const [loading, setLoading] = useState(true);
+  const [pageLoading, setPageLoading] = useState(true);
+  const [items, setItems] = useState([]);
+  const [currentPage, setCurrentPage] = useState(pageDefault);
+  const [pageSize, setPageSize] = useState(pageSizeDefault);
+  const [totalCount, setTotalCount] = useState(0);
+  const [totalPages, setTotalPages] = useState(0);
+  const [facets, setFacets] = useState([]);
+  const [categoryName, setCategoryName] = useState(
+    storeCtx && storeCtx.config && storeCtx.config.categoryName 
+      ? storeCtx.config.categoryName 
+      : ''
+  );
+  
+  const [pageSizeOptions, setPageSizeOptions] = useState([]);
+  
+  const [currencySymbol, setCurrencySymbol] = useState(
+    storeCtx && storeCtx.config && storeCtx.config.currencySymbol 
+      ? storeCtx.config.currencySymbol 
+      : ''
+  );
+   
+  const [currencyRate, setCurrencyRate] = useState(
+    storeCtx && storeCtx.config && storeCtx.config.currencyRate 
+      ? storeCtx.config.currencyRate 
+      : ''
+  );
+  
+  const [minQueryLengthReached, setMinQueryLengthReached] = useState(false);
+
+  const minQueryLength = useMemo(() => {
+    return storeCtx?.config?.minQueryLength || DEFAULT_MIN_QUERY_LENGTH;
+  }, [storeCtx?.config?.minQueryLength]);
+
+  const categoryPath = storeCtx.config?.currentCategoryUrlPath;
+
+  const viewTypeFromUrl = getValueFromUrl('view_type');
+  const [viewType, setViewType] = useState(
+    viewTypeFromUrl ? viewTypeFromUrl : 'gridView'
+  );
+  const [listViewType, setListViewType] = useState('default');
+
+  const variables = useMemo(() => {
+    return {
+      phrase: searchCtx.phrase,
+      filter: searchCtx.filters,
+      sort: searchCtx.sort,
+      context: storeCtx.context,
+      pageSize,
+      displayOutOfStock: storeCtx.config.displayOutOfStock,
+      currentPage,
+    };
+  }, [
+    searchCtx.phrase,
+    searchCtx.filters,
+    searchCtx.sort,
+    storeCtx.context,
+    storeCtx.config.displayOutOfStock,
+    pageSize,
+    currentPage,
+  ]);
+
+  const handleRefineProductSearch = async (optionIds, sku) => {
+    const data = await refineProductSearch({ ...storeCtx, optionIds, sku });
+    return data;
+  };
+
+  const context = {
+    variables,
+    loading,
+    items,
+    setItems,
+    currentPage,
+    setCurrentPage,
+    pageSize,
+    setPageSize,
+    totalCount,
+    setTotalCount,
+    totalPages,
+    setTotalPages,
+    facets,
+    setFacets,
+    categoryName,
+    setCategoryName,
+    currencySymbol,
+    setCurrencySymbol,
+    currencyRate,
+    setCurrencyRate,
+    minQueryLength,
+    minQueryLengthReached,
+    setMinQueryLengthReached,
+    pageSizeOptions,
+    setRoute: storeCtx.route,
+    refineProduct: handleRefineProductSearch,
+    pageLoading,
+    setPageLoading,
+    categoryPath,
+    viewType,
+    setViewType,
+    listViewType,
+    setListViewType,
+    cartId: storeCtx.config.resolveCartId,
+    refreshCart: storeCtx.config.refreshCart,
+    resolveCartId: storeCtx.config.resolveCartId,
+    addToCart: storeCtx.config.addToCart,
+  };
+
+  useEffect(() => {
+    searchProducts();
+  }, [variables]);
+
+  const searchProducts = async () => {
+    try {
+      setLoading(true);
+      moveToTop();
+      if (checkMinQueryLength()) {
+        const filters = [...variables.filter];
+
+        handleCategorySearch(categoryPath, filters);
+
+        const data = await getProductSearch({
+          ...variables,
+          ...storeCtx,
+          apiUrl: storeCtx.apiUrl,
+          filter: filters,
+          categorySearch: !!categoryPath,
+        });
+
+        setItems(data?.productSearch?.items || []);
+        setFacets(data?.productSearch?.facets || []);
+        setTotalCount(data?.productSearch?.total_count || 0);
+        setTotalPages(data?.productSearch?.page_info?.total_pages || 1);
+        handleCategoryNames(data?.productSearch?.facets || []);
+
+        getPageSizeOptions(data?.productSearch?.total_count);
+
+        paginationCheck(
+          data?.productSearch?.total_count,
+          data?.productSearch?.page_info?.total_pages
+        );
+      }
+      setLoading(false);
+      setPageLoading(false);
+    } catch (error) {
+      setLoading(false);
+      setPageLoading(false);
+    }
+  };
+
+  const checkMinQueryLength = () => {
+    if (
+      !storeCtx.config?.currentCategoryUrlPath &&
+      searchCtx.phrase.trim().length <
+        (Number(storeCtx.config.minQueryLength) || DEFAULT_MIN_QUERY_LENGTH)
+    ) {
+      setItems([]);
+      setFacets([]);
+      setTotalCount(0);
+      setTotalPages(1);
+      setMinQueryLengthReached(false);
+      return false;
+    }
+    setMinQueryLengthReached(true);
+    return true;
+  };
+
+  const getPageSizeOptions = (totalCount) => {
+    const optionsArray = [];
+    const pageSizeString =
+      storeCtx?.config?.perPageConfig?.pageSizeOptions ||
+      DEFAULT_PAGE_SIZE_OPTIONS;
+    const pageSizeArray = pageSizeString.split(',');
+    pageSizeArray.forEach((option) => {
+      optionsArray.push({
+        label: option,
+        value: parseInt(option, 10),
+      });
+    });
+
+    if (storeCtx?.config?.allowAllProducts == '1') {
+      optionsArray.push({
+        label: showAllLabel,
+        value: totalCount !== null ? (totalCount > 500 ? 500 : totalCount) : 0,
+      });
+    }
+    setPageSizeOptions(optionsArray);
+  };
+
+  const paginationCheck = (totalCount, totalPages) => {
+    if (totalCount && totalCount > 0 && totalPages === 1) {
+      setCurrentPage(1);
+      handleUrlPagination(1);
+    }
+  };
+
+  const handleCategorySearch = (categoryPath, filters) => {
+    if (categoryPath) {
+      const categoryFilter = {
+        attribute: 'categoryPath',
+        eq: categoryPath,
+      };
+      filters.push(categoryFilter);
+
+      if (variables.sort.length < 1 || variables.sort === SEARCH_SORT_DEFAULT) {
+        variables.sort = CATEGORY_SORT_DEFAULT;
+      }
+    }
+  };
+
+  const handleCategoryNames = (facets) => {
+    facets.map((facet) => {
+      const bucketType = facet?.buckets[0]?.__typename;
+      if (bucketType === 'CategoryView') {
+        const names = facet.buckets.map((bucket) => {
+          if (bucket.__typename === 'CategoryView')
+            return {
+              name: bucket.name,
+              id: bucket.id,
+            };
+        });
+        setCategoryName(names?.[0]?.name);
+      }
+    });
+  };
+
+  return (
+    <ProductsContext.Provider value={context}>
+      {children}
+    </ProductsContext.Provider>
+  );
+};
+
+const useProducts = () => useContext(ProductsContext);
+
+export { ProductsContextProvider, useProducts };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/resultsModifierContext.js b/packages/extensions/venia-pwa-live-search/src/context/resultsModifierContext.js
new file mode 100644
index 0000000000..f08889bc6e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/resultsModifierContext.js
@@ -0,0 +1,35 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext } from 'react';
+
+const ResultsModifierContext = createContext({
+    baseUrl: '',
+    baseUrlWithoutProtocol: ''
+});
+
+const ResultsModifierProvider = ({
+    baseUrl,
+    baseUrlWithoutProtocol,
+    children
+}) => {
+    return (
+        <ResultsModifierContext.Provider
+            value={{ baseUrl, baseUrlWithoutProtocol }}
+        >
+            {children}
+        </ResultsModifierContext.Provider>
+    );
+};
+
+const useResultsModifier = () => {
+    return useContext(ResultsModifierContext);
+};
+
+export { ResultsModifierProvider, useResultsModifier };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/search.jsx b/packages/extensions/venia-pwa-live-search/src/context/search.jsx
new file mode 100644
index 0000000000..1ea69d1e44
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/search.jsx
@@ -0,0 +1,127 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useState, useEffect, useContext } from 'react';
+import { useLocation } from 'react-router-dom';
+
+import { SEARCH_SORT_DEFAULT } from '../utils/constants';
+import {
+  addUrlFilter,
+  getValueFromUrl,
+  removeAllUrlFilters,
+  removeUrlFilter,
+} from '../utils/handleUrlFilters';
+import { generateGQLSortInput } from '../utils/sort';
+import { useStore } from './store';
+
+export const SearchContext = createContext({});
+
+const SearchProvider = ({ children }) => {
+  const storeCtx = useStore();
+  const location = useLocation(); // watches changes in URL query params
+
+  const getSearchPhrase = () => getValueFromUrl(storeCtx.searchQuery || 'q');
+  const getSortFromUrl = () => getValueFromUrl('product_list_order');
+
+  const [phrase, setPhrase] = useState(getSearchPhrase());
+  const [categoryPath, setCategoryPath] = useState('');
+  const [filters, setFilters] = useState([]);
+  const [categoryNames, setCategoryNames] = useState([]);
+  const [sort, setSort] = useState(generateGQLSortInput(getSortFromUrl()) || SEARCH_SORT_DEFAULT);
+  const [filterCount, setFilterCount] = useState(0);
+
+  // Update phrase and sort when URL changes
+  useEffect(() => {
+    setPhrase(getSearchPhrase());
+    setSort(generateGQLSortInput(getSortFromUrl()) || SEARCH_SORT_DEFAULT);
+  }, [location.search]);
+
+  const createFilter = (filter) => {
+    const newFilters = [...filters, filter];
+    setFilters(newFilters);
+    addUrlFilter(filter);
+  };
+
+  const updateFilter = (filter) => {
+    const newFilters = [...filters];
+    const index = newFilters.findIndex((e) => e.attribute === filter.attribute);
+    newFilters[index] = filter;
+    setFilters(newFilters);
+    addUrlFilter(filter);
+  };
+
+  const removeFilter = (name, option) => {
+    const newFilters = filters.filter((e) => e.attribute !== name);
+    setFilters(newFilters);
+    removeUrlFilter(name, option);
+  };
+
+  const clearFilters = () => {
+    removeAllUrlFilters();
+    setFilters([]);
+  };
+
+  const updateFilterOptions = (facetFilter, option) => {
+    const newFilters = filters.filter((e) => e.attribute !== facetFilter.attribute);
+    const newOptions = facetFilter.in?.filter((e) => e !== option);
+
+    newFilters.push({
+      attribute: facetFilter.attribute,
+      in: newOptions,
+    });
+
+    if (newOptions?.length) {
+      setFilters(newFilters);
+      removeUrlFilter(facetFilter.attribute, option);
+    } else {
+      removeFilter(facetFilter.attribute, option);
+    }
+  };
+
+  const getFilterCount = (filters) => {
+    return filters.reduce((count, filter) => {
+      return count + (filter.in ? filter.in.length : 1);
+    }, 0);
+  };
+
+  useEffect(() => {
+    setFilterCount(getFilterCount(filters));
+  }, [filters]);
+
+  const context = {
+    phrase,
+    categoryPath,
+    filters,
+    sort,
+    categoryNames,
+    filterCount,
+    setPhrase,
+    setCategoryPath,
+    setFilters,
+    setCategoryNames,
+    setSort,
+    createFilter,
+    updateFilter,
+    updateFilterOptions,
+    removeFilter,
+    clearFilters,
+  };
+
+  return (
+    <SearchContext.Provider value={context}>
+      {children}
+    </SearchContext.Provider>
+  );
+};
+
+const useSearch = () => {
+  return useContext(SearchContext);
+};
+
+export { SearchProvider, useSearch };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/store.jsx b/packages/extensions/venia-pwa-live-search/src/context/store.jsx
new file mode 100644
index 0000000000..e68ad6c763
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/store.jsx
@@ -0,0 +1,93 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { createContext } from 'react';
+import { useContext, useMemo } from 'react';
+import React from 'react';
+
+// Define default URLs and keys (you can move these to a constants file)
+const API_URL = 'https://catalog-service.adobe.io/graphql';
+const TEST_URL = 'https://catalog-service-sandbox.adobe.io/graphql';
+const SANDBOX_KEY = 'storefront-widgets'; // Replace with your actual sandbox key if needed
+
+const StoreContext = createContext({
+  environmentId: '',
+  environmentType: '',
+  websiteCode: '',
+  storeCode: '',
+  storeViewCode: '',
+  apiUrl: '',
+  apiKey: '',
+  config: {},
+  context: {},
+  route: undefined,
+  searchQuery: 'q',
+});
+
+const StoreContextProvider = ({
+  children,
+  environmentId,
+  environmentType,
+  websiteCode,
+  storeCode,
+  storeViewCode,
+  config,
+  context,
+  apiKey,
+  route,
+  searchQuery = 'q',
+}) => {
+  const storeProps = useMemo(() => {
+    const isTesting = environmentType?.toLowerCase() === 'testing';
+    return {
+      environmentId,
+      environmentType,
+      websiteCode,
+      storeCode,
+      storeViewCode,
+      config,
+      context: {
+        //getting error because the nullish coalescing operator (??) isn't supported by your Babel/Webpack setup yet.
+        // customerGroup: context?.customerGroup ?? '',
+        // userViewHistory: context?.userViewHistory ?? [],
+
+        //workaround
+        customerGroup: context && context.customerGroup != null ? context.customerGroup : '',
+        userViewHistory: context && context.userViewHistory != null ? context.userViewHistory : [],
+      },
+      apiUrl: isTesting ? TEST_URL : API_URL,
+      apiKey: isTesting && !apiKey ? SANDBOX_KEY : apiKey,
+      route,
+      searchQuery,
+    };
+  }, [
+    environmentId,
+    environmentType,
+    websiteCode,
+    storeCode,
+    storeViewCode,
+    config,
+    context,
+    apiKey,
+    route,
+    searchQuery,
+  ]);
+
+  return (
+    <StoreContext.Provider value={storeProps}>
+      {children}
+    </StoreContext.Provider>
+  );
+};
+
+const useStore = () => {
+  return useContext(StoreContext);
+};
+
+export { StoreContextProvider, useStore };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/translation.jsx b/packages/extensions/venia-pwa-live-search/src/context/translation.jsx
new file mode 100644
index 0000000000..8e7f541f6c
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/translation.jsx
@@ -0,0 +1,125 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext } from 'react';
+
+import {
+  bg_BG,
+  ca_ES,
+  cs_CZ,
+  da_DK,
+  de_DE,
+  el_GR,
+  en_GB,
+  en_US,
+  es_ES,
+  et_EE,
+  eu_ES,
+  fa_IR,
+  fi_FI,
+  fr_FR,
+  gl_ES,
+  hi_IN,
+  hu_HU,
+  id_ID,
+  it_IT,
+  ja_JP,
+  ko_KR,
+  lt_LT,
+  lv_LV,
+  nb_NO,
+  nl_NL,
+  pt_BR,
+  pt_PT,
+  ro_RO,
+  ru_RU,
+  sv_SE,
+  th_TH,
+  tr_TR,
+  zh_Hans_CN,
+  zh_Hant_TW,
+} from '../i18n';
+import { useStore } from './store';
+
+export const languages = {
+  default: en_US,
+  bg_BG,
+  ca_ES,
+  cs_CZ,
+  da_DK,
+  de_DE,
+  el_GR,
+  en_GB,
+  en_US,
+  es_ES,
+  et_EE,
+  eu_ES,
+  fa_IR,
+  fi_FI,
+  fr_FR,
+  gl_ES,
+  hi_IN,
+  hu_HU,
+  id_ID,
+  it_IT,
+  ja_JP,
+  ko_KR,
+  lt_LT,
+  lv_LV,
+  nb_NO,
+  nl_NL,
+  pt_BR,
+  pt_PT,
+  ro_RO,
+  ru_RU,
+  sv_SE,
+  th_TH,
+  tr_TR,
+  zh_Hans_CN,
+  zh_Hant_TW,
+};
+
+export const TranslationContext = createContext(languages.default);
+
+const useTranslation = () => {
+  const translation = useContext(TranslationContext);
+  return translation;
+};
+
+const getCurrLanguage = (languageDetected) => {
+  const langKeys = Object.keys(languages);
+  if (langKeys.includes(languageDetected)) {
+    return languageDetected;
+  }
+  return 'default';
+};
+
+const Translation = ({ children }) => {
+  const storeCtx = useStore();
+
+  //getting error because the nullish coalescing operator (??) isn't supported by your Babel/Webpack setup yet.
+  //const currLanguage = getCurrLanguage(storeCtx?.config?.locale ?? '');
+
+  //workaround
+  const currLanguage = getCurrLanguage(
+    storeCtx && storeCtx.config && storeCtx.config.locale
+      ? storeCtx.config.locale
+      : ''
+  );
+
+
+  return (
+    <TranslationContext.Provider value={languages[currLanguage]}>
+      {children}
+    </TranslationContext.Provider>
+  );
+};
+
+export default Translation;
+export { getCurrLanguage, useTranslation };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/widgetConfig.jsx b/packages/extensions/venia-pwa-live-search/src/context/widgetConfig.jsx
new file mode 100644
index 0000000000..b0892bc676
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/widgetConfig.jsx
@@ -0,0 +1,120 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext, useEffect, useState } from 'react';
+import { useStore } from './store';
+
+// Default widget config state
+const defaultWidgetConfigState = {
+  badge: {
+    enabled: false,
+    label: '',
+    attributeCode: '',
+    backgroundColor: '',
+  },
+  price: {
+    showNoPrice: false,
+    showRange: true,
+    showRegularPrice: true,
+    showStrikethruPrice: true,
+  },
+  attributeSlot: {
+    enabled: false,
+    attributeCode: '',
+    backgroundColor: '',
+  },
+  addToWishlist: {
+    enabled: true,
+    placement: 'inLineWithName',
+  },
+  layout: {
+    defaultLayout: 'grid',
+    allowedLayouts: [],
+    showToggle: true,
+  },
+  addToCart: { enabled: true },
+  stockStatusFilterLook: 'radio',
+  swatches: {
+    enabled: false,
+    swatchAttributes: [],
+    swatchesOnPage: 10,
+  },
+  multipleImages: {
+    enabled: true,
+    limit: 10,
+  },
+  compare: {
+    enabled: true,
+  },
+};
+
+const WidgetConfigContext = createContext(defaultWidgetConfigState);
+
+const WidgetConfigContextProvider = ({ children }) => {
+  const storeCtx = useStore();
+  const { environmentId, storeCode } = storeCtx;
+
+  const [widgetConfig, setWidgetConfig] = useState(defaultWidgetConfigState);
+  const [widgetConfigFetched, setWidgetConfigFetched] = useState(false);
+
+  useEffect(() => {
+    if (!environmentId || !storeCode) {
+      return;
+    }
+
+    if (!widgetConfigFetched) {
+      getWidgetConfig(environmentId, storeCode)
+        .then((results) => {
+          const newWidgetConfig = {
+            ...defaultWidgetConfigState,
+            ...results,
+          };
+          setWidgetConfig(newWidgetConfig);
+          setWidgetConfigFetched(true);
+        })
+        .finally(() => {
+          setWidgetConfigFetched(true);
+        });
+    }
+  }, [environmentId, storeCode, widgetConfigFetched]);
+
+  const getWidgetConfig = async (envId, storeCode) => {
+    const fileName = 'widgets-config.json';
+    const S3path = `/${envId}/${storeCode}/${fileName}`;
+    const widgetConfigUrl = `${WIDGET_CONFIG_URL}${S3path}`;
+
+    const response = await fetch(widgetConfigUrl, {
+      method: 'GET',
+    });
+
+    if (response.status !== 200) {
+      return defaultWidgetConfigState;
+    }
+
+    const results = await response.json();
+    return results;
+  };
+
+  const widgetConfigCtx = {
+    ...widgetConfig,
+  };
+
+  return (
+    <WidgetConfigContext.Provider value={widgetConfigCtx}>
+      {widgetConfigFetched && children}
+    </WidgetConfigContext.Provider>
+  );
+};
+
+const useWidgetConfig = () => {
+  const widgetConfigCtx = useContext(WidgetConfigContext);
+  return widgetConfigCtx;
+};
+
+export { WidgetConfigContextProvider, useWidgetConfig };
diff --git a/packages/extensions/venia-pwa-live-search/src/context/wishlist.jsx b/packages/extensions/venia-pwa-live-search/src/context/wishlist.jsx
new file mode 100644
index 0000000000..e147226873
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/context/wishlist.jsx
@@ -0,0 +1,97 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import React, { createContext, useContext, useEffect, useState } from 'react';
+import { getGraphQL } from '../api/graphql';
+import { ADD_TO_WISHLIST, REMOVE_FROM_WISHLIST } from '../api/mutations';
+import { GET_CUSTOMER_WISHLISTS } from '../api/queries';
+import { useStore } from './store';
+
+// Default values for WishlistContext
+const WishlistContext = createContext({});
+
+const useWishlist = () => {
+  return useContext(WishlistContext);
+};
+
+const WishlistProvider = ({ children }) => {
+  const [isAuthorized, setIsAuthorized] = useState(false);
+  const [allWishlist, setAllWishlist] = useState([]);
+  const [wishlist, setWishlist] = useState();
+  const { storeViewCode, config } = useStore();
+
+  useEffect(() => {
+    getWishlists();
+  }, []);
+
+  const getWishlists = async () => {
+    const { data } =
+      (await getGraphQL(
+        GET_CUSTOMER_WISHLISTS,
+        {},
+        storeViewCode,
+        config?.baseUrl
+      )) || {};
+    const wishlistResponse = data?.customer;
+    const isAuthorized = !!wishlistResponse;
+
+    setIsAuthorized(isAuthorized);
+    if (isAuthorized) {
+      const firstWishlist = wishlistResponse.wishlists[0];
+      setWishlist(firstWishlist);
+      setAllWishlist(wishlistResponse.wishlists);
+    }
+  };
+
+  const addItemToWishlist = async (wishlistId, wishlistItem) => {
+    const { data } =
+      (await getGraphQL(
+        ADD_TO_WISHLIST,
+        {
+          wishlistId,
+          wishlistItems: [wishlistItem],
+        },
+        storeViewCode,
+        config?.baseUrl
+      )) || {};
+    const wishlistResponse = data?.addProductsToWishlist.wishlist;
+    setWishlist(wishlistResponse);
+  };
+
+  const removeItemFromWishlist = async (wishlistId, wishlistItemsIds) => {
+    const { data } =
+      (await getGraphQL(
+        REMOVE_FROM_WISHLIST,
+        {
+          wishlistId,
+          wishlistItemsIds: [wishlistItemsIds],
+        },
+        storeViewCode,
+        config?.baseUrl
+      )) || {};
+    const wishlistResponse = data?.removeProductsFromWishlist.wishlist;
+    setWishlist(wishlistResponse);
+  };
+
+  const wishlistContext = {
+    isAuthorized,
+    wishlist,
+    allWishlist,
+    addItemToWishlist,
+    removeItemFromWishlist,
+  };
+
+  return (
+    <WishlistContext.Provider value={wishlistContext}>
+      {children}
+    </WishlistContext.Provider>
+  );
+};
+
+export { useWishlist, WishlistProvider };
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useEventListener.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useEventListener.js
new file mode 100644
index 0000000000..c41c497acf
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useEventListener.js
@@ -0,0 +1,13 @@
+import { useEffect } from 'react';
+
+const useEventListener = (target, type, listener) => {
+    useEffect(() => {
+        target.addEventListener(type, listener);
+
+        return () => {
+            target.removeEventListener(type, listener);
+        };
+    }, [listener, target, type]);
+};
+
+export default useEventListener;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useLocation.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useLocation.js
new file mode 100644
index 0000000000..5cc6630cb4
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useLocation.js
@@ -0,0 +1,21 @@
+import { useLocation as useLocationDriver } from 'react-router-dom';
+import { useEffect, useState } from 'react';
+
+// This thin wrapper prevents us from having references to venia drivers literred around the code
+const useLocation = () => {
+    const locationDriver = useLocationDriver();
+    const [location, setLocation] = useState(locationDriver);
+
+    useEffect(() => {
+        // Location consistency described here (https://reactrouter.com/web/api/Hooks/uselocation)
+        // is disrupted by Venia's implementation. This wrapper ensures that location
+        // only changes when the user navigates
+        if (locationDriver.pathname !== location.pathname) {
+            setLocation(locationDriver);
+        }
+    }, [locationDriver, location.pathname]);
+
+    return location;
+};
+
+export default useLocation;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useMagentoExtensionContext.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useMagentoExtensionContext.js
new file mode 100644
index 0000000000..7155920861
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useMagentoExtensionContext.js
@@ -0,0 +1,28 @@
+import { useQuery } from '@apollo/client';
+import { useEffect } from 'react';
+import { GET_MAGENTO_EXTENSION_CONTEXT } from '../../queries/eventing/getMagentoExtensionContext.gql.js';
+import mse from '@adobe/magento-storefront-events-sdk';
+
+const useMagentoExtensionContext = () => {
+    const { data, error } = useQuery(GET_MAGENTO_EXTENSION_CONTEXT);
+    if (
+        (process.env.NODE_ENV === 'development' ||
+            process.env.NODE_ENV === 'test') &&
+        error
+    ) {
+        console.error('Magento Extension context query failed!', error);
+    }
+
+    useEffect(() => {
+        let magentoExtensionContext = null;
+        if (data && data.magentoExtensionContext) {
+            magentoExtensionContext = {
+                magentoExtensionVersion:
+                    data.magentoExtensionContext.magento_extension_version
+            };
+        }
+        mse.context.setMagentoExtension(magentoExtensionContext);
+    }, [data]);
+};
+
+export default useMagentoExtensionContext;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/usePageView.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/usePageView.js
new file mode 100644
index 0000000000..1a01e0e82a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/usePageView.js
@@ -0,0 +1,36 @@
+import useLocation from './useLocation';
+import { useEffect, useRef } from 'react';
+import mse from '@adobe/magento-storefront-events-sdk';
+import usePageTypeFromUrl from '../../utils/eventing/usePageTypeFromUrl';
+
+// const usePageView = () => {
+//     const location = useLocation();
+//     const pageType = getPagetype(location);
+//     useEffect(() => {
+//         mse.context.setPage({ pageType });
+//         mse.publish.pageView();
+//     }, [location]);
+// };
+
+const usePageView = () => {
+    const location = useLocation();
+    const pathname = location?.pathname;
+
+    const pageType = usePageTypeFromUrl(pathname);
+
+    const lastPathnameRef = useRef(null);
+
+    useEffect(() => {
+        if (!pathname || !pageType) return;
+
+        // Publish only if pathname actually changed
+        if (lastPathnameRef.current === pathname) return;
+
+        lastPathnameRef.current = pathname;
+
+        mse.context.setPage({ pageType });
+        mse.publish.pageView();
+    }, [pathname, pageType]);
+};
+
+export default usePageView;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useShopperContext.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useShopperContext.js
new file mode 100644
index 0000000000..e0a0a1282b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useShopperContext.js
@@ -0,0 +1,33 @@
+import { useEffect } from 'react';
+import { useUserContext } from '@magento/peregrine/lib/context/user';
+import mse from '@adobe/magento-storefront-events-sdk';
+import { getDecodedCookie } from '../../utils/eventing/getCookie';
+
+const useShopperContext = () => {
+    const [{ isSignedIn }] = useUserContext();
+
+    useEffect(() => {
+        if (isSignedIn) {
+            try {
+                const customerGroupCode = getDecodedCookie(
+                    'dataservices_customer_group='
+                );
+                mse.context.setContext('customerGroup', customerGroupCode);
+            } catch (error) {
+                console.error(
+                    'Cannot access customer group cookie. It seems the data-services module is not able to populate cookies properly.',
+                    error
+                );
+            }
+            mse.context.setShopper({
+                shopperId: 'logged-in'
+            });
+        } else {
+            mse.context.setShopper({
+                shopperId: 'guest'
+            });
+        }
+    }, [isSignedIn]);
+};
+
+export default useShopperContext;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useStorefrontInstanceContext.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useStorefrontInstanceContext.js
new file mode 100644
index 0000000000..428d177b6e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useStorefrontInstanceContext.js
@@ -0,0 +1,46 @@
+import { useQuery } from '@apollo/client';
+import { GET_STOREFRONT_CONTEXT } from '../../queries/eventing/getStorefrontContext.gql';
+import { useEffect } from 'react';
+import mse from '@adobe/magento-storefront-events-sdk';
+
+const useStorefrontInstanceContext = () => {
+    const { data, error } = useQuery(GET_STOREFRONT_CONTEXT);
+    if (
+        error &&
+        (process.env.NODE_ENV === 'development' ||
+            process.env.NODE_ENV === 'test')
+    ) {
+        console.error(
+            'Magento Storefront Instance context query failed!',
+            error
+        );
+    }
+
+    useEffect(() => {
+        let storefrontInstanceContext = null;
+        if (data && data.storefrontInstanceContext) {
+            const { storefrontInstanceContext: storefront } = data;
+            storefrontInstanceContext = {
+                catalogExtensionVersion: storefront.catalog_extension_version,
+                environment: storefront.environment,
+                environmentId: storefront.environment_id,
+                storeCode: storefront.store_code,
+                storeId: storefront.store_id,
+                storeName: storefront.store_name,
+                storeUrl: storefront.store_url,
+                storeViewCode: storefront.store_view_code,
+                storeViewId: storefront.store_view_id,
+                storeViewName: storefront.store_view_name,
+                websiteCode: storefront.website_code,
+                websiteId: storefront.website_id,
+                websiteName: storefront.website_name,
+                baseCurrencyCode: storefront.base_currency_code,
+                storeViewCurrencyCode: storefront.store_view_currency_code,
+                storefrontTemplate: 'PWA Studio'
+            };
+        }
+        mse.context.setStorefrontInstance(storefrontInstanceContext);
+    }, [data, error]);
+};
+
+export default useStorefrontInstanceContext;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useViewedOffsets.js b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useViewedOffsets.js
new file mode 100644
index 0000000000..48b3253e21
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/eventing/useViewedOffsets.js
@@ -0,0 +1,74 @@
+import { useCallback, useState } from 'react';
+import useEventListener from './useEventListener';
+
+const documentScrollTop = () =>
+    document.body.scrollTop || document.documentElement.scrollTop;
+
+const documentScrollLeft = () =>
+    document.body.scrollLeft || document.documentElement.scrollLeft;
+
+const useViewedOffsets = () => {
+    const [offsets, setOffsets] = useState(() => {
+        const xOffset = documentScrollLeft();
+        const yOffset = documentScrollTop();
+        return {
+            minXOffset: xOffset,
+            maxXOffset: xOffset + window.innerWidth,
+            minYOffset: yOffset,
+            maxYOffset: yOffset + window.innerHeight
+        };
+    });
+    let waitingOnAnimRequest = false;
+
+    // Update refs for resetting the scroll position after navigation
+    // Do we need this? Or could we just reset both to the current scroll position when the location changes?
+    const handleChange = () => {
+        if (!waitingOnAnimRequest) {
+            requestAnimationFrame(() => {
+                const windowLeft = documentScrollLeft();
+                const windowRight = windowLeft + window.innerWidth;
+                const windowTop = documentScrollTop();
+                const windowBottom = windowTop + window.innerHeight;
+                const newOffsets = { ...offsets };
+                if (windowRight > offsets.maxXOffset) {
+                    newOffsets.maxXOffset = windowRight;
+                }
+                if (windowLeft < offsets.minXOffset) {
+                    newOffsets.minXOffset = windowLeft;
+                }
+                if (windowBottom > offsets.maxYOffset) {
+                    newOffsets.maxYOffset = windowBottom;
+                }
+                if (windowTop < offsets.minYOffset) {
+                    newOffsets.minYOffset = windowTop;
+                }
+                setOffsets(newOffsets);
+                waitingOnAnimRequest = false;
+            });
+            waitingOnAnimRequest = true;
+        }
+    };
+
+    useEventListener(window, 'scroll', handleChange);
+    useEventListener(window, 'resize', handleChange);
+
+    const resetScrollOffsets = useCallback(() => {
+        const windowLeft = documentScrollLeft();
+        const windowRight = windowLeft + window.innerWidth;
+        const windowTop = documentScrollTop();
+        const windowBottom = windowTop + window.innerHeight;
+        setOffsets({
+            minXOffset: windowLeft,
+            maxXOffset: windowRight,
+            minYOffset: windowTop,
+            maxYOffset: windowBottom
+        });
+    }, []);
+
+    return {
+        resetScrollOffsets,
+        offsets
+    };
+};
+
+export default useViewedOffsets;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useAccessibleDropdown.js b/packages/extensions/venia-pwa-live-search/src/hooks/useAccessibleDropdown.js
new file mode 100644
index 0000000000..59f68970a3
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useAccessibleDropdown.js
@@ -0,0 +1,148 @@
+import { useEffect, useRef, useState, useCallback } from 'react';
+
+const registerOpenDropdownHandlers = ({
+    options,
+    activeIndex,
+    setActiveIndex,
+    select
+}) => {
+    const optionsLength = options.length;
+
+    const keyDownCallback = e => {
+        e.preventDefault();
+
+        switch (e.key) {
+            case 'Up':
+            case 'ArrowUp':
+                setActiveIndex(
+                    activeIndex <= 0 ? optionsLength - 1 : activeIndex - 1
+                );
+                return;
+            case 'Down':
+            case 'ArrowDown':
+                setActiveIndex(
+                    activeIndex + 1 === optionsLength ? 0 : activeIndex + 1
+                );
+                return;
+            case 'Enter':
+            case ' ': // Space
+                select(options[activeIndex].value);
+                return;
+            case 'Esc':
+            case 'Escape':
+                select(null);
+                return;
+            case 'PageUp':
+            case 'Home':
+                setActiveIndex(0);
+                return;
+            case 'PageDown':
+            case 'End':
+                setActiveIndex(options.length - 1);
+                return;
+        }
+    };
+
+    document.addEventListener('keydown', keyDownCallback);
+    return () => {
+        document.removeEventListener('keydown', keyDownCallback);
+    };
+};
+
+const registerClosedDropdownHandlers = ({ setIsDropdownOpen }) => {
+    const keyDownCallback = e => {
+        switch (e.key) {
+            case 'Up':
+            case 'ArrowUp':
+            case 'Down':
+            case 'ArrowDown':
+            case ' ': // Space
+            case 'Enter':
+                e.preventDefault();
+                setIsDropdownOpen(true);
+        }
+    };
+
+    document.addEventListener('keydown', keyDownCallback);
+    return () => {
+        document.removeEventListener('keydown', keyDownCallback);
+    };
+};
+
+const isSafari = () => {
+    const chromeInAgent = navigator.userAgent.indexOf('Chrome') > -1;
+    const safariInAgent = navigator.userAgent.indexOf('Safari') > -1;
+    return safariInAgent && !chromeInAgent;
+};
+
+export const useAccessibleDropdown = ({ options, value, onChange }) => {
+    const [isDropdownOpen, setIsDropdownOpenInternal] = useState(false);
+    const listRef = useRef(null);
+    const [activeIndex, setActiveIndex] = useState(0);
+    const [isFocus, setIsFocus] = useState(false);
+
+    const setIsDropdownOpen = useCallback(
+        v => {
+            if (v) {
+                const selected = options?.findIndex(o => o.value === value);
+                setActiveIndex(selected < 0 ? 0 : selected);
+
+                if (listRef.current && isSafari()) {
+                    requestAnimationFrame(() => {
+                        listRef.current?.focus();
+                    });
+                }
+            } else if (listRef.current && isSafari()) {
+                requestAnimationFrame(() => {
+                    listRef.current?.previousSibling?.focus();
+                });
+            }
+
+            setIsDropdownOpenInternal(v);
+        },
+        [options, value]
+    );
+
+    const select = useCallback(
+        val => {
+            if (val !== null && val !== undefined) {
+                onChange && onChange(val);
+            }
+            setIsDropdownOpen(false);
+            setIsFocus(false);
+        },
+        [onChange, setIsDropdownOpen]
+    );
+
+    useEffect(() => {
+        if (isDropdownOpen) {
+            return registerOpenDropdownHandlers({
+                activeIndex,
+                setActiveIndex,
+                options,
+                select
+            });
+        }
+
+        if (isFocus) {
+            return registerClosedDropdownHandlers({ setIsDropdownOpen });
+        }
+    }, [
+        isDropdownOpen,
+        activeIndex,
+        isFocus,
+        options,
+        select,
+        setIsDropdownOpen
+    ]);
+
+    return {
+        isDropdownOpen,
+        setIsDropdownOpen,
+        activeIndex,
+        setActiveIndex,
+        select,
+        setIsFocus,
+        listRef
+    };
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchPLPConfig.js b/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchPLPConfig.js
new file mode 100644
index 0000000000..50cd8e21a3
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchPLPConfig.js
@@ -0,0 +1,112 @@
+// src/hooks/useLiveSearchPLPConfig.js
+import { useQuery, useMutation } from '@apollo/client';
+import { GET_STORE_CONFIG_FOR_PLP, GET_CUSTOMER_GROUP_CODE } from '../queries';
+import CATEGORY_OPERATIONS from '@magento/peregrine/lib/talons/RootComponents/Category/categoryContent.gql';
+import { useCartContext } from '@magento/peregrine/lib/context/cart';
+import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
+import operations from '@magento/peregrine/lib/talons/Gallery/addToCart.gql';
+
+export const useLiveSearchPLPConfig = ({ categoryId }) => {
+    const { getCategoryContentQuery } = CATEGORY_OPERATIONS;
+    const { data: categoryData } = useQuery(getCategoryContentQuery, {
+        fetchPolicy: 'cache-and-network',
+        nextFetchPolicy: 'cache-first',
+        //skip: !categoryId,
+        variables: {
+            id: categoryId
+        }
+    });
+
+    const {
+        data: storeConfigData,
+        loading: loadingStoreConfig,
+        error: errorStoreConfig
+    } = useQuery(GET_STORE_CONFIG_FOR_PLP);
+
+    const { data: customerData, loading: loadingCustomer } = useQuery(
+        GET_CUSTOMER_GROUP_CODE
+    );
+
+    const loading = loadingStoreConfig || loadingCustomer;
+    const error = errorStoreConfig;
+
+    // Extract store config from the response
+    const storeConfig = storeConfigData?.storeConfig;
+    const currency = storeConfigData?.currency;
+    const baseUrl = storeConfig?.base_url || '';
+    const baseUrlwithoutProtocol = baseUrl
+        ?.replace(/^https?:/, '')
+        .replace(/\/$/, '');
+    const customerGroupCode =
+        customerData?.customer?.group_code ||
+        'b6589fc6ab0dc82cf12099d1c2d40ab994e8410c';
+
+    const [{ cartId }] = useCartContext();
+    const [addToCart] = useMutation(operations.ADD_ITEM);
+    const [, { dispatch }] = useEventingContext();
+
+    //console.log("categoryData ==",categoryData);
+    const config = {
+        environmentId: storeConfig?.ls_environment_id || '',
+        environmentType: storeConfig?.ls_environment_type || '',
+        //apiKey: storeConfig?.ls_service_api_key || '',
+        apiKey: '',
+        websiteCode: storeConfig?.website_code || '',
+        storeCode: storeConfig?.store_group_code || '',
+        storeViewCode: storeConfig?.store_code || '',
+        config: {
+            pageSize: storeConfig?.ls_page_size_default || '8',
+            perPageConfig: {
+                pageSizeOptions:
+                    storeConfig?.ls_page_size_options || '12,24,36',
+                defaultPageSizeOption: storeConfig?.ls_page_size_default || '12'
+            },
+            minQueryLength: storeConfig?.ls_min_query_length || '3',
+            currencySymbol:
+                currency?.default_display_currency_symbol || '\u0024',
+            currencyCode: currency?.default_display_currency_code || 'USD',
+            currencyRate: '1',
+            displayOutOfStock: storeConfig?.ls_display_out_of_stock || '',
+            allowAllProducts: storeConfig?.ls_allow_all || '',
+            currentCategoryUrlPath:
+                categoryData?.categories?.items[0]?.url_path,
+            categoryName: categoryData?.categories?.items[0]?.name,
+            displayMode: '',
+            locale: storeConfig?.ls_locale || 'en_US',
+            resolveCartId: () => cartId,
+            addToCart: async (sku, options, quantity) => {
+                try {
+                    await addToCart({
+                        variables: {
+                            cartId,
+                            cartItem: {
+                                quantity,
+                                entered_options: options,
+                                sku: sku
+                            }
+                        }
+                    });
+
+                    dispatch({
+                        type: 'CART_ADD_ITEM',
+                        payload: {
+                            cartId,
+                            sku: sku,
+                            selectedOptions: null,
+                            quantity
+                        }
+                    });
+                } catch (error) {
+                    console.error('Error adding to cart:', error);
+                }
+            }
+        },
+        context: {
+            customerGroup: customerGroupCode
+        },
+        baseUrl,
+        baseUrlwithoutProtocol
+    };
+
+    return { config, loading, error };
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchPopoverConfig.js b/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchPopoverConfig.js
new file mode 100644
index 0000000000..1d3989bd4f
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchPopoverConfig.js
@@ -0,0 +1,83 @@
+import { useQuery } from '@apollo/client';
+import {
+    GET_STORE_CONFIG_FOR_LIVE_SEARCH_POPOVER,
+    GET_CUSTOMER_GROUP_CODE
+} from '../queries';
+import { useUserContext } from '@magento/peregrine/lib/context/user';
+
+export const useLiveSearchPopoverConfig = () => {
+    const [{ isSignedIn }] = useUserContext();
+
+    const {
+        data: storeData,
+        loading: storeLoading,
+        error: storeError
+    } = useQuery(GET_STORE_CONFIG_FOR_LIVE_SEARCH_POPOVER);
+
+    const {
+        data: customerData,
+        loading: customerLoading,
+        error: customerError
+    } = useQuery(GET_CUSTOMER_GROUP_CODE, {
+        skip: !isSignedIn,
+        fetchPolicy: 'cache-and-network'
+    });
+
+    const storeConfig = storeData?.storeConfig || {};
+    const currency = storeData?.currency || {};
+    const baseUrl = storeConfig.base_url || '';
+    const baseUrlwithoutProtocol = baseUrl
+        .replace(/^https?:/, '')
+        .replace(/\/$/, '');
+    const customerGroupCode =
+        isSignedIn && customerData?.customer?.group_code
+            ? customerData.customer.group_code
+            : 'b6589fc6ab0dc82cf12099d1c2d40ab994e8410c';
+
+    const configReady =
+        !storeLoading &&
+        (!isSignedIn || !customerLoading) &&
+        !storeError &&
+        (!isSignedIn || !customerError) &&
+        storeConfig?.ls_environment_id; // required field
+
+    if (!configReady) {
+        return {
+            storeDetails: null,
+            storeLoading,
+            customerLoading,
+            storeError,
+            customerError,
+            configReady: false
+        };
+    }
+
+    const storeDetails = {
+        environmentId: storeConfig.ls_environment_id || '',
+        websiteCode: storeConfig.website_code || '',
+        storeCode: storeConfig.store_group_code || '',
+        storeViewCode: storeConfig.store_code || '',
+        config: {
+            pageSize: storeConfig.ls_page_size_default || '8',
+            minQueryLength: storeConfig.ls_min_query_length || '3',
+            currencySymbol:
+                currency.default_display_currency_symbol || '\u0024',
+            currencyCode: currency.default_display_currency_code || 'USD',
+            locale: storeConfig.ls_locale || 'en_US'
+        },
+        context: {
+            customerGroup: customerGroupCode
+        },
+        baseUrl,
+        baseUrlwithoutProtocol
+    };
+
+    return {
+        storeDetails,
+        storeLoading,
+        customerLoading,
+        storeError,
+        customerError,
+        configReady
+    };
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchSRLPConfig.js b/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchSRLPConfig.js
new file mode 100644
index 0000000000..933d99fdb6
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useLiveSearchSRLPConfig.js
@@ -0,0 +1,97 @@
+// src/hooks/useLiveSearchSRLPConfig.js
+import { useQuery, useMutation } from '@apollo/client';
+import { GET_STORE_CONFIG_FOR_PLP, GET_CUSTOMER_GROUP_CODE } from '../queries';
+import { useCartContext } from '@magento/peregrine/lib/context/cart';
+import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
+import operations from '@magento/peregrine/lib/talons/Gallery/addToCart.gql';
+
+export const useLiveSearchSRLPConfig = () => {
+    const {
+        data: storeConfigData,
+        loading: loadingStoreConfig,
+        error: errorStoreConfig
+    } = useQuery(GET_STORE_CONFIG_FOR_PLP);
+
+    const { data: customerData, loading: loadingCustomer } = useQuery(
+        GET_CUSTOMER_GROUP_CODE
+    );
+
+    const loading = loadingStoreConfig || loadingCustomer;
+    const error = errorStoreConfig;
+
+    // Extract store config from the response
+    const storeConfig = storeConfigData?.storeConfig;
+    const currency = storeConfigData?.currency;
+    const baseUrl = storeConfig?.base_url || '';
+    const baseUrlwithoutProtocol = baseUrl
+        ?.replace(/^https?:/, '')
+        .replace(/\/$/, '');
+    const customerGroupCode =
+        customerData?.customer?.group_code ||
+        'b6589fc6ab0dc82cf12099d1c2d40ab994e8410c';
+
+    const [{ cartId }] = useCartContext();
+    const [addToCart] = useMutation(operations.ADD_ITEM);
+    const [, { dispatch }] = useEventingContext();
+
+    const config = {
+        environmentId: storeConfig?.ls_environment_id || '',
+        environmentType: storeConfig?.ls_environment_type || '',
+        apiKey: '',
+        websiteCode: storeConfig?.website_code || '',
+        storeCode: storeConfig?.store_group_code || '',
+        storeViewCode: storeConfig?.store_code || '',
+        searchQuery: 'query',
+        config: {
+            pageSize: storeConfig?.ls_page_size_default || '8',
+            perPageConfig: {
+                pageSizeOptions:
+                    storeConfig?.ls_page_size_options || '12,24,36',
+                defaultPageSizeOption: storeConfig?.ls_page_size_default || '12'
+            },
+            minQueryLength: storeConfig?.ls_min_query_length || '3',
+            currencySymbol:
+                currency?.default_display_currency_symbol || '\u0024',
+            currencyCode: currency?.default_display_currency_code || 'USD',
+            currencyRate: '1',
+            displayOutOfStock: storeConfig?.ls_display_out_of_stock || '',
+            allowAllProducts: storeConfig?.ls_allow_all || '',
+            locale: storeConfig?.ls_locale || 'en_US',
+            resolveCartId: () => cartId,
+            addToCart: async (sku, options, quantity) => {
+                try {
+                    await addToCart({
+                        variables: {
+                            cartId,
+                            cartItem: {
+                                quantity,
+                                entered_options: options,
+                                sku: sku
+                            }
+                        }
+                    });
+
+                    dispatch({
+                        type: 'CART_ADD_ITEM',
+                        payload: {
+                            cartId,
+                            sku: sku,
+                            selectedOptions: null,
+                            quantity
+                        }
+                    });
+                } catch (error) {
+                    console.error('Error adding to cart:', error);
+                }
+            }
+        },
+        context: {
+            customerGroup: customerGroupCode
+        },
+        baseUrl,
+        baseUrlwithoutProtocol
+    };
+    console.log('SRLP config : ', config);
+
+    return { config, loading, error };
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/usePagination.js b/packages/extensions/venia-pwa-live-search/src/hooks/usePagination.js
new file mode 100644
index 0000000000..ee06fcc7dc
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/usePagination.js
@@ -0,0 +1,83 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { useMemo } from 'react';
+
+export const ELLIPSIS = '...';
+
+const getRange = (start, end) => {
+    const length = end - start + 1;
+    return Array.from({ length }, (_, index) => start + index);
+};
+
+export const usePagination = ({
+    currentPage,
+    totalPages,
+    siblingCount = 1
+}) => {
+    const paginationRange = useMemo(() => {
+        const firstPageIndex = 1;
+        const lastPageIndex = totalPages;
+        const totalPagePills = siblingCount + 5; // siblingCount + firstPage + lastPage + currentPage + 2 * ellipsis(...)
+
+        const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
+        const rightSiblingIndex = Math.min(
+            currentPage + siblingCount,
+            totalPages
+        );
+
+        // We do not show the left/right dots(...) if there is just one page left to be inserted between the extremes of sibling and the page limits.
+        const showLeftDots = leftSiblingIndex > 2;
+        const showRightDots = rightSiblingIndex < totalPages - 2;
+
+        // Case 1 - the total page count is less than the page pills we want to show.
+
+        // < 1 2 3 4 5 6 >
+        if (totalPages <= totalPagePills) {
+            return getRange(1, totalPages);
+        }
+
+        // Case 2 - the total page count is greater than the page pills and only the dots on the right are shown
+
+        // < 1 2 3 4 ... 25 >
+        if (!showLeftDots && showRightDots) {
+            const leftItemCount = 3 + 2 * siblingCount;
+            const leftRange = getRange(1, leftItemCount);
+            return [...leftRange, ELLIPSIS, totalPages];
+        }
+
+        // Case 3 - the total page count is greater than the page pills and only the dots on the left are shown
+
+        // < 1 ... 22 23 24 25 >
+        if (showLeftDots && !showRightDots) {
+            const rightItemCount = 3 + 2 * siblingCount;
+            const rightRange = getRange(
+                totalPages - rightItemCount + 1,
+                totalPages
+            );
+            return [firstPageIndex, ELLIPSIS, ...rightRange];
+        }
+
+        // Case 4 - the total page count is greater than the page pills and both the right and left dots are shown
+
+        // < 1 ... 19 20 21 ... 25 >
+        if (showLeftDots && showRightDots) {
+            const middleRange = getRange(leftSiblingIndex, rightSiblingIndex);
+            return [
+                firstPageIndex,
+                ELLIPSIS,
+                ...middleRange,
+                ELLIPSIS,
+                lastPageIndex
+            ];
+        }
+    }, [currentPage, totalPages, siblingCount]);
+
+    return paginationRange;
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useRangeFacet.js b/packages/extensions/venia-pwa-live-search/src/hooks/useRangeFacet.js
new file mode 100644
index 0000000000..ffe3928695
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useRangeFacet.js
@@ -0,0 +1,62 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { useSearch } from '../context';
+
+const useRangeFacet = ({ attribute, buckets }) => {
+    const processedBuckets = {};
+
+    buckets.forEach(bucket => {
+        processedBuckets[bucket.title] = {
+            from: bucket.from,
+            to: bucket.to
+        };
+    });
+
+    const searchCtx = useSearch();
+
+    const filter = searchCtx?.filters?.find(e => e.attribute === attribute);
+
+    const isSelected = title => {
+        const selected = filter
+            ? processedBuckets[title].from === filter.range?.from &&
+              processedBuckets[title].to === filter.range?.to
+            : false;
+        return selected;
+    };
+
+    const onChange = value => {
+        const selectedRange = processedBuckets[value];
+
+        if (!filter) {
+            const newFilter = {
+                attribute,
+                range: {
+                    from: selectedRange.from,
+                    to: selectedRange.to
+                }
+            };
+            searchCtx.createFilter(newFilter);
+            return;
+        }
+
+        const newFilter = {
+            ...filter,
+            range: {
+                from: selectedRange.from,
+                to: selectedRange.to
+            }
+        };
+        searchCtx.updateFilter(newFilter);
+    };
+
+    return { isSelected, onChange };
+};
+
+export default useRangeFacet;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useScalarFacet.js b/packages/extensions/venia-pwa-live-search/src/hooks/useScalarFacet.js
new file mode 100644
index 0000000000..1b97f0122b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useScalarFacet.js
@@ -0,0 +1,61 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { useSearch } from '../context';
+
+const useScalarFacet = facet => {
+    const searchCtx = useSearch();
+
+    const filter = searchCtx?.filters?.find(
+        e => e.attribute === facet.attribute
+    );
+
+    const isSelected = attribute => {
+        return filter ? filter.in?.includes(attribute) : false;
+    };
+
+    const onChange = (value, selected) => {
+        if (!filter) {
+            const newFilter = {
+                attribute: facet.attribute,
+                in: [value]
+            };
+
+            searchCtx.createFilter(newFilter);
+            return;
+        }
+
+        const newFilter = { ...filter };
+        const currentFilterIn = filter.in || [];
+
+        newFilter.in = selected
+            ? [...currentFilterIn, value]
+            : filter.in?.filter(e => e !== value);
+
+        const filterUnselected = filter.in?.filter(
+            x => !newFilter.in?.includes(x)
+        );
+
+        if (newFilter.in?.length) {
+            if (filterUnselected?.length) {
+                searchCtx.removeFilter(facet.attribute, filterUnselected[0]);
+            }
+            searchCtx.updateFilter(newFilter);
+            return;
+        }
+
+        if (!newFilter.in?.length) {
+            searchCtx.removeFilter(facet.attribute);
+        }
+    };
+
+    return { isSelected, onChange };
+};
+
+export default useScalarFacet;
diff --git a/packages/extensions/venia-pwa-live-search/src/hooks/useSliderFacet.js b/packages/extensions/venia-pwa-live-search/src/hooks/useSliderFacet.js
new file mode 100644
index 0000000000..7d6862b0d3
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/hooks/useSliderFacet.js
@@ -0,0 +1,43 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { useSearch } from '../context';
+
+const useSliderFacet = ({ attribute }) => {
+    const searchCtx = useSearch();
+
+    const onChange = (from, to) => {
+        const filter = searchCtx?.filters?.find(e => e.attribute === attribute);
+
+        if (!filter) {
+            const newFilter = {
+                attribute,
+                range: {
+                    from,
+                    to
+                }
+            };
+            searchCtx.createFilter(newFilter);
+            return;
+        }
+
+        const newFilter = {
+            ...filter,
+            range: {
+                from,
+                to
+            }
+        };
+        searchCtx.updateFilter(newFilter);
+    };
+
+    return { onChange };
+};
+
+export default useSliderFacet;
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/Sorani.js b/packages/extensions/venia-pwa-live-search/src/i18n/Sorani.js
new file mode 100644
index 0000000000..3e30d667a5
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/Sorani.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const Sorani = {
+    Filter: {
+        title: 'فلتەرەکان',
+        showTitle: 'پیشاندانی فلتەرەکان',
+        hideTitle: 'شاردنەوەی فلتەرەکان',
+        clearAll: 'سڕینەوەی هەمووان'
+    },
+    InputButtonGroup: {
+        title: 'پۆلەکان',
+        price: 'نرخ',
+        customPrice: 'نرخی بەکەسیکراو',
+        priceIncluded: 'بەڵێ',
+        priceExcluded: 'نەخێر',
+        priceExcludedMessage: 'نا {title}',
+        priceRange: ' و سەرووتر',
+        showmore: 'بینینی زیاتر'
+    },
+    Loading: {
+        title: 'بارکردن'
+    },
+    NoResults: {
+        heading: 'هیچ ئەنجامێک بۆ گەڕانەکەت نییە.',
+        subheading: 'تكایە دیسان هەوڵ بدەوە...'
+    },
+    SortDropdown: {
+        title: 'پۆلێنکردن بەگوێرەی',
+        option: 'پۆلێنکردن بەگوێرەی: {selectedOption}',
+        relevanceLabel: 'پەیوەندیدارترین',
+        positionLabel: 'شوێن'
+    },
+    CategoryFilters: {
+        results: 'ئەنجامەکان بۆ {phrase}',
+        products: '{totalCount} بەرهەمەکان'
+    },
+    ProductCard: {
+        asLowAs: 'بەقەد نزمیی {discountPrice}',
+        startingAt: 'دەستپێدەکات لە {productPrice}',
+        bundlePrice: 'لە {fromBundlePrice} بۆ {toBundlePrice}',
+        from: 'لە {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'زاراوەی گەڕانەکەت {variables.phrase} بەلانی کەم نەگەیشتۆتە {minQueryLength} پیت.',
+        noresults: 'گەڕانەکەت هیچ ئەنجامێکی نەبوو.',
+        pagePicker: 'پیشاندانی {pageSize} لە هەر لاپەڕەیەکدا',
+        showAll: 'هەموو'
+    },
+    SearchBar: {
+        placeholder: 'گەڕان...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/ar_AE.js b/packages/extensions/venia-pwa-live-search/src/i18n/ar_AE.js
new file mode 100644
index 0000000000..bd02a07a2a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/ar_AE.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const ar_AE = {
+    Filter: {
+        title: 'عوامل التصفية',
+        showTitle: 'إظهار عوامل التصفية',
+        hideTitle: 'إخفاء عوامل التصفية',
+        clearAll: 'مسح الكل'
+    },
+    InputButtonGroup: {
+        title: 'الفئات',
+        price: 'السعر',
+        customPrice: 'السعر المخصص',
+        priceIncluded: 'نعم.',
+        priceExcluded: 'لا',
+        priceExcludedMessage: 'ليس {title}',
+        priceRange: ' وما بعده',
+        showmore: 'إظهار أكثر'
+    },
+    Loading: {
+        title: 'تحميل'
+    },
+    NoResults: {
+        heading: 'لا يوجد نتائج لبحثك.',
+        subheading: 'الرجاء المحاولة مرة أخرى...'
+    },
+    SortDropdown: {
+        title: 'فرز حسب',
+        option: 'فرز حسب: {selectedOption}',
+        relevanceLabel: 'الأكثر صلة',
+        positionLabel: 'الموضع'
+    },
+    CategoryFilters: {
+        results: 'النتائج لـ {phrase}',
+        products: 'منتجات {totalCount}'
+    },
+    ProductCard: {
+        asLowAs: 'بقيمة {discountPrice} فقط',
+        startingAt: 'بدءًا من {productPrice}',
+        bundlePrice: 'من {fromBundlePrice} إلى {toBundlePrice}',
+        from: 'من {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'مصطلح البحث الخاص بك {variables.phrase} لم يصل إلى {minQueryLength} من الأحرف كحد أدنى.',
+        noresults: 'لا يوجد لبحثك أي نتائج.',
+        pagePicker: 'إظهار {pageSize} لكل صفحة',
+        showAll: 'الكل'
+    },
+    SearchBar: {
+        placeholder: 'بحث...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/bg_BG.js b/packages/extensions/venia-pwa-live-search/src/i18n/bg_BG.js
new file mode 100644
index 0000000000..a3ad4c7b99
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/bg_BG.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const bg_BG = {
+    Filter: {
+        title: 'Филтри',
+        showTitle: 'Показване на филтри',
+        hideTitle: 'Скриване на филтри',
+        clearAll: 'Изчистване на всичко'
+    },
+    InputButtonGroup: {
+        title: 'Категории',
+        price: 'Цена',
+        customPrice: 'Персонализирана цена',
+        priceIncluded: 'да',
+        priceExcluded: 'не',
+        priceExcludedMessage: 'Не {title}',
+        priceRange: ' и по-висока',
+        showmore: 'Показване на повече'
+    },
+    Loading: {
+        title: 'Зареждане'
+    },
+    NoResults: {
+        heading: 'Няма резултати за вашето търсене.',
+        subheading: 'Моля, опитайте отново...'
+    },
+    SortDropdown: {
+        title: 'Сортиране по',
+        option: 'Сортиране по: {selectedOption}',
+        relevanceLabel: 'Най-подходящи',
+        positionLabel: 'Позиция'
+    },
+    CategoryFilters: {
+        results: 'резултати за {phrase}',
+        products: '{totalCount} продукта'
+    },
+    ProductCard: {
+        asLowAs: 'Само {discountPrice}',
+        startingAt: 'От {productPrice}',
+        bundlePrice: 'От {fromBundlePrice} до {toBundlePrice}',
+        from: 'От {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Вашата дума за търсене {variables.phrase} не достига минимума от {minQueryLength} знака.',
+        noresults: 'Вашето търсене не даде резултати.',
+        pagePicker: 'Показване на {pageSize} на страница',
+        showAll: 'всички'
+    },
+    SearchBar: {
+        placeholder: 'Търсене...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/bn_IN.js b/packages/extensions/venia-pwa-live-search/src/i18n/bn_IN.js
new file mode 100644
index 0000000000..f38aaaefb0
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/bn_IN.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const bn_IN = {
+    Filter: {
+        title: 'ফিল্টারগুলি',
+        showTitle: 'ফিল্টারগুলি দেখান',
+        hideTitle: 'ফিল্টারগুলি লুকান',
+        clearAll: 'সব ক্লিয়ার করুন'
+    },
+    InputButtonGroup: {
+        title: 'ক্যাটেগরি',
+        price: 'মূল্য',
+        customPrice: 'কাস্টম প্রাইস',
+        priceIncluded: 'হ্যাঁ',
+        priceExcluded: 'না',
+        priceExcludedMessage: 'না {title}',
+        priceRange: ' এবং উর্দ্ধে',
+        showmore: 'আরো দেখান'
+    },
+    Loading: {
+        title: 'লোডিং হচ্ছে'
+    },
+    NoResults: {
+        heading: 'আপনার অনুসন্ধানের কোনো ফলাফল নেই।',
+        subheading: 'অনুগ্রহ করে পুনরায় চেষ্টা করুন...'
+    },
+    SortDropdown: {
+        title: 'ক্রমানুসারে সাজান',
+        option: 'ক্রমানুসারে সাজান: {selectedOption}',
+        relevanceLabel: 'সবচেয়ে প্রাসঙ্গিক',
+        positionLabel: 'অবস্থান'
+    },
+    CategoryFilters: {
+        results: '{phrase} এর জন্য ফলাফল',
+        products: '{totalCount} প্রোডাক্টগুলি'
+    },
+    ProductCard: {
+        asLowAs: 'এত কম যে {discountPrice}',
+        startingAt: 'শুরু হচ্ছে {productPrice}',
+        bundlePrice: '{fromBundlePrice} থেকে {toBundlePrice} পর্যন্ত',
+        from: '{productPrice} থেকে'
+    },
+    ProductContainers: {
+        minquery:
+            'আপনার অনুসন্ধান করা শব্দটি {variables.phrase} ন্যূনতম অক্ষরসীমা {minQueryLength} পর্যন্ত পৌঁছাতে পারেনি।',
+        noresults: 'আপনার অনুসন্ধান থেকে কোনো ফলাফল পাওয়া যায়নি।',
+        pagePicker: 'পৃষ্ঠা {pageSize} অনুযায়ী দেখান',
+        showAll: 'সবগুলি'
+    },
+    SearchBar: {
+        placeholder: 'অনুসন্ধান করুন...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/ca_ES.js b/packages/extensions/venia-pwa-live-search/src/i18n/ca_ES.js
new file mode 100644
index 0000000000..8cdb379a79
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/ca_ES.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const ca_ES = {
+    Filter: {
+        title: 'Filtres',
+        showTitle: 'Mostra els filtres',
+        hideTitle: 'Amaga els filtres',
+        clearAll: 'Esborra-ho tot'
+    },
+    InputButtonGroup: {
+        title: 'Categories',
+        price: 'Preu',
+        customPrice: 'Preu personalitzat',
+        priceIncluded: 'sí',
+        priceExcluded: 'no',
+        priceExcludedMessage: 'No {title}',
+        priceRange: ' i superior',
+        showmore: 'Mostra més'
+    },
+    Loading: {
+        title: 'Carregant'
+    },
+    NoResults: {
+        heading: 'No hi ha resultats per a la vostra cerca.',
+        subheading: 'Siusplau torna-ho a provar...'
+    },
+    SortDropdown: {
+        title: 'Ordenar per',
+        option: 'Ordena per: {selectedOption}',
+        relevanceLabel: 'El més rellevant',
+        positionLabel: 'Posició'
+    },
+    CategoryFilters: {
+        results: 'Resultats per a {phrase}',
+        products: '{totalCount}productes'
+    },
+    ProductCard: {
+        asLowAs: 'Mínim de {discountPrice}',
+        startingAt: 'A partir de {productPrice}',
+        bundlePrice: 'Des de {fromBundlePrice} A {toBundlePrice}',
+        from: 'Des de {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'El vostre terme de cerca {variables.phrase} no ha arribat al mínim de {minQueryLength} caràcters.',
+        noresults: 'La vostra cerca no ha retornat cap resultat.',
+        pagePicker: 'Mostra {pageSize} per pàgina',
+        showAll: 'tots'
+    },
+    SearchBar: {
+        placeholder: 'Cerca...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/cs_CZ.js b/packages/extensions/venia-pwa-live-search/src/i18n/cs_CZ.js
new file mode 100644
index 0000000000..4bbcc241ae
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/cs_CZ.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const cs_CZ = {
+    Filter: {
+        title: 'Filtry',
+        showTitle: 'Zobrazit filtry',
+        hideTitle: 'Skrýt filtry',
+        clearAll: 'Vymazat vše'
+    },
+    InputButtonGroup: {
+        title: 'Kategorie',
+        price: 'Cena',
+        customPrice: 'Vlastní cena',
+        priceIncluded: 'ano',
+        priceExcluded: 'ne',
+        priceExcludedMessage: 'Ne {title}',
+        priceRange: ' a výše',
+        showmore: 'Zobrazit více'
+    },
+    Loading: {
+        title: 'Načítá se'
+    },
+    NoResults: {
+        heading: 'Nebyly nalezeny žádné výsledky.',
+        subheading: 'Zkuste to znovu...'
+    },
+    SortDropdown: {
+        title: 'Seřadit podle',
+        option: 'Seřadit podle: {selectedOption}',
+        relevanceLabel: 'Nejrelevantnější',
+        positionLabel: 'Umístění'
+    },
+    CategoryFilters: {
+        results: 'výsledky pro {phrase}',
+        products: 'Produkty: {totalCount}'
+    },
+    ProductCard: {
+        asLowAs: 'Pouze za {discountPrice}',
+        startingAt: 'Cena od {productPrice}',
+        bundlePrice: 'Z {fromBundlePrice} na {toBundlePrice}',
+        from: 'Z {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Hledaný výraz {variables.phrase} nedosáhl minima počtu znaků ({minQueryLength}).',
+        noresults: 'Při hledání nebyly nalezeny žádné výsledky.',
+        pagePicker: 'Zobrazit {pageSize} na stránku',
+        showAll: 'vše'
+    },
+    SearchBar: {
+        placeholder: 'Hledat...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/da_DK.js b/packages/extensions/venia-pwa-live-search/src/i18n/da_DK.js
new file mode 100644
index 0000000000..b08c282ddb
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/da_DK.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const da_DK = {
+    Filter: {
+        title: 'Filtre',
+        showTitle: 'Vis filtre',
+        hideTitle: 'Skjul filtre',
+        clearAll: 'Ryd alt'
+    },
+    InputButtonGroup: {
+        title: 'Kategorier',
+        price: 'Pris',
+        customPrice: 'Brugerdefineret pris',
+        priceIncluded: 'ja',
+        priceExcluded: 'nej',
+        priceExcludedMessage: 'Ikke {title}',
+        priceRange: ' og over',
+        showmore: 'Vis mere'
+    },
+    Loading: {
+        title: 'Indlæser'
+    },
+    NoResults: {
+        heading: 'Ingen søgeresultater for din søgning',
+        subheading: 'Prøv igen...'
+    },
+    SortDropdown: {
+        title: 'Sortér efter',
+        option: 'Sortér efter: {selectedOption}',
+        relevanceLabel: 'Mest relevant',
+        positionLabel: 'Position'
+    },
+    CategoryFilters: {
+        results: 'resultater for {phrase}',
+        products: '{totalCount} produkter'
+    },
+    ProductCard: {
+        asLowAs: 'Så lav som {discountPrice}',
+        startingAt: 'Fra {productPrice}',
+        bundlePrice: 'Fra {fromBundlePrice} til {toBundlePrice}',
+        from: 'Fra {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Dit søgeord {variables.phrase} har ikke minimum på {minQueryLength} tegn.',
+        noresults: 'Din søgning gav ingen resultater.',
+        pagePicker: 'Vis {pageSize} pr. side',
+        showAll: 'alle'
+    },
+    SearchBar: {
+        placeholder: 'Søg...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/de_DE.js b/packages/extensions/venia-pwa-live-search/src/i18n/de_DE.js
new file mode 100644
index 0000000000..7947ec6bbf
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/de_DE.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const de_DE = {
+    Filter: {
+        title: 'Filter',
+        showTitle: 'Filter einblenden',
+        hideTitle: 'Filter ausblenden',
+        clearAll: 'Alle löschen'
+    },
+    InputButtonGroup: {
+        title: 'Kategorien',
+        price: 'Preis',
+        customPrice: 'Benutzerdefinierter Preis',
+        priceIncluded: 'ja',
+        priceExcluded: 'nein',
+        priceExcludedMessage: 'Nicht {title}',
+        priceRange: ' und höher',
+        showmore: 'Mehr anzeigen'
+    },
+    Loading: {
+        title: 'Ladevorgang läuft'
+    },
+    NoResults: {
+        heading: 'Keine Ergebnisse zu Ihrer Suche.',
+        subheading: 'Versuchen Sie es erneut...'
+    },
+    SortDropdown: {
+        title: 'Sortieren nach',
+        option: 'Sortieren nach: {selectedOption}',
+        relevanceLabel: 'Höchste Relevanz',
+        positionLabel: 'Position'
+    },
+    CategoryFilters: {
+        results: 'Ergebnisse für {phrase}',
+        products: '{totalCount} Produkte'
+    },
+    ProductCard: {
+        asLowAs: 'Schon ab {discountPrice}',
+        startingAt: 'Ab {productPrice}',
+        bundlePrice: 'Aus {fromBundlePrice} zu {toBundlePrice}',
+        from: 'Ab {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Ihr Suchbegriff {variables.phrase} ist kürzer als das Minimum von {minQueryLength} Zeichen.',
+        noresults: 'Zu Ihrer Suche wurden keine Ergebnisse zurückgegeben.',
+        pagePicker: '{pageSize} pro Seite anzeigen',
+        showAll: 'alle'
+    },
+    SearchBar: {
+        placeholder: 'Suchen...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/el_GR.js b/packages/extensions/venia-pwa-live-search/src/i18n/el_GR.js
new file mode 100644
index 0000000000..c98d2a7896
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/el_GR.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const el_GR = {
+    Filter: {
+        title: 'Φίλτρα',
+        showTitle: 'Εμφάνιση φίλτρων',
+        hideTitle: 'Απόκρυψη φίλτρων',
+        clearAll: 'Απαλοιφή όλων'
+    },
+    InputButtonGroup: {
+        title: 'Κατηγορίες',
+        price: 'Τιμή',
+        customPrice: 'Προσαρμοσμένη τιμή',
+        priceIncluded: 'ναι',
+        priceExcluded: 'όχι',
+        priceExcludedMessage: 'Όχι {title}',
+        priceRange: ' και παραπάνω',
+        showmore: 'Εμφάνιση περισσότερων'
+    },
+    Loading: {
+        title: 'Γίνεται φόρτωση'
+    },
+    NoResults: {
+        heading: 'Δεν υπάρχουν αποτελέσματα για την αναζήτησή σας.',
+        subheading: 'Προσπαθήστε ξανά...'
+    },
+    SortDropdown: {
+        title: 'Ταξινόμηση κατά',
+        option: 'Ταξινόμηση κατά: {selectedOption}',
+        relevanceLabel: 'Το πιο σχετικό',
+        positionLabel: 'Θέση'
+    },
+    CategoryFilters: {
+        results: 'αποτελέσματα για {phrase}',
+        products: '{totalCount} προϊόντα'
+    },
+    ProductCard: {
+        asLowAs: 'Τόσο χαμηλά όσο {discountPrice}',
+        startingAt: 'Έναρξη από {productPrice}',
+        bundlePrice: 'Από {fromBundlePrice} Προς {toBundlePrice}',
+        from: 'Από {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Ο όρος αναζήτησής σας {variables.phrase} δεν έχει φτάσει στο ελάχιστο {minQueryLength} χαρακτήρες.',
+        noresults: 'Η αναζήτηση δεν επέστρεψε κανένα αποτέλεσμα.',
+        pagePicker: 'Προβολή {pageSize} ανά σελίδα',
+        showAll: 'όλα'
+    },
+    SearchBar: {
+        placeholder: 'Αναζήτηση...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/en_GA.js b/packages/extensions/venia-pwa-live-search/src/i18n/en_GA.js
new file mode 100644
index 0000000000..594cd44b77
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/en_GA.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const en_GA = {
+    Filter: {
+        title: 'Scagairí',
+        showTitle: 'Taispeáin scagairí',
+        hideTitle: 'Folaigh scagairí',
+        clearAll: 'Glan gach'
+    },
+    InputButtonGroup: {
+        title: 'Catagóirí',
+        price: 'Praghas',
+        customPrice: 'Saincheap Praghas',
+        priceIncluded: 'tá',
+        priceExcluded: 'níl',
+        priceExcludedMessage: 'Ní {title}',
+        priceRange: ' agus níos costasaí',
+        showmore: 'Taispeáin níos mó'
+    },
+    Loading: {
+        title: 'Lódáil'
+    },
+    NoResults: {
+        heading: 'Níl aon torthaí ar do chuardach.',
+        subheading: 'Bain triail eile as...'
+    },
+    SortDropdown: {
+        title: 'Sórtáil de réir',
+        option: 'Sórtáil de réir: {selectedOption}',
+        relevanceLabel: 'Is Ábhartha',
+        positionLabel: 'Post'
+    },
+    CategoryFilters: {
+        results: 'torthaí do {phrase}',
+        products: '{totalCount} táirge'
+    },
+    ProductCard: {
+        asLowAs: 'Chomh híseal le {discountPrice}',
+        startingAt: 'Ag tosú ag {productPrice}',
+        bundlePrice: 'Ó {fromBundlePrice} go {toBundlePrice}',
+        from: 'Ó {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Níor shroich do théarma cuardaigh {variables.phrase} íosmhéid {minQueryLength} carachtar.',
+        noresults: 'Níl aon torthaí ar do chuardach.',
+        pagePicker: 'Taispeáin {pageSize} in aghaidh an leathanaigh',
+        showAll: 'gach'
+    },
+    SearchBar: {
+        placeholder: 'Cuardaigh...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/en_GB.js b/packages/extensions/venia-pwa-live-search/src/i18n/en_GB.js
new file mode 100644
index 0000000000..60a3b56836
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/en_GB.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const en_GB = {
+    Filter: {
+        title: 'Filters',
+        showTitle: 'Show filters',
+        hideTitle: 'Hide filters',
+        clearAll: 'Clear all'
+    },
+    InputButtonGroup: {
+        title: 'Categories',
+        price: 'Price',
+        customPrice: 'Custom Price',
+        priceIncluded: 'yes',
+        priceExcluded: 'no',
+        priceExcludedMessage: 'Not {title}',
+        priceRange: ' and above',
+        showmore: 'Show more'
+    },
+    Loading: {
+        title: 'Loading'
+    },
+    NoResults: {
+        heading: 'No results for your search.',
+        subheading: 'Please try again...'
+    },
+    SortDropdown: {
+        title: 'Sort by',
+        option: 'Sort by: {selectedOption}',
+        relevanceLabel: 'Most Relevant',
+        positionLabel: 'Position'
+    },
+    CategoryFilters: {
+        results: 'results for {phrase}',
+        products: '{totalCount} products'
+    },
+    ProductCard: {
+        asLowAs: 'As low as {discountPrice}',
+        startingAt: 'Starting at {productPrice}',
+        bundlePrice: 'From {fromBundlePrice} To {toBundlePrice}',
+        from: 'From {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Your search term {variables.phrase} has not reached the minimum of {minQueryLength} characters.',
+        noresults: 'Your search returned no results.',
+        pagePicker: 'Show {pageSize} per page',
+        showAll: 'all'
+    },
+    SearchBar: {
+        placeholder: 'Search...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/en_US.js b/packages/extensions/venia-pwa-live-search/src/i18n/en_US.js
new file mode 100644
index 0000000000..3c64ac4d77
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/en_US.js
@@ -0,0 +1,70 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const en_US = {
+    Filter: {
+        title: 'Filters',
+        showTitle: 'Show filters',
+        hideTitle: 'Hide filters',
+        clearAll: 'Clear all'
+    },
+    InputButtonGroup: {
+        title: 'Categories',
+        price: 'Price',
+        customPrice: 'Custom Price',
+        priceIncluded: 'yes',
+        priceExcluded: 'no',
+        priceExcludedMessage: 'Not {title}',
+        priceRange: ' and above',
+        showmore: 'Show more'
+    },
+    Loading: {
+        title: 'Loading'
+    },
+    NoResults: {
+        heading: 'No results for your search.',
+        subheading: 'Please try again...'
+    },
+    SortDropdown: {
+        title: 'Sort by',
+        option: 'Sort by: {selectedOption}',
+        relevanceLabel: 'Most Relevant',
+        positionLabel: 'Position',
+        sortAttributeASC: '{label}: Low to High',
+        sortAttributeDESC: '{label}: High to Low',
+        sortASC: 'Price: Low to High',
+        sortDESC: 'Price: High to Low',
+        productName: 'Product Name',
+        productInStock: 'In Stock',
+        productLowStock: 'Low Stock'
+    },
+    CategoryFilters: {
+        results: 'results for {phrase}',
+        products: '{totalCount} products'
+    },
+    ProductCard: {
+        asLowAs: 'As low as {discountPrice}',
+        startingAt: 'Starting at {productPrice}',
+        bundlePrice: 'From {fromBundlePrice} To {toBundlePrice}',
+        from: 'From {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Your search term {variables.phrase} has not reached the minimum of {minQueryLength} characters.',
+        noresults: 'Your search returned no results.',
+        pagePicker: 'Show {pageSize} per page',
+        showAll: 'all'
+    },
+    SearchBar: {
+        placeholder: 'Search...'
+    },
+    ListView: {
+        viewDetails: 'View details'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/es_ES.js b/packages/extensions/venia-pwa-live-search/src/i18n/es_ES.js
new file mode 100644
index 0000000000..30ca3d3237
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/es_ES.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const es_ES = {
+    Filter: {
+        title: 'Filtros',
+        showTitle: 'Mostrar filtros',
+        hideTitle: 'Ocultar filtros',
+        clearAll: 'Borrar todo'
+    },
+    InputButtonGroup: {
+        title: 'Categorías',
+        price: 'Precio',
+        customPrice: 'Precio personalizado',
+        priceIncluded: 'sí',
+        priceExcluded: 'no',
+        priceExcludedMessage: 'No es {title}',
+        priceRange: ' y más',
+        showmore: 'Mostrar más'
+    },
+    Loading: {
+        title: 'Cargando'
+    },
+    NoResults: {
+        heading: 'No hay resultados para tu búsqueda.',
+        subheading: 'Inténtalo de nuevo...'
+    },
+    SortDropdown: {
+        title: 'Ordenar por',
+        option: 'Ordenar por: {selectedOption}',
+        relevanceLabel: 'Más relevantes',
+        positionLabel: 'Posición'
+    },
+    CategoryFilters: {
+        results: 'resultados de {phrase}',
+        products: '{totalCount} productos'
+    },
+    ProductCard: {
+        asLowAs: 'Por solo {discountPrice}',
+        startingAt: 'A partir de {productPrice}',
+        bundlePrice: 'Desde {fromBundlePrice} hasta {toBundlePrice}',
+        from: 'Desde {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'El término de búsqueda {variables.phrase} no llega al mínimo de {minQueryLength} caracteres.',
+        noresults: 'Tu búsqueda no ha dado resultados.',
+        pagePicker: 'Mostrar {pageSize} por página',
+        showAll: 'todo'
+    },
+    SearchBar: {
+        placeholder: 'Buscar...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/et_EE.js b/packages/extensions/venia-pwa-live-search/src/i18n/et_EE.js
new file mode 100644
index 0000000000..042aee7e1c
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/et_EE.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const et_EE = {
+    Filter: {
+        title: 'Filtrid',
+        showTitle: 'Kuva filtrid',
+        hideTitle: 'Peida filtrid',
+        clearAll: 'Tühjenda kõik'
+    },
+    InputButtonGroup: {
+        title: 'Kategooriad',
+        price: 'Hind',
+        customPrice: 'Kohandatud hind',
+        priceIncluded: 'jah',
+        priceExcluded: 'ei',
+        priceExcludedMessage: 'Mitte {title}',
+        priceRange: ' ja üleval',
+        showmore: 'Kuva rohkem'
+    },
+    Loading: {
+        title: 'Laadimine'
+    },
+    NoResults: {
+        heading: 'Teie otsingule pole tulemusi.',
+        subheading: 'Proovige uuesti…'
+    },
+    SortDropdown: {
+        title: 'Sortimisjärjekord',
+        option: 'Sortimisjärjekord: {selectedOption}',
+        relevanceLabel: 'Kõige asjakohasem',
+        positionLabel: 'Asukoht'
+    },
+    CategoryFilters: {
+        results: '{phrase} tulemused',
+        products: '{totalCount} toodet'
+    },
+    ProductCard: {
+        asLowAs: 'Ainult {discountPrice}',
+        startingAt: 'Alates {productPrice}',
+        bundlePrice: 'Alates {fromBundlePrice} kuni {toBundlePrice}',
+        from: 'Alates {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Teie otsingutermin {variables.phrase} ei sisalda vähemalt {minQueryLength} tähemärki.',
+        noresults: 'Teie otsing ei andnud tulemusi.',
+        pagePicker: 'Näita {pageSize} lehekülje kohta',
+        showAll: 'kõik'
+    },
+    SearchBar: {
+        placeholder: 'Otsi…'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/eu_ES.js b/packages/extensions/venia-pwa-live-search/src/i18n/eu_ES.js
new file mode 100644
index 0000000000..7b31dc024d
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/eu_ES.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const eu_ES = {
+    Filter: {
+        title: 'Iragazkiak',
+        showTitle: 'Erakutsi iragazkiak',
+        hideTitle: 'Ezkutatu iragazkiak',
+        clearAll: 'Garbitu dena'
+    },
+    InputButtonGroup: {
+        title: 'Kategoriak',
+        price: 'Prezioa',
+        customPrice: 'Prezio pertsonalizatua',
+        priceIncluded: 'bai',
+        priceExcluded: 'ez',
+        priceExcludedMessage: 'Ez da {title}',
+        priceRange: ' eta gorago',
+        showmore: 'Erakutsi gehiago'
+    },
+    Loading: {
+        title: 'Kargatzen'
+    },
+    NoResults: {
+        heading: 'Ez dago emaitzarik zure bilaketarako.',
+        subheading: 'Saiatu berriro mesedez...'
+    },
+    SortDropdown: {
+        title: 'Ordenatu',
+        option: 'Ordenatu honen arabera: {selectedOption}',
+        relevanceLabel: 'Garrantzitsuena',
+        positionLabel: 'Posizioa'
+    },
+    CategoryFilters: {
+        results: '{phrase} bilaketaren emaitzak',
+        products: '{totalCount} produktu'
+    },
+    ProductCard: {
+        asLowAs: '{discountPrice} bezain baxua',
+        startingAt: '{productPrice}-tatik hasita',
+        bundlePrice: '{fromBundlePrice} eta {toBundlePrice} artean',
+        from: '{productPrice}-tatik hasita'
+    },
+    ProductContainers: {
+        minquery:
+            'Zure bilaketa-terminoa ({variables.phrase}) ez da iritsi gutxieneko {minQueryLength} karakteretara.',
+        noresults: 'Zure bilaketak ez du emaitzarik eman.',
+        pagePicker: 'Erakutsi {pageSize} orriko',
+        showAll: 'guztiak'
+    },
+    SearchBar: {
+        placeholder: 'Bilatu...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/fa_IR.js b/packages/extensions/venia-pwa-live-search/src/i18n/fa_IR.js
new file mode 100644
index 0000000000..dbe60fc19c
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/fa_IR.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const fa_IR = {
+    Filter: {
+        title: 'فیلترها',
+        showTitle: 'نمایش فیلترها',
+        hideTitle: 'محو فیلترها',
+        clearAll: 'پاک کردن همه'
+    },
+    InputButtonGroup: {
+        title: 'دسته‌ها',
+        price: 'قیمت',
+        customPrice: 'قیمت سفارشی',
+        priceIncluded: 'بله',
+        priceExcluded: 'خیر',
+        priceExcludedMessage: 'نه {title}',
+        priceRange: ' و بالاتر',
+        showmore: 'نمایش بیشتر'
+    },
+    Loading: {
+        title: 'درحال بارگیری'
+    },
+    NoResults: {
+        heading: 'جستجوی شما نتیجه‌ای دربر نداشت.',
+        subheading: 'لطفاً دوباره امتحان کنید...'
+    },
+    SortDropdown: {
+        title: 'مرتب‌سازی براساس',
+        option: 'مرتب‌سازی براساس: {selectedOption}',
+        relevanceLabel: 'مرتبط‌ترین',
+        positionLabel: 'موقعیت'
+    },
+    CategoryFilters: {
+        results: 'نتایج برای {phrase}',
+        products: '{totalCount} محصولات'
+    },
+    ProductCard: {
+        asLowAs: 'برابر با {discountPrice}',
+        startingAt: 'شروع از {productPrice}',
+        bundlePrice: 'از {fromBundlePrice} تا {toBundlePrice}',
+        from: 'از {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'عبارت جستجوی شما {variables.phrase} به حداقل تعداد کاراکترهای لازم یعنی {minQueryLength} کاراکتر نرسیده است.',
+        noresults: 'جستجوی شما نتیجه‌ای را حاصل نکرد.',
+        pagePicker: 'نمایش {pageSize} در هر صفحه',
+        showAll: 'همه'
+    },
+    SearchBar: {
+        placeholder: 'جستجو...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/fi_FI.js b/packages/extensions/venia-pwa-live-search/src/i18n/fi_FI.js
new file mode 100644
index 0000000000..24301e2f84
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/fi_FI.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const fi_FI = {
+    Filter: {
+        title: 'Suodattimet',
+        showTitle: 'Näytä suodattimet',
+        hideTitle: 'Piilota suodattimet',
+        clearAll: 'Poista kaikki'
+    },
+    InputButtonGroup: {
+        title: 'Luokat',
+        price: 'Hinta',
+        customPrice: 'Mukautettu hinta',
+        priceIncluded: 'kyllä',
+        priceExcluded: 'ei',
+        priceExcludedMessage: 'Ei {title}',
+        priceRange: ' ja enemmän',
+        showmore: 'Näytä enemmän'
+    },
+    Loading: {
+        title: 'Ladataan'
+    },
+    NoResults: {
+        heading: 'Haullasi ei löytynyt tuloksia.',
+        subheading: 'Yritä uudelleen...'
+    },
+    SortDropdown: {
+        title: 'Lajitteluperuste',
+        option: 'Lajitteluperuste: {selectedOption}',
+        relevanceLabel: 'Olennaisimmat',
+        positionLabel: 'Sijainti'
+    },
+    CategoryFilters: {
+        results: 'tulosta ilmaukselle {phrase}',
+        products: '{totalCount} tuotetta'
+    },
+    ProductCard: {
+        asLowAs: 'Parhaimmillaan {discountPrice}',
+        startingAt: 'Alkaen {productPrice}',
+        bundlePrice: '{fromBundlePrice} alkaen {toBundlePrice} asti',
+        from: '{productPrice} alkaen'
+    },
+    ProductContainers: {
+        minquery:
+            'Hakusanasi {variables.phrase} ei ole saavuttanut {minQueryLength} merkin vähimmäismäärää.',
+        noresults: 'Hakusi ei palauttanut tuloksia.',
+        pagePicker: 'Näytä {pageSize} sivua kohti',
+        showAll: 'kaikki'
+    },
+    SearchBar: {
+        placeholder: 'Hae...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/fr_FR.js b/packages/extensions/venia-pwa-live-search/src/i18n/fr_FR.js
new file mode 100644
index 0000000000..a244418ed4
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/fr_FR.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const fr_FR = {
+    Filter: {
+        title: 'Filtres',
+        showTitle: 'Afficher les filtres',
+        hideTitle: 'Masquer les filtres',
+        clearAll: 'Tout effacer'
+    },
+    InputButtonGroup: {
+        title: 'Catégories',
+        price: 'Prix',
+        customPrice: 'Prix personnalisé',
+        priceIncluded: 'oui',
+        priceExcluded: 'non',
+        priceExcludedMessage: 'Exclure {title}',
+        priceRange: ' et plus',
+        showmore: 'Plus'
+    },
+    Loading: {
+        title: 'Chargement'
+    },
+    NoResults: {
+        heading: 'Votre recherche n’a renvoyé aucun résultat',
+        subheading: 'Veuillez réessayer…'
+    },
+    SortDropdown: {
+        title: 'Trier par',
+        option: 'Trier par : {selectedOption}',
+        relevanceLabel: 'Pertinence',
+        positionLabel: 'Position'
+    },
+    CategoryFilters: {
+        results: 'résultats trouvés pour {phrase}',
+        products: '{totalCount} produits'
+    },
+    ProductCard: {
+        asLowAs: 'Prix descendant jusqu’à {discountPrice}',
+        startingAt: 'À partir de {productPrice}',
+        bundlePrice: 'De {fromBundlePrice} à {toBundlePrice}',
+        from: 'De {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Votre terme de recherche « {variables.phrase} » est en dessous de la limite minimale de {minQueryLength} caractères.',
+        noresults: 'Votre recherche n’a renvoyé aucun résultat.',
+        pagePicker: 'Affichage : {pageSize} par page',
+        showAll: 'tout'
+    },
+    SearchBar: {
+        placeholder: 'Rechercher…'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/gl_ES.js b/packages/extensions/venia-pwa-live-search/src/i18n/gl_ES.js
new file mode 100644
index 0000000000..40e9b9376f
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/gl_ES.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const gl_ES = {
+    Filter: {
+        title: 'Filtros',
+        showTitle: 'Mostrar filtros',
+        hideTitle: 'Ocultar filtros',
+        clearAll: 'Borrar todo'
+    },
+    InputButtonGroup: {
+        title: 'Categorías',
+        price: 'Prezo',
+        customPrice: 'Prezo personalizado',
+        priceIncluded: 'si',
+        priceExcluded: 'non',
+        priceExcludedMessage: 'Non {title}',
+        priceRange: ' e superior',
+        showmore: 'Mostrar máis'
+    },
+    Loading: {
+        title: 'Cargando'
+    },
+    NoResults: {
+        heading: 'Non hai resultados para a súa busca.',
+        subheading: 'Ténteo de novo...'
+    },
+    SortDropdown: {
+        title: 'Ordenar por',
+        option: 'Ordenar por: {selectedOption}',
+        relevanceLabel: 'Máis relevante',
+        positionLabel: 'Posición'
+    },
+    CategoryFilters: {
+        results: 'resultados para {phrase}',
+        products: '{totalCount} produtos'
+    },
+    ProductCard: {
+        asLowAs: 'A partir de só {discountPrice}',
+        startingAt: 'A partir de {productPrice}',
+        bundlePrice: 'Desde {fromBundlePrice} ata {toBundlePrice}',
+        from: 'Desde {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'O seu termo de busca {variables.phrase} non alcanzou o mínimo de {minQueryLength} caracteres.',
+        noresults: 'A súa busca non obtivo resultados.',
+        pagePicker: 'Mostrar {pageSize} por páxina',
+        showAll: 'todos'
+    },
+    SearchBar: {
+        placeholder: 'Buscar...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/hi_IN.js b/packages/extensions/venia-pwa-live-search/src/i18n/hi_IN.js
new file mode 100644
index 0000000000..f1f1187227
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/hi_IN.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const hi_IN = {
+    Filter: {
+        title: 'फिल्टर',
+        showTitle: 'फ़िल्टर दिखाएं',
+        hideTitle: 'फ़िल्टर छुपाएं',
+        clearAll: 'सभी साफ करें'
+    },
+    InputButtonGroup: {
+        title: 'श्रेणियाँ',
+        price: 'कीमत',
+        customPrice: 'कस्टम कीमत',
+        priceIncluded: 'हां',
+        priceExcluded: 'नहीं',
+        priceExcludedMessage: 'नहीं {title}',
+        priceRange: ' और ऊपर',
+        showmore: 'और दिखाएं'
+    },
+    Loading: {
+        title: 'लोड हो रहा है'
+    },
+    NoResults: {
+        heading: 'आपकी खोज के लिए कोई परिणाम नहीं.',
+        subheading: 'कृपया फिर कोशिश करें...'
+    },
+    SortDropdown: {
+        title: 'इसके अनुसार क्रमबद्ध करें',
+        option: 'इसके अनुसार क्रमबद्ध करें: {selectedOption}',
+        relevanceLabel: 'सबसे अधिक प्रासंगिक',
+        positionLabel: 'पद'
+    },
+    CategoryFilters: {
+        results: '{phrase} के लिए परिणाम',
+        products: '{totalCount} प्रोडक्ट्स'
+    },
+    ProductCard: {
+        asLowAs: '{discountPrice} जितना कम ',
+        startingAt: '{productPrice} से शुरू',
+        bundlePrice: '{fromBundlePrice} से {toBundlePrice} तक',
+        from: '{productPrice} से '
+    },
+    ProductContainers: {
+        minquery:
+            'आपका खोज शब्द {variables.phrase} न्यूनतम {minQueryLength} वर्ण तक नहीं पहुंच पाया है।',
+        noresults: 'आपकी खोज का कोई परिणाम नहीं निकला।',
+        pagePicker: 'प्रति पृष्ठ {pageSize}दिखाओ',
+        showAll: 'सब'
+    },
+    SearchBar: {
+        placeholder: 'खोज...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/hu_HU.js b/packages/extensions/venia-pwa-live-search/src/i18n/hu_HU.js
new file mode 100644
index 0000000000..ab21250535
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/hu_HU.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const hu_HU = {
+    Filter: {
+        title: 'Szűrők',
+        showTitle: 'Szűrők megjelenítése',
+        hideTitle: 'Szűrők elrejtése',
+        clearAll: 'Összes törlése'
+    },
+    InputButtonGroup: {
+        title: 'Kategóriák',
+        price: 'Ár',
+        customPrice: 'Egyedi ár',
+        priceIncluded: 'igen',
+        priceExcluded: 'nem',
+        priceExcludedMessage: 'Nem {title}',
+        priceRange: ' és fölötte',
+        showmore: 'További információk megjelenítése'
+    },
+    Loading: {
+        title: 'Betöltés'
+    },
+    NoResults: {
+        heading: 'Nincs találat a keresésre.',
+        subheading: 'Kérjük, próbálja meg újra...'
+    },
+    SortDropdown: {
+        title: 'Rendezési szempont',
+        option: 'Rendezési szempont: {selectedOption}',
+        relevanceLabel: 'Legrelevánsabb',
+        positionLabel: 'Pozíció'
+    },
+    CategoryFilters: {
+        results: 'eredmények a következőre: {phrase}',
+        products: '{totalCount} termék'
+    },
+    ProductCard: {
+        asLowAs: 'Ennyire alacsony: {discountPrice}',
+        startingAt: 'Kezdő ár: {productPrice}',
+        bundlePrice: 'Ettől: {fromBundlePrice} Eddig: {toBundlePrice}',
+        from: 'Ettől: {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'A keresett kifejezés: {variables.phrase} nem érte el a minimum {minQueryLength} karaktert.',
+        noresults: 'A keresés nem hozott eredményt.',
+        pagePicker: '{pageSize} megjelenítése oldalanként',
+        showAll: 'összes'
+    },
+    SearchBar: {
+        placeholder: 'Keresés...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/hy_AM.js b/packages/extensions/venia-pwa-live-search/src/i18n/hy_AM.js
new file mode 100644
index 0000000000..b3b2b80a3c
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/hy_AM.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const hy_AM = {
+    Filter: {
+        title: 'Ֆիլտրեր',
+        showTitle: 'Ցույց տալ ֆիլտրերը',
+        hideTitle: 'Թաքցնել ֆիլտրերը',
+        clearAll: 'Մաքրել բոլորը'
+    },
+    InputButtonGroup: {
+        title: 'Կատեգորիաներ',
+        price: 'Գինը',
+        customPrice: 'Սովորական գինը',
+        priceIncluded: 'այո',
+        priceExcluded: 'ոչ',
+        priceExcludedMessage: 'Ոչ {title}',
+        priceRange: ' և վերևում',
+        showmore: 'Ցույց տալ ավելին'
+    },
+    Loading: {
+        title: 'Բեռնվում է'
+    },
+    NoResults: {
+        heading: 'Ձեր որոնման համար արդյունքներ չկան:',
+        subheading: 'Խնդրում եմ փորձել կրկին...'
+    },
+    SortDropdown: {
+        title: 'Դասավորել ըստ',
+        option: 'Դասավորել ըստ՝ {selectedOption}',
+        relevanceLabel: 'Ամենակարևորը',
+        positionLabel: 'Դիրք'
+    },
+    CategoryFilters: {
+        results: 'արդյունքներ {phrase}-ի համար',
+        products: '{totalCount} ապրանքներ'
+    },
+    ProductCard: {
+        asLowAs: '{discountPrice}-ի չափ ցածր',
+        startingAt: 'Սկսած {productPrice}-ից',
+        bundlePrice: '{fromBundlePrice}-ից մինչև {toBundlePrice}',
+        from: '{productPrice}-ից'
+    },
+    ProductContainers: {
+        minquery:
+            'Ձեր որոնման բառը {variables.phrase} չի հասել նվազագույն {minQueryLength} նիշերի:',
+        noresults: 'Ձեր որոնումը արդյունք չտվեց:',
+        pagePicker: 'Ցույց տալ {pageSize} յուրաքանչյուր էջի համար',
+        showAll: 'բոլորը'
+    },
+    SearchBar: {
+        placeholder: 'Որոնել...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/id_ID.js b/packages/extensions/venia-pwa-live-search/src/i18n/id_ID.js
new file mode 100644
index 0000000000..822828c035
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/id_ID.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const id_ID = {
+    Filter: {
+        title: 'Filter',
+        showTitle: 'Tampilkan filter',
+        hideTitle: 'Sembunyikan filter',
+        clearAll: 'Bersihkan semua'
+    },
+    InputButtonGroup: {
+        title: 'Kategori',
+        price: 'Harga',
+        customPrice: 'Harga Kustom',
+        priceIncluded: 'ya',
+        priceExcluded: 'tidak',
+        priceExcludedMessage: 'Bukan {title}',
+        priceRange: ' ke atas',
+        showmore: 'Tampilkan lainnya'
+    },
+    Loading: {
+        title: 'Memuat'
+    },
+    NoResults: {
+        heading: 'Tidak ada hasil untuk pencarian Anda.',
+        subheading: 'Coba lagi...'
+    },
+    SortDropdown: {
+        title: 'Urut berdasarkan',
+        option: 'Urut berdasarkan: {selectedOption}',
+        relevanceLabel: 'Paling Relevan',
+        positionLabel: 'Posisi'
+    },
+    CategoryFilters: {
+        results: 'hasil untuk {phrase}',
+        products: '{totalCount} produk'
+    },
+    ProductCard: {
+        asLowAs: 'Paling rendah {discountPrice}',
+        startingAt: 'Mulai dari {productPrice}',
+        bundlePrice: 'Mulai {fromBundlePrice} hingga {toBundlePrice}',
+        from: 'Mulai {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Istilah pencarian {variables.phrase} belum mencapai batas minimum {minQueryLength} karakter.',
+        noresults: 'Pencarian Anda tidak memberikan hasil.',
+        pagePicker: 'Menampilkan {pageSize} per halaman',
+        showAll: 'semua'
+    },
+    SearchBar: {
+        placeholder: 'Cari...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/index.js b/packages/extensions/venia-pwa-live-search/src/i18n/index.js
new file mode 100644
index 0000000000..96729d2130
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/index.js
@@ -0,0 +1,89 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+import { ar_AE } from './ar_AE';
+import { bg_BG } from './bg_BG';
+import { bn_IN } from './bn_IN';
+import { ca_ES } from './ca_ES';
+import { cs_CZ } from './cs_CZ';
+import { da_DK } from './da_DK';
+import { de_DE } from './de_DE';
+import { el_GR } from './el_GR';
+import { en_GA } from './en_GA';
+import { en_GB } from './en_GB';
+import { en_US } from './en_US';
+import { es_ES } from './es_ES';
+import { et_EE } from './et_EE';
+import { eu_ES } from './eu_ES';
+import { fa_IR } from './fa_IR';
+import { fi_FI } from './fi_FI';
+import { fr_FR } from './fr_FR';
+import { gl_ES } from './gl_ES';
+import { hi_IN } from './hi_IN';
+import { hu_HU } from './hu_HU';
+import { hy_AM } from './hy_AM';
+import { id_ID } from './id_ID';
+import { it_IT } from './it_IT';
+import { ja_JP } from './ja_JP';
+import { ko_KR } from './ko_KR';
+import { lt_LT } from './lt_LT';
+import { lv_LV } from './lv_LV';
+import { nb_NO } from './nb_NO';
+import { nl_NL } from './nl_NL';
+import { pt_BR } from './pt_BR';
+import { pt_PT } from './pt_PT';
+import { ro_RO } from './ro_RO';
+import { ru_RU } from './ru_RU';
+import { Sorani } from './Sorani';
+import { sv_SE } from './sv_SE';
+import { th_TH } from './th_TH';
+import { tr_TR } from './tr_TR';
+import { zh_Hans_CN } from './zh_Hans_CN';
+import { zh_Hant_TW } from './zh_Hant_TW';
+export {
+    ar_AE,
+    bg_BG,
+    bn_IN,
+    ca_ES,
+    cs_CZ,
+    da_DK,
+    de_DE,
+    el_GR,
+    en_GA,
+    en_GB,
+    en_US,
+    es_ES,
+    et_EE,
+    eu_ES,
+    fa_IR,
+    fi_FI,
+    fr_FR,
+    gl_ES,
+    hi_IN,
+    hu_HU,
+    hy_AM,
+    id_ID,
+    it_IT,
+    ja_JP,
+    ko_KR,
+    lt_LT,
+    lv_LV,
+    nb_NO,
+    nl_NL,
+    pt_BR,
+    pt_PT,
+    ro_RO,
+    ru_RU,
+    Sorani,
+    sv_SE,
+    th_TH,
+    tr_TR,
+    zh_Hans_CN,
+    zh_Hant_TW
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/it_IT.js b/packages/extensions/venia-pwa-live-search/src/i18n/it_IT.js
new file mode 100644
index 0000000000..2da94033b9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/it_IT.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const it_IT = {
+    Filter: {
+        title: 'Filtri',
+        showTitle: 'Mostra filtri',
+        hideTitle: 'Nascondi filtri',
+        clearAll: 'Cancella tutto'
+    },
+    InputButtonGroup: {
+        title: 'Categorie',
+        price: 'Prezzo',
+        customPrice: 'Prezzo personalizzato',
+        priceIncluded: 'sì',
+        priceExcluded: 'no',
+        priceExcludedMessage: 'Non {title}',
+        priceRange: ' e superiore',
+        showmore: 'Mostra altro'
+    },
+    Loading: {
+        title: 'Caricamento'
+    },
+    NoResults: {
+        heading: 'Nessun risultato per la ricerca.',
+        subheading: 'Riprova...'
+    },
+    SortDropdown: {
+        title: 'Ordina per',
+        option: 'Ordina per: {selectedOption}',
+        relevanceLabel: 'Più rilevante',
+        positionLabel: 'Posizione'
+    },
+    CategoryFilters: {
+        results: 'risultati per {phrase}',
+        products: '{totalCount} prodotti'
+    },
+    ProductCard: {
+        asLowAs: 'A partire da {discountPrice}',
+        startingAt: 'A partire da {productPrice}',
+        bundlePrice: 'Da {fromBundlePrice} a {toBundlePrice}',
+        from: 'Da {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Il termine di ricerca {variables.phrase} non ha raggiunto il minimo di {minQueryLength} caratteri.',
+        noresults: 'La ricerca non ha prodotto risultati.',
+        pagePicker: 'Mostra {pageSize} per pagina',
+        showAll: 'tutto'
+    },
+    SearchBar: {
+        placeholder: 'Cerca...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/ja_JP.js b/packages/extensions/venia-pwa-live-search/src/i18n/ja_JP.js
new file mode 100644
index 0000000000..ad81a17405
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/ja_JP.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const ja_JP = {
+    Filter: {
+        title: 'フィルター',
+        showTitle: 'フィルターを表示',
+        hideTitle: 'フィルターを隠す',
+        clearAll: 'すべて消去'
+    },
+    InputButtonGroup: {
+        title: 'カテゴリ',
+        price: '価格',
+        customPrice: 'カスタム価格',
+        priceIncluded: 'はい',
+        priceExcluded: 'いいえ',
+        priceExcludedMessage: '{title}ではない',
+        priceRange: ' 以上',
+        showmore: 'すべてを表示'
+    },
+    Loading: {
+        title: '読み込み中'
+    },
+    NoResults: {
+        heading: '検索結果はありません。',
+        subheading: '再試行してください'
+    },
+    SortDropdown: {
+        title: '並べ替え条件',
+        option: '{selectedOption}に並べ替え',
+        relevanceLabel: '最も関連性が高い',
+        positionLabel: '配置'
+    },
+    CategoryFilters: {
+        results: '{phrase}の検索結果',
+        products: '{totalCount}製品'
+    },
+    ProductCard: {
+        asLowAs: '割引料金 : {discountPrice}',
+        startingAt: '初年度価格 : {productPrice}',
+        bundlePrice: '{fromBundlePrice} から {toBundlePrice}',
+        from: '{productPrice} から'
+    },
+    ProductContainers: {
+        minquery:
+            'ご入力の検索語{variables.phrase}は、最低文字数 {minQueryLength} 文字に達していません。',
+        noresults: '検索結果はありませんでした。',
+        pagePicker: '1 ページあたり {pageSize} を表示',
+        showAll: 'すべて'
+    },
+    SearchBar: {
+        placeholder: '検索'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/ko_KR.js b/packages/extensions/venia-pwa-live-search/src/i18n/ko_KR.js
new file mode 100644
index 0000000000..14e7fc805e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/ko_KR.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const ko_KR = {
+    Filter: {
+        title: '필터',
+        showTitle: '필터 표시',
+        hideTitle: '필터 숨기기',
+        clearAll: '모두 지우기'
+    },
+    InputButtonGroup: {
+        title: '범주',
+        price: '가격',
+        customPrice: '맞춤 가격',
+        priceIncluded: '예',
+        priceExcluded: '아니요',
+        priceExcludedMessage: '{title} 아님',
+        priceRange: ' 이상',
+        showmore: '자세히 표시'
+    },
+    Loading: {
+        title: '로드 중'
+    },
+    NoResults: {
+        heading: '현재 검색에 대한 결과가 없습니다.',
+        subheading: '다시 시도해 주십시오.'
+    },
+    SortDropdown: {
+        title: '정렬 기준',
+        option: '정렬 기준: {selectedOption}',
+        relevanceLabel: '관련성 가장 높음',
+        positionLabel: '위치'
+    },
+    CategoryFilters: {
+        results: '{phrase}에 대한 검색 결과',
+        products: '{totalCount}개 제품'
+    },
+    ProductCard: {
+        asLowAs: '최저 {discountPrice}',
+        startingAt: '최저가: {productPrice}',
+        bundlePrice: '{fromBundlePrice} ~ {toBundlePrice}',
+        from: '{productPrice}부터'
+    },
+    ProductContainers: {
+        minquery:
+            '검색어 “{variables.phrase}”이(가) 최소 문자 길이인 {minQueryLength}자 미만입니다.',
+        noresults: '검색 결과가 없습니다.',
+        pagePicker: '페이지당 {pageSize}개 표시',
+        showAll: '모두'
+    },
+    SearchBar: {
+        placeholder: '검색...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/lt_LT.js b/packages/extensions/venia-pwa-live-search/src/i18n/lt_LT.js
new file mode 100644
index 0000000000..f9e6c4b372
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/lt_LT.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const lt_LT = {
+    Filter: {
+        title: 'Filtrai',
+        showTitle: 'Rodyti filtrus',
+        hideTitle: 'Slėpti filtrus',
+        clearAll: 'Išvalyti viską'
+    },
+    InputButtonGroup: {
+        title: 'Kategorijos',
+        price: 'Kaina',
+        customPrice: 'Individualizuota kaina',
+        priceIncluded: 'taip',
+        priceExcluded: 'ne',
+        priceExcludedMessage: 'Ne {title}',
+        priceRange: ' ir aukščiau',
+        showmore: 'Rodyti daugiau'
+    },
+    Loading: {
+        title: 'Įkeliama'
+    },
+    NoResults: {
+        heading: 'Nėra jūsų ieškos rezultatų.',
+        subheading: 'Bandykite dar kartą...'
+    },
+    SortDropdown: {
+        title: 'Rikiuoti pagal',
+        option: 'Rikiuoti pagal: {selectedOption}',
+        relevanceLabel: 'Svarbiausias',
+        positionLabel: 'Padėtis'
+    },
+    CategoryFilters: {
+        results: 'rezultatai {phrase}',
+        products: 'Produktų: {totalCount}'
+    },
+    ProductCard: {
+        asLowAs: 'Žema kaip {discountPrice}',
+        startingAt: 'Pradedant nuo {productPrice}',
+        bundlePrice: 'Nuo {fromBundlePrice} iki {toBundlePrice}',
+        from: 'Nuo {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Jūsų ieškos sąlyga {variables.phrase} nesiekia minimalaus skaičiaus simbolių: {minQueryLength}.',
+        noresults: 'Jūsų ieška nedavė jokių rezultatų.',
+        pagePicker: 'Rodyti {pageSize} psl.',
+        showAll: 'viskas'
+    },
+    SearchBar: {
+        placeholder: 'Ieška...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/lv_LV.js b/packages/extensions/venia-pwa-live-search/src/i18n/lv_LV.js
new file mode 100644
index 0000000000..ceb6edb06e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/lv_LV.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const lv_LV = {
+    Filter: {
+        title: 'Filtri',
+        showTitle: 'Rādīt filtrus',
+        hideTitle: 'Slēpt filtrus',
+        clearAll: 'Notīrīt visus'
+    },
+    InputButtonGroup: {
+        title: 'Kategorijas',
+        price: 'Cena',
+        customPrice: 'Pielāgot cenu',
+        priceIncluded: 'jā',
+        priceExcluded: 'nē',
+        priceExcludedMessage: 'Nav {title}',
+        priceRange: ' un augstāk',
+        showmore: 'Rādīt vairāk'
+    },
+    Loading: {
+        title: 'Notiek ielāde'
+    },
+    NoResults: {
+        heading: 'Jūsu meklēšanai nav rezultātu.',
+        subheading: 'Mēģiniet vēlreiz…'
+    },
+    SortDropdown: {
+        title: 'Kārtot pēc',
+        option: 'Kārtot pēc: {selectedOption}',
+        relevanceLabel: 'Visatbilstošākais',
+        positionLabel: 'Pozīcija'
+    },
+    CategoryFilters: {
+        results: '{phrase} rezultāti',
+        products: '{totalCount} produkti'
+    },
+    ProductCard: {
+        asLowAs: 'Tik zemu kā {discountPrice}',
+        startingAt: 'Sākot no {productPrice}',
+        bundlePrice: 'No {fromBundlePrice} uz{toBundlePrice}',
+        from: 'No {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Jūsu meklēšanas vienums {variables.phrase} nav sasniedzis minimumu {minQueryLength} rakstzīmes.',
+        noresults: 'Jūsu meklēšana nedeva nekādus rezultātus.',
+        pagePicker: 'Rādīt {pageSize} vienā lapā',
+        showAll: 'viss'
+    },
+    SearchBar: {
+        placeholder: 'Meklēt…'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/nb_NO.js b/packages/extensions/venia-pwa-live-search/src/i18n/nb_NO.js
new file mode 100644
index 0000000000..8c45479296
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/nb_NO.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const nb_NO = {
+    Filter: {
+        title: 'Filtre',
+        showTitle: 'Vis filtre',
+        hideTitle: 'Skjul filtre',
+        clearAll: 'Fjern alle'
+    },
+    InputButtonGroup: {
+        title: 'Kategorier',
+        price: 'Pris',
+        customPrice: 'Egendefinert pris',
+        priceIncluded: 'ja',
+        priceExcluded: 'nei',
+        priceExcludedMessage: 'Ikke {title}',
+        priceRange: ' og over',
+        showmore: 'Vis mer'
+    },
+    Loading: {
+        title: 'Laster inn'
+    },
+    NoResults: {
+        heading: 'Finner ingen resultater for søket.',
+        subheading: 'Prøv igjen.'
+    },
+    SortDropdown: {
+        title: 'Sorter etter',
+        option: 'Sorter etter: {selectedOption}',
+        relevanceLabel: 'Mest aktuelle',
+        positionLabel: 'Plassering'
+    },
+    CategoryFilters: {
+        results: 'resultater for {phrase}',
+        products: '{totalCount} produkter'
+    },
+    ProductCard: {
+        asLowAs: 'Så lavt som {discountPrice}',
+        startingAt: 'Fra {productPrice}',
+        bundlePrice: 'Fra {fromBundlePrice} til {toBundlePrice}',
+        from: 'Fra {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Søkeordet {variables.phrase} har ikke de påkrevde {minQueryLength} tegnene.',
+        noresults: 'Søket ditt ga ingen resultater.',
+        pagePicker: 'Vis {pageSize} per side',
+        showAll: 'alle'
+    },
+    SearchBar: {
+        placeholder: 'Søk …'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/nl_NL.js b/packages/extensions/venia-pwa-live-search/src/i18n/nl_NL.js
new file mode 100644
index 0000000000..52142710bc
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/nl_NL.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const nl_NL = {
+    Filter: {
+        title: 'Filters',
+        showTitle: 'Filters weergeven',
+        hideTitle: 'Filters verbergen',
+        clearAll: 'Alles wissen'
+    },
+    InputButtonGroup: {
+        title: 'Categorieën',
+        price: 'Prijs',
+        customPrice: 'Aangepaste prijs',
+        priceIncluded: 'ja',
+        priceExcluded: 'nee',
+        priceExcludedMessage: 'Niet {title}',
+        priceRange: ' en meer',
+        showmore: 'Meer tonen'
+    },
+    Loading: {
+        title: 'Laden'
+    },
+    NoResults: {
+        heading: 'Geen resultaten voor je zoekopdracht.',
+        subheading: 'Probeer het opnieuw...'
+    },
+    SortDropdown: {
+        title: 'Sorteren op',
+        option: 'Sorteren op: {selectedOption}',
+        relevanceLabel: 'Meest relevant',
+        positionLabel: 'Positie'
+    },
+    CategoryFilters: {
+        results: 'resultaten voor {phrase}',
+        products: '{totalCount} producten'
+    },
+    ProductCard: {
+        asLowAs: 'Slechts {discountPrice}',
+        startingAt: 'Vanaf {productPrice}',
+        bundlePrice: 'Van {fromBundlePrice} tot {toBundlePrice}',
+        from: 'Vanaf {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Je zoekterm {variables.phrase} bevat niet het minimumaantal van {minQueryLength} tekens.',
+        noresults: 'Geen resultaten gevonden voor je zoekopdracht.',
+        pagePicker: '{pageSize} weergeven per pagina',
+        showAll: 'alles'
+    },
+    SearchBar: {
+        placeholder: 'Zoeken...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/pt_BR.js b/packages/extensions/venia-pwa-live-search/src/i18n/pt_BR.js
new file mode 100644
index 0000000000..ec3c9f2f71
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/pt_BR.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const pt_BR = {
+    Filter: {
+        title: 'Filtros',
+        showTitle: 'Mostrar filtros',
+        hideTitle: 'Ocultar filtros',
+        clearAll: 'Limpar tudo'
+    },
+    InputButtonGroup: {
+        title: 'Categorias',
+        price: 'Preço',
+        customPrice: 'Preço personalizado',
+        priceIncluded: 'sim',
+        priceExcluded: 'não',
+        priceExcludedMessage: 'Não {title}',
+        priceRange: ' e acima',
+        showmore: 'Mostrar mais'
+    },
+    Loading: {
+        title: 'Carregando'
+    },
+    NoResults: {
+        heading: 'Nenhum resultado para sua busca.',
+        subheading: 'Tente novamente...'
+    },
+    SortDropdown: {
+        title: 'Classificar por',
+        option: 'Classificar por: {selectedOption}',
+        relevanceLabel: 'Mais relevantes',
+        positionLabel: 'Posição'
+    },
+    CategoryFilters: {
+        results: 'resultados para {phrase}',
+        products: '{totalCount} produtos'
+    },
+    ProductCard: {
+        asLowAs: 'Por apenas {discountPrice}',
+        startingAt: 'A partir de {productPrice}',
+        bundlePrice: 'De {fromBundlePrice} por {toBundlePrice}',
+        from: 'De {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Seu termo de pesquisa {variables.phrase} não atingiu o mínimo de {minQueryLength} caracteres.',
+        noresults: 'Sua busca não retornou resultados.',
+        pagePicker: 'Mostrar {pageSize} por página',
+        showAll: 'tudo'
+    },
+    SearchBar: {
+        placeholder: 'Pesquisar...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/pt_PT.js b/packages/extensions/venia-pwa-live-search/src/i18n/pt_PT.js
new file mode 100644
index 0000000000..1fbef7cf8d
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/pt_PT.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const pt_PT = {
+    Filter: {
+        title: 'Filtros',
+        showTitle: 'Mostrar filtros',
+        hideTitle: 'Ocultar filtros',
+        clearAll: 'Limpar tudo'
+    },
+    InputButtonGroup: {
+        title: 'Categorias',
+        price: 'Preço',
+        customPrice: 'Preço Personalizado',
+        priceIncluded: 'sim',
+        priceExcluded: 'não',
+        priceExcludedMessage: 'Não {title}',
+        priceRange: ' e acima',
+        showmore: 'Mostrar mais'
+    },
+    Loading: {
+        title: 'A carregar'
+    },
+    NoResults: {
+        heading: 'Não existem resultados para a sua pesquisa.',
+        subheading: 'Tente novamente...'
+    },
+    SortDropdown: {
+        title: 'Ordenar por',
+        option: 'Ordenar por: {selectedOption}',
+        relevanceLabel: 'Mais Relevantes',
+        positionLabel: 'Posição'
+    },
+    CategoryFilters: {
+        results: 'resultados para {phrase}',
+        products: '{totalCount} produtos'
+    },
+    ProductCard: {
+        asLowAs: 'A partir de {discountPrice}',
+        startingAt: 'A partir de {productPrice}',
+        bundlePrice: 'De {fromBundlePrice} a {toBundlePrice}',
+        from: 'A partir de {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'O seu termo de pesquisa {variables.phrase} não atingiu o mínimo de {minQueryLength} carateres.',
+        noresults: 'A sua pesquisa não devolveu resultados.',
+        pagePicker: 'Mostrar {pageSize} por página',
+        showAll: 'tudo'
+    },
+    SearchBar: {
+        placeholder: 'Procurar...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/ro_RO.js b/packages/extensions/venia-pwa-live-search/src/i18n/ro_RO.js
new file mode 100644
index 0000000000..5be5a707fc
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/ro_RO.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const ro_RO = {
+    Filter: {
+        title: 'Filtre',
+        showTitle: 'Afișați filtrele',
+        hideTitle: 'Ascundeți filtrele',
+        clearAll: 'Ștergeți tot'
+    },
+    InputButtonGroup: {
+        title: 'Categorii',
+        price: 'Preț',
+        customPrice: 'Preț personalizat',
+        priceIncluded: 'da',
+        priceExcluded: 'nu',
+        priceExcludedMessage: 'Fără {title}',
+        priceRange: ' și mai mult',
+        showmore: 'Afișați mai multe'
+    },
+    Loading: {
+        title: 'Se încarcă'
+    },
+    NoResults: {
+        heading: 'Niciun rezultat pentru căutarea dvs.',
+        subheading: 'Încercați din nou...'
+    },
+    SortDropdown: {
+        title: 'Sortați după',
+        option: 'Sortați după: {selectedOption}',
+        relevanceLabel: 'Cele mai relevante',
+        positionLabel: 'Poziție'
+    },
+    CategoryFilters: {
+        results: 'rezultate pentru {phrase}',
+        products: '{totalCount} produse'
+    },
+    ProductCard: {
+        asLowAs: 'Preț redus până la {discountPrice}',
+        startingAt: 'Începând de la {productPrice}',
+        bundlePrice: 'De la {fromBundlePrice} la {toBundlePrice}',
+        from: 'De la {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Termenul căutat {variables.phrase} nu a atins numărul minim de {minQueryLength} caractere.',
+        noresults: 'Nu există rezultate pentru căutarea dvs.',
+        pagePicker: 'Afișați {pageSize} per pagină',
+        showAll: 'toate'
+    },
+    SearchBar: {
+        placeholder: 'Căutare...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/ru_RU.js b/packages/extensions/venia-pwa-live-search/src/i18n/ru_RU.js
new file mode 100644
index 0000000000..1abea70930
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/ru_RU.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const ru_RU = {
+    Filter: {
+        title: 'Фильтры',
+        showTitle: 'Показать фильтры',
+        hideTitle: 'Скрыть фильтры',
+        clearAll: 'Очистить все'
+    },
+    InputButtonGroup: {
+        title: 'Категории',
+        price: 'Цена',
+        customPrice: 'Индивидуальная цена',
+        priceIncluded: 'да',
+        priceExcluded: 'нет',
+        priceExcludedMessage: 'Нет {title}',
+        priceRange: ' и выше',
+        showmore: 'Показать еще'
+    },
+    Loading: {
+        title: 'Загрузка'
+    },
+    NoResults: {
+        heading: 'Нет результатов по вашему поисковому запросу.',
+        subheading: 'Повторите попытку...'
+    },
+    SortDropdown: {
+        title: 'Сортировка по',
+        option: 'Сортировать по: {selectedOption}',
+        relevanceLabel: 'Самые подходящие',
+        positionLabel: 'Положение'
+    },
+    CategoryFilters: {
+        results: 'Результаты по запросу «{phrase}»',
+        products: 'Продукты: {totalCount}'
+    },
+    ProductCard: {
+        asLowAs: 'Всего за {discountPrice}',
+        startingAt: 'От {productPrice}',
+        bundlePrice: 'От {fromBundlePrice} до {toBundlePrice}',
+        from: 'От {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Поисковый запрос «{variables.phrase}» содержит меньше {minQueryLength} символов.',
+        noresults: 'Нет результатов по вашему запросу.',
+        pagePicker: 'Показывать {pageSize} на странице',
+        showAll: 'все'
+    },
+    SearchBar: {
+        placeholder: 'Поиск...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/sv_SE.js b/packages/extensions/venia-pwa-live-search/src/i18n/sv_SE.js
new file mode 100644
index 0000000000..9f3bf9a545
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/sv_SE.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const sv_SE = {
+    Filter: {
+        title: 'Filter',
+        showTitle: 'Visa filter',
+        hideTitle: 'Dölj filter',
+        clearAll: 'Rensa allt'
+    },
+    InputButtonGroup: {
+        title: 'Kategorier',
+        price: 'Pris',
+        customPrice: 'Anpassat pris',
+        priceIncluded: 'ja',
+        priceExcluded: 'nej',
+        priceExcludedMessage: 'Inte {title}',
+        priceRange: ' eller mer',
+        showmore: 'Visa mer'
+    },
+    Loading: {
+        title: 'Läser in'
+    },
+    NoResults: {
+        heading: 'Inga sökresultat.',
+        subheading: 'Försök igen …'
+    },
+    SortDropdown: {
+        title: 'Sortera på',
+        option: 'Sortera på: {selectedOption}',
+        relevanceLabel: 'Mest relevant',
+        positionLabel: 'Position'
+    },
+    CategoryFilters: {
+        results: 'resultat för {phrase}',
+        products: '{totalCount} produkter'
+    },
+    ProductCard: {
+        asLowAs: 'Så lite som {discountPrice}',
+        startingAt: 'Från {productPrice}',
+        bundlePrice: 'Från {fromBundlePrice} till {toBundlePrice}',
+        from: 'Från {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Din sökterm {variables.phrase} har inte nått upp till minimiantalet tecken, {minQueryLength}.',
+        noresults: 'Sökningen gav inget resultat.',
+        pagePicker: 'Visa {pageSize} per sida',
+        showAll: 'alla'
+    },
+    SearchBar: {
+        placeholder: 'Sök …'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/th_TH.js b/packages/extensions/venia-pwa-live-search/src/i18n/th_TH.js
new file mode 100644
index 0000000000..506b01d45e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/th_TH.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const th_TH = {
+    Filter: {
+        title: 'ตัวกรอง',
+        showTitle: 'แสดงตัวกรอง',
+        hideTitle: 'ซ่อนตัวกรอง',
+        clearAll: 'ล้างทั้งหมด'
+    },
+    InputButtonGroup: {
+        title: 'หมวดหมู่',
+        price: 'ราคา',
+        customPrice: 'ปรับแต่งราคา',
+        priceIncluded: 'ใช่',
+        priceExcluded: 'ไม่',
+        priceExcludedMessage: 'ไม่ใช่ {title}',
+        priceRange: ' และสูงกว่า',
+        showmore: 'แสดงมากขึ้น'
+    },
+    Loading: {
+        title: 'กำลังโหลด'
+    },
+    NoResults: {
+        heading: 'ไม่มีผลลัพธ์สำหรับการค้นหาของคุณ',
+        subheading: 'โปรดลองอีกครั้ง...'
+    },
+    SortDropdown: {
+        title: 'เรียงตาม',
+        option: 'เรียงตาม: {selectedOption}',
+        relevanceLabel: 'เกี่ยวข้องมากที่สุด',
+        positionLabel: 'ตำแหน่ง'
+    },
+    CategoryFilters: {
+        results: 'ผลลัพธ์สำหรับ {phrase}',
+        products: '{totalCount} ผลิตภัณฑ์'
+    },
+    ProductCard: {
+        asLowAs: 'ต่ำสุดที่ {discountPrice}',
+        startingAt: 'เริ่มต้นที่ {productPrice}',
+        bundlePrice: 'ตั้งแต่ {fromBundlePrice} ถึง {toBundlePrice}',
+        from: 'ตั้งแต่ {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'คำว่า {variables.phrase} ที่คุณใช้ค้นหายังมีจำนวนอักขระไม่ถึงจำนวนขั้นต่ำ {minQueryLength} อักขระ',
+        noresults: 'การค้นหาของคุณไม่มีผลลัพธ์',
+        pagePicker: 'แสดง {pageSize} ต่อหน้า',
+        showAll: 'ทั้งหมด'
+    },
+    SearchBar: {
+        placeholder: 'ค้นหา...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/tr_TR.js b/packages/extensions/venia-pwa-live-search/src/i18n/tr_TR.js
new file mode 100644
index 0000000000..75a6043aea
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/tr_TR.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const tr_TR = {
+    Filter: {
+        title: 'Filtreler',
+        showTitle: 'Filtreleri göster',
+        hideTitle: 'Filtreleri gizle',
+        clearAll: 'Tümünü temizle'
+    },
+    InputButtonGroup: {
+        title: 'Kategoriler',
+        price: 'Fiyat',
+        customPrice: 'Özel Fiyat',
+        priceIncluded: 'evet',
+        priceExcluded: 'hayır',
+        priceExcludedMessage: 'Hariç: {title}',
+        priceRange: ' ve üzeri',
+        showmore: 'Diğerlerini göster'
+    },
+    Loading: {
+        title: 'Yükleniyor'
+    },
+    NoResults: {
+        heading: 'Aramanız hiç sonuç döndürmedi',
+        subheading: 'Lütfen tekrar deneyin...'
+    },
+    SortDropdown: {
+        title: 'Sırala',
+        option: 'Sıralama ölçütü: {selectedOption}',
+        relevanceLabel: 'En Çok İlişkili',
+        positionLabel: 'Konum'
+    },
+    CategoryFilters: {
+        results: '{phrase} için sonuçlar',
+        products: '{totalCount} ürün'
+    },
+    ProductCard: {
+        asLowAs: 'En düşük: {discountPrice}',
+        startingAt: 'Başlangıç fiyatı: {productPrice}',
+        bundlePrice: '{fromBundlePrice} - {toBundlePrice} arası',
+        from: 'Başlangıç: {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            'Arama teriminiz ({variables.phrase}) minimum {minQueryLength} karakter sınırlamasından daha kısa.',
+        noresults: 'Aramanız hiç sonuç döndürmedi.',
+        pagePicker: 'Sayfa başına {pageSize} göster',
+        showAll: 'tümü'
+    },
+    SearchBar: {
+        placeholder: 'Ara...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/zh_Hans_CN.js b/packages/extensions/venia-pwa-live-search/src/i18n/zh_Hans_CN.js
new file mode 100644
index 0000000000..e47d322a23
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/zh_Hans_CN.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const zh_Hans_CN = {
+    Filter: {
+        title: '筛选条件',
+        showTitle: '显示筛选条件',
+        hideTitle: '隐藏筛选条件',
+        clearAll: '全部清除'
+    },
+    InputButtonGroup: {
+        title: '类别',
+        price: '价格',
+        customPrice: '自定义价格',
+        priceIncluded: '是',
+        priceExcluded: '否',
+        priceExcludedMessage: '不是 {title}',
+        priceRange: ' 及以上',
+        showmore: '显示更多'
+    },
+    Loading: {
+        title: '正在加载'
+    },
+    NoResults: {
+        heading: '无搜索结果。',
+        subheading: '请重试...'
+    },
+    SortDropdown: {
+        title: '排序依据',
+        option: '排序依据:{selectedOption}',
+        relevanceLabel: '最相关',
+        positionLabel: '位置'
+    },
+    CategoryFilters: {
+        results: '{phrase} 的结果',
+        products: '{totalCount} 个产品'
+    },
+    ProductCard: {
+        asLowAs: '低至 {discountPrice}',
+        startingAt: '起价为 {productPrice}',
+        bundlePrice: '从 {fromBundlePrice} 到 {toBundlePrice}',
+        from: '从 {productPrice} 起'
+    },
+    ProductContainers: {
+        minquery:
+            '您的搜索词 {variables.phrase} 尚未达到最少 {minQueryLength} 个字符这一要求。',
+        noresults: '您的搜索未返回任何结果。',
+        pagePicker: '每页显示 {pageSize} 项',
+        showAll: '全部'
+    },
+    SearchBar: {
+        placeholder: '搜索...'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/i18n/zh_Hant_TW.js b/packages/extensions/venia-pwa-live-search/src/i18n/zh_Hant_TW.js
new file mode 100644
index 0000000000..ae2d40c09a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/i18n/zh_Hant_TW.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+export const zh_Hant_TW = {
+    Filter: {
+        title: '篩選器',
+        showTitle: '顯示篩選器',
+        hideTitle: '隱藏篩選器',
+        clearAll: '全部清除'
+    },
+    InputButtonGroup: {
+        title: '類別',
+        price: '價格',
+        customPrice: '自訂價格',
+        priceIncluded: '是',
+        priceExcluded: '否',
+        priceExcludedMessage: '不是 {title}',
+        priceRange: ' 以上',
+        showmore: '顯示更多'
+    },
+    Loading: {
+        title: '載入中'
+    },
+    NoResults: {
+        heading: '沒有符合搜尋的結果。',
+        subheading: '請再試一次…'
+    },
+    SortDropdown: {
+        title: '排序依據',
+        option: '排序方式:{selectedOption}',
+        relevanceLabel: '最相關',
+        positionLabel: '位置'
+    },
+    CategoryFilters: {
+        results: '{phrase} 的結果',
+        products: '{totalCount} 個產品'
+    },
+    ProductCard: {
+        asLowAs: '低至 {discountPrice}',
+        startingAt: '起價為 {productPrice}',
+        bundlePrice: '從 {fromBundlePrice} 到 {toBundlePrice}',
+        from: '起價為 {productPrice}'
+    },
+    ProductContainers: {
+        minquery:
+            '您的搜尋字詞 {variables.phrase} 未達到最少 {minQueryLength} 個字元。',
+        noresults: '您的搜尋未傳回任何結果。',
+        pagePicker: '顯示每頁 {pageSize}',
+        showAll: '全部'
+    },
+    SearchBar: {
+        placeholder: '搜尋…'
+    }
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/NoImage.svg b/packages/extensions/venia-pwa-live-search/src/icons/NoImage.svg
new file mode 100644
index 0000000000..68bbb41f39
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/NoImage.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 74"><path d="M26,85H70a8.009,8.009,0,0,0,8-8V29.941a7.947,7.947,0,0,0-2.343-5.657L64.716,13.343A7.946,7.946,0,0,0,59.059,11H26a8.009,8.009,0,0,0-8,8V77a8.009,8.009,0,0,0,8,8ZM20,19a6.007,6.007,0,0,1,6-6H59.059A5.96,5.96,0,0,1,63.3,14.757L74.242,25.7A5.96,5.96,0,0,1,76,29.941V77a6.007,6.007,0,0,1-6,6H26a6.007,6.007,0,0,1-6-6Zm6.614,51.06h0L68,69.98a.75.75,0,0,0,.545-1.263L57.67,57.129a1.99,1.99,0,0,0-2.808-.028L51.6,60.467l-.024.026-7.087-7.543a1.73,1.73,0,0,0-1.229-.535,1.765,1.765,0,0,0-1.249.5L26.084,68.778a.75.75,0,0,0,.529,1.281Zm26.061-8.548,3.252-3.354a.333.333,0,0,1,.332-.123.463.463,0,0,1,.324.126L66.27,68.484l-7.177.014-6.5-6.916a.735.735,0,0,0,.078-.071Zm-9.611-7.526a.235.235,0,0,1,.168-.069.212.212,0,0,1,.168.068L57.039,68.5l-28.606.055Zm20.05-.43h.079a5.087,5.087,0,0,0,3.583-1.47,5.146,5.146,0,1,0-7.279-.109,5.089,5.089,0,0,0,3.617,1.579Zm-2.456-7.839a3.6,3.6,0,0,1,2.534-1.042h.056a3.7,3.7,0,0,1,2.478,6.34,3.51,3.51,0,0,1-2.589,1.041,3.6,3.6,0,0,1-2.557-1.118,3.715,3.715,0,0,1,.079-5.221Z" transform="translate(-18 -11)" fill="#8e8e8e"/></svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/adjustments.svg b/packages/extensions/venia-pwa-live-search/src/icons/adjustments.svg
new file mode 100644
index 0000000000..ae69e7d924
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/adjustments.svg
@@ -0,0 +1,3 @@
+<svg className="w-6 h-6 mr-1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="black">
+    <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75"/>
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/cart.svg b/packages/extensions/venia-pwa-live-search/src/icons/cart.svg
new file mode 100644
index 0000000000..91896175f9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/cart.svg
@@ -0,0 +1,3 @@
+<svg width="23" height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M17.9002 18.2899H18.6502V16.7899H17.9002V18.2899ZM6.13016 17.5399L5.38475 17.6228C5.42698 18.0026 5.74801 18.2899 6.13016 18.2899V17.5399ZM4.34016 1.43994L5.08556 1.35707C5.04334 0.977265 4.7223 0.689941 4.34016 0.689941V1.43994ZM1.66016 0.689941H0.910156V2.18994H1.66016V0.689941ZM21.3402 6.80996L22.0856 6.89324C22.1077 6.69506 22.05 6.49622 21.9253 6.34067C21.8005 6.18512 21.6189 6.08566 21.4206 6.06428L21.3402 6.80996ZM20.5402 13.97V14.72C20.9222 14.72 21.2432 14.4329 21.2856 14.0532L20.5402 13.97ZM6.30029 19.0499C6.30029 19.4641 5.96451 19.7999 5.55029 19.7999V21.2999C6.79293 21.2999 7.80029 20.2926 7.80029 19.0499H6.30029ZM5.55029 19.7999C5.13608 19.7999 4.80029 19.4641 4.80029 19.0499H3.30029C3.30029 20.2926 4.30765 21.2999 5.55029 21.2999V19.7999ZM4.80029 19.0499C4.80029 18.6357 5.13608 18.2999 5.55029 18.2999V16.7999C4.30765 16.7999 3.30029 17.8073 3.30029 19.0499H4.80029ZM5.55029 18.2999C5.96451 18.2999 6.30029 18.6357 6.30029 19.0499H7.80029C7.80029 17.8073 6.79293 16.7999 5.55029 16.7999V18.2999ZM19.3003 19.0499C19.3003 19.4641 18.9645 19.7999 18.5503 19.7999V21.2999C19.7929 21.2999 20.8003 20.2926 20.8003 19.0499H19.3003ZM18.5503 19.7999C18.1361 19.7999 17.8003 19.4641 17.8003 19.0499H16.3003C16.3003 20.2926 17.3077 21.2999 18.5503 21.2999V19.7999ZM17.8003 19.0499C17.8003 18.6357 18.1361 18.2999 18.5503 18.2999V16.7999C17.3077 16.7999 16.3003 17.8073 16.3003 19.0499H17.8003ZM18.5503 18.2999C18.9645 18.2999 19.3003 18.6357 19.3003 19.0499H20.8003C20.8003 17.8073 19.7929 16.7999 18.5503 16.7999V18.2999ZM17.9002 16.7899H6.13016V18.2899H17.9002V16.7899ZM6.87556 17.4571L5.08556 1.35707L3.59475 1.52282L5.38475 17.6228L6.87556 17.4571ZM4.34016 0.689941H1.66016V2.18994H4.34016V0.689941ZM4.65983 5.76564L21.2598 7.55564L21.4206 6.06428L4.82064 4.27428L4.65983 5.76564ZM20.5949 6.72668L19.7949 13.8867L21.2856 14.0532L22.0856 6.89324L20.5949 6.72668ZM20.5402 13.22H5.74023V14.72H20.5402V13.22Z" fill="white"/>
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/checkmark.svg b/packages/extensions/venia-pwa-live-search/src/icons/checkmark.svg
new file mode 100644
index 0000000000..e861174a81
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/checkmark.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-circle-fill" viewBox="0 0 16 16">
+  <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/chevron.svg b/packages/extensions/venia-pwa-live-search/src/icons/chevron.svg
new file mode 100644
index 0000000000..098103dad9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/chevron.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8.122 5.121" stroke="currentColor">
+  <path id="chevron" d="M199.75,367.5l3,3,3-3" transform="translate(-198.689 -366.435)" fill="none" />
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/emptyHeart.svg b/packages/extensions/venia-pwa-live-search/src/icons/emptyHeart.svg
new file mode 100644
index 0000000000..dcf75a55b9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/emptyHeart.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
+  <path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" />
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/error.svg b/packages/extensions/venia-pwa-live-search/src/icons/error.svg
new file mode 100644
index 0000000000..f7a7d17bf7
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/error.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-circle-fill" viewBox="0 0 16 16">
+  <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 4a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 4zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/filledHeart.svg b/packages/extensions/venia-pwa-live-search/src/icons/filledHeart.svg
new file mode 100644
index 0000000000..4fdb897d48
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/filledHeart.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
+  <path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" />
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/filter.svg b/packages/extensions/venia-pwa-live-search/src/icons/filter.svg
new file mode 100644
index 0000000000..095325239e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/filter.svg
@@ -0,0 +1,29 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17.5 16">
+  <g id="Group_173236" data-name="Group 173236" transform="translate(-31.25)">
+    <rect id="area" width="16" height="16" transform="translate(32)" fill="none" opacity="0.3" />
+    <g id="filters" transform="translate(32 0.75)">
+      <line id="Line_737" data-name="Line 737" x2="10.07" transform="translate(5.93 7.11)" fill="none" stroke="#4b4b4b"
+        stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_738" data-name="Line 738" x2="2.37" transform="translate(0 7.11)" fill="none" stroke="#4b4b4b"
+        stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_739" data-name="Line 739" x2="2.37" transform="translate(13.63 1.777)" fill="none" stroke="#4b4b4b"
+        stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_740" data-name="Line 740" x2="10.07" transform="translate(0 1.777)" fill="none" stroke="#4b4b4b"
+        stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_741" data-name="Line 741" x2="10.07" transform="translate(0 12.443)" fill="none" stroke="#4b4b4b"
+        stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_742" data-name="Line 742" x2="2.37" transform="translate(13.63 12.443)" fill="none"
+        stroke="#4b4b4b" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <path id="Path_38507" data-name="Path 38507"
+        d="M6.676,2.528A1.778,1.778,0,1,1,4.9.75,1.778,1.778,0,0,1,6.676,2.528Z" transform="translate(6.95 -0.75)"
+        fill="none" stroke="#4b4b4b" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+      <path id="Path_38508" data-name="Path 38508"
+        d="M14.379,7.861A1.778,1.778,0,1,1,12.6,6.084,1.778,1.778,0,0,1,14.379,7.861Z"
+        transform="translate(-8.453 -0.75)" fill="none" stroke="#4b4b4b" stroke-linecap="round" stroke-linejoin="round"
+        stroke-width="1.5" />
+      <path id="Path_38509" data-name="Path 38509"
+        d="M6.676,13.194A1.778,1.778,0,1,1,4.9,11.417,1.778,1.778,0,0,1,6.676,13.194Z" transform="translate(6.95 -0.75)"
+        fill="none" stroke="#4b4b4b" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
+    </g>
+  </g>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/gridView.svg b/packages/extensions/venia-pwa-live-search/src/icons/gridView.svg
new file mode 100644
index 0000000000..9849d50cc3
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/gridView.svg
@@ -0,0 +1,11 @@
+<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.75 1.25H2.25C1.69772 1.25 1.25 1.69772 1.25 2.25V3.75C1.25 4.30228 1.69772 4.75 2.25 4.75H3.75C4.30228 4.75 4.75 4.30228 4.75 3.75V2.25C4.75 1.69772 4.30228 1.25 3.75 1.25Z" fill="#222222"/>
+<path d="M9.75 1.25H8.25C7.69772 1.25 7.25 1.69772 7.25 2.25V3.75C7.25 4.30228 7.69772 4.75 8.25 4.75H9.75C10.3023 4.75 10.75 4.30228 10.75 3.75V2.25C10.75 1.69772 10.3023 1.25 9.75 1.25Z" fill="#222222"/>
+<path d="M15.75 1.25H14.25C13.6977 1.25 13.25 1.69772 13.25 2.25V3.75C13.25 4.30228 13.6977 4.75 14.25 4.75H15.75C16.3023 4.75 16.75 4.30228 16.75 3.75V2.25C16.75 1.69772 16.3023 1.25 15.75 1.25Z" fill="#222222"/>
+<path d="M3.75 7.25H2.25C1.69772 7.25 1.25 7.69772 1.25 8.25V9.75C1.25 10.3023 1.69772 10.75 2.25 10.75H3.75C4.30228 10.75 4.75 10.3023 4.75 9.75V8.25C4.75 7.69772 4.30228 7.25 3.75 7.25Z" fill="#222222"/>
+<path d="M9.75 7.25H8.25C7.69772 7.25 7.25 7.69772 7.25 8.25V9.75C7.25 10.3023 7.69772 10.75 8.25 10.75H9.75C10.3023 10.75 10.75 10.3023 10.75 9.75V8.25C10.75 7.69772 10.3023 7.25 9.75 7.25Z" fill="#222222"/>
+<path d="M15.75 7.25H14.25C13.6977 7.25 13.25 7.69772 13.25 8.25V9.75C13.25 10.3023 13.6977 10.75 14.25 10.75H15.75C16.3023 10.75 16.75 10.3023 16.75 9.75V8.25C16.75 7.69772 16.3023 7.25 15.75 7.25Z" fill="#222222"/>
+<path d="M3.75 13.25H2.25C1.69772 13.25 1.25 13.6977 1.25 14.25V15.75C1.25 16.3023 1.69772 16.75 2.25 16.75H3.75C4.30228 16.75 4.75 16.3023 4.75 15.75V14.25C4.75 13.6977 4.30228 13.25 3.75 13.25Z" fill="#222222"/>
+<path d="M9.75 13.25H8.25C7.69772 13.25 7.25 13.6977 7.25 14.25V15.75C7.25 16.3023 7.69772 16.75 8.25 16.75H9.75C10.3023 16.75 10.75 16.3023 10.75 15.75V14.25C10.75 13.6977 10.3023 13.25 9.75 13.25Z" fill="#222222"/>
+<path d="M15.75 13.25H14.25C13.6977 13.25 13.25 13.6977 13.25 14.25V15.75C13.25 16.3023 13.6977 16.75 14.25 16.75H15.75C16.3023 16.75 16.75 16.3023 16.75 15.75V14.25C16.75 13.6977 16.3023 13.25 15.75 13.25Z" fill="#222222"/>
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/info.svg b/packages/extensions/venia-pwa-live-search/src/icons/info.svg
new file mode 100644
index 0000000000..9d38231fc7
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/info.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle-fill" viewBox="0 0 16 16">
+  <path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/listView.svg b/packages/extensions/venia-pwa-live-search/src/icons/listView.svg
new file mode 100644
index 0000000000..7736fd01d9
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/listView.svg
@@ -0,0 +1,5 @@
+<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.5 4H3.5C3.22386 4 3 4.22386 3 4.5V5.5C3 5.77614 3.22386 6 3.5 6H14.5C14.7761 6 15 5.77614 15 5.5V4.5C15 4.22386 14.7761 4 14.5 4Z" fill="#222222"/>
+<path d="M14.5 8H3.5C3.22386 8 3 8.22386 3 8.5V9.5C3 9.77614 3.22386 10 3.5 10H14.5C14.7761 10 15 9.77614 15 9.5V8.5C15 8.22386 14.7761 8 14.5 8Z" fill="#222222"/>
+<path d="M14.5 12H3.5C3.22386 12 3 12.2239 3 12.5V13.5C3 13.7761 3.22386 14 3.5 14H14.5C14.7761 14 15 13.7761 15 13.5V12.5C15 12.2239 14.7761 12 14.5 12Z" fill="#222222"/>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/loading.svg b/packages/extensions/venia-pwa-live-search/src/icons/loading.svg
new file mode 100644
index 0000000000..d96e129176
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/loading.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+  <circle className="opacity-50" cx="12" cy="12" r="10" fill="white" stroke="white" stroke-width="4"></circle>
+  <path
+    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
+  </path>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/plus.svg b/packages/extensions/venia-pwa-live-search/src/icons/plus.svg
new file mode 100644
index 0000000000..0234636131
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/plus.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
+  <path fillRule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
+    clipRule="evenodd" />
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/sort.svg b/packages/extensions/venia-pwa-live-search/src/icons/sort.svg
new file mode 100644
index 0000000000..5a7008d927
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/sort.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.158 16" stroke="currentColor">
+  <g id="icon-mini-sort" transform="translate(-4 -8)">
+    <rect id="Placement_area" data-name="Placement area" width="16" height="16" transform="translate(4 8)"
+      opacity="0.004" />
+    <g id="icon" transform="translate(-290.537 -358.082)">
+      <path id="Path_38562" data-name="Path 38562" d="M309.634,376.594l-1.5,1.5-1.5-1.5" stroke-linecap="round"
+        stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_510" data-name="Line 510" x2="6.833" transform="translate(295.537 373.59)" stroke-linecap="round"
+        stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_511" data-name="Line 511" x2="8.121" transform="translate(295.537 369.726)" stroke-linecap="round"
+        stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_511-2" data-name="Line 511" y2="9.017" transform="translate(308.13 369.082)" stroke-linecap="round"
+        stroke-linejoin="round" stroke-width="1.5" />
+      <line id="Line_512" data-name="Line 512" x2="5.545" transform="translate(295.537 377.455)" stroke-linecap="round"
+        stroke-linejoin="round" stroke-width="1.5" />
+    </g>
+  </g>
+</svg>
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/warning.svg b/packages/extensions/venia-pwa-live-search/src/icons/warning.svg
new file mode 100644
index 0000000000..50e17525ee
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/warning.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle-fill" viewBox="0 0 16 16">
+  <path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/icons/x.svg b/packages/extensions/venia-pwa-live-search/src/icons/x.svg
new file mode 100644
index 0000000000..c865d888e0
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/icons/x.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16">
+  <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/venia-pwa-live-search/src/index.jsx b/packages/extensions/venia-pwa-live-search/src/index.jsx
new file mode 100644
index 0000000000..a47940017e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/index.jsx
@@ -0,0 +1,65 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+//import { render } from 'react'; // Ensure we're using React
+import React from 'react';
+
+import './styles/index.css';
+
+import { getUserViewHistory } from '../src/utils/getUserViewHistory';
+import App from './containers/App';
+import {
+  AttributeMetadataProvider,
+  CartProvider,
+  ProductsContextProvider,
+  SearchProvider,
+  StoreContextProvider,
+} from './context/';
+import Resize from './context/displayChange';
+import Translation from './context/translation';
+import { validateStoreDetailsKeys } from './utils/validateStoreDetails';
+
+/**
+ * @param {{ storeDetails: object }} props
+ */
+const LiveSearchPLP = ({ storeDetails }) => {
+  if (!storeDetails) {
+    throw new Error("Livesearch PLP's storeDetails prop was not provided");
+  }
+
+  const userViewHistory = getUserViewHistory();
+
+  const updatedStoreDetails = {
+    ...storeDetails,
+    context: {
+      ...storeDetails.context,
+      userViewHistory,
+    },
+  };
+
+  return (
+    <StoreContextProvider {...validateStoreDetailsKeys(updatedStoreDetails)}>
+      <AttributeMetadataProvider>
+        <SearchProvider>
+          <Resize>
+            <Translation>
+              <ProductsContextProvider>
+                <CartProvider>
+                  <App />
+                </CartProvider>
+              </ProductsContextProvider>
+            </Translation>
+          </Resize>
+        </SearchProvider>
+      </AttributeMetadataProvider>
+    </StoreContextProvider>
+  );
+};
+
+export default LiveSearchPLP;
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/customerGroupCode.gql.js b/packages/extensions/venia-pwa-live-search/src/queries/customerGroupCode.gql.js
new file mode 100644
index 0000000000..110501c531
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/customerGroupCode.gql.js
@@ -0,0 +1,10 @@
+import { gql } from '@apollo/client';
+
+export const GET_CUSTOMER_GROUP_CODE = gql`
+    query GetCustomerForLiveSearch {
+        customer {
+            id
+            group_code
+        }
+    }
+`;
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/eventing/getMagentoExtensionContext.gql.js b/packages/extensions/venia-pwa-live-search/src/queries/eventing/getMagentoExtensionContext.gql.js
new file mode 100644
index 0000000000..feb8cc766b
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/eventing/getMagentoExtensionContext.gql.js
@@ -0,0 +1,13 @@
+import { gql } from '@apollo/client';
+
+export const GET_MAGENTO_EXTENSION_CONTEXT = gql`
+    query magentoExtensionContext {
+        magentoExtensionContext: dataServicesMagentoExtensionContext {
+            magento_extension_version
+        }
+    }
+`;
+
+export default {
+    getMagentoExtensionContext: GET_MAGENTO_EXTENSION_CONTEXT
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/eventing/getPageType.gql.js b/packages/extensions/venia-pwa-live-search/src/queries/eventing/getPageType.gql.js
new file mode 100644
index 0000000000..922369a8d5
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/eventing/getPageType.gql.js
@@ -0,0 +1,14 @@
+import { gql } from '@apollo/client';
+
+export const RESOLVE_PAGE_TYPE = gql`
+    query ResolveURL($url: String!) {
+        urlResolver(url: $url) {
+            id
+            type
+        }
+    }
+`;
+
+export default {
+    resolvePagetypeQuery: RESOLVE_PAGE_TYPE
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/eventing/getStorefrontContext.gql.js b/packages/extensions/venia-pwa-live-search/src/queries/eventing/getStorefrontContext.gql.js
new file mode 100644
index 0000000000..8c6d2b8443
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/eventing/getStorefrontContext.gql.js
@@ -0,0 +1,27 @@
+import { gql } from '@apollo/client';
+
+export const GET_STOREFRONT_CONTEXT = gql`
+    query storefrontContext {
+        storefrontInstanceContext: dataServicesStorefrontInstanceContext {
+            catalog_extension_version
+            environment
+            environment_id
+            store_code
+            store_id
+            store_name
+            store_url
+            store_view_code
+            store_view_id
+            store_view_name
+            website_code
+            website_id
+            website_name
+            store_view_currency_code
+            base_currency_code
+        }
+    }
+`;
+
+export default {
+    getStorefrontContext: GET_STOREFRONT_CONTEXT
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/index.js b/packages/extensions/venia-pwa-live-search/src/queries/index.js
new file mode 100644
index 0000000000..f2c550971e
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/index.js
@@ -0,0 +1,3 @@
+export * from './customerGroupCode.gql';
+export * from './liveSearchPlpConfigs.gql';
+export * from './liveSearchPopoverConfigs.gql';
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/liveSearchPlpConfigs.gql.js b/packages/extensions/venia-pwa-live-search/src/queries/liveSearchPlpConfigs.gql.js
new file mode 100644
index 0000000000..ef418e4d35
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/liveSearchPlpConfigs.gql.js
@@ -0,0 +1,30 @@
+import { gql } from '@apollo/client';
+
+export const GET_STORE_CONFIG_FOR_PLP = gql`
+    query GetStoreConfigForLiveSearchPLP {
+        storeConfig {
+            id
+            ls_service_api_key
+            ls_environment_type
+            ls_environment_id
+            website_code
+            store_group_code
+            store_code
+            ls_autocomplete_limit
+            ls_min_query_length
+            #currency_symbol
+            base_currency_code
+            #currency_rate
+            ls_display_out_of_stock
+            ls_allow_all
+            ls_locale
+            ls_page_size_options
+            ls_page_size_default
+            base_url
+        }
+        currency {
+            default_display_currency_code
+            default_display_currency_symbol
+        }
+    }
+`;
diff --git a/packages/extensions/venia-pwa-live-search/src/queries/liveSearchPopoverConfigs.gql.js b/packages/extensions/venia-pwa-live-search/src/queries/liveSearchPopoverConfigs.gql.js
new file mode 100644
index 0000000000..e97ebd8325
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/queries/liveSearchPopoverConfigs.gql.js
@@ -0,0 +1,28 @@
+import { gql } from '@apollo/client';
+
+export const GET_STORE_CONFIG_FOR_LIVE_SEARCH_POPOVER = gql`
+    query GetStoreConfigForLiveSearchPopover {
+        storeConfig {
+            id
+            ls_environment_id
+            website_code
+            store_group_code
+            store_code
+            ls_autocomplete_limit
+            ls_min_query_length
+            #currency_symbol
+            base_currency_code
+            #currency_rate
+            ls_display_out_of_stock
+            ls_allow_all
+            ls_locale
+            ls_page_size_options
+            ls_page_size_default
+            base_url
+        }
+        currency {
+            default_display_currency_code
+            default_display_currency_symbol
+        }
+    }
+`;
diff --git a/packages/extensions/venia-pwa-live-search/src/styles/autocomplete.module.css b/packages/extensions/venia-pwa-live-search/src/styles/autocomplete.module.css
new file mode 100644
index 0000000000..7929e6aa8a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/styles/autocomplete.module.css
@@ -0,0 +1,56 @@
+.root {
+    composes: absolute from global;
+    composes: bg-white from global;
+    composes: border-2 from global;
+    composes: border-input from global;
+    composes: border-solid from global;
+    composes: border-t-0 from global;
+    composes: gap-3 from global;
+    composes: grid from global;
+    composes: left-0 from global;
+    composes: p-xs from global;
+    composes: right-0 from global;
+    composes: rounded-b-md from global;
+    composes: rounded-t-none from global;
+    composes: shadow-inputFocus from global;
+    composes: text-sm from global;
+    composes: top-9 from global;
+    composes: z-menu from global;
+    transition-property: opacity, transform, visibility;
+}
+
+.root_hidden {
+    composes: root;
+
+    composes: invisible from global;
+    composes: opacity-0 from global;
+    transform: translate3d(0, -2rem, 0);
+    transition-duration: 192ms;
+    transition-timing-function: var(--venia-global-anim-out);
+}
+
+.root_visible {
+    composes: root;
+
+    composes: opacity-100 from global;
+    composes: visible from global;
+    transform: translate3d(0, 0, 0);
+    transition-duration: 224ms;
+    transition-timing-function: var(--venia-global-anim-in);
+}
+
+.message {
+    composes: px-3 from global;
+    composes: py-0 from global;
+    composes: text-center from global;
+    composes: text-subtle from global;
+
+    composes: empty_hidden from global;
+}
+
+.suggestions {
+    composes: gap-2xs from global;
+    composes: grid from global;
+
+    composes: empty_hidden from global;
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/styles/index.css b/packages/extensions/venia-pwa-live-search/src/styles/index.css
new file mode 100644
index 0000000000..8cf3f8b8e6
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/styles/index.css
@@ -0,0 +1,1638 @@
+/* Tokens */
+
+.ds-widgets {
+    /* ! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com */
+    /*
+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
+*/
+    *,
+    ::before,
+    ::after {
+        box-sizing: border-box;
+        /* 1 */
+        border-width: 0;
+        /* 2 */
+        border-style: solid;
+        /* 2 */
+        border-color: var(--color-gray-2);
+        /* 2 */
+    }
+    ::before,
+    ::after {
+        --tw-content: '';
+    }
+    /*
+1. Use a consistent sensible line-height in all browsers.
+2. Prevent adjustments of font size after orientation changes in iOS.
+3. Use a more readable tab size.
+4. Use the user's configured `sans` font-family by default.
+5. Use the user's configured `sans` font-feature-settings by default.
+6. Use the user's configured `sans` font-variation-settings by default.
+7. Disable tap highlights on iOS
+*/
+    html,
+    :host {
+        line-height: 1.5;
+        /* 1 */
+        -webkit-text-size-adjust: 100%;
+        /* 2 */
+        -moz-tab-size: 4;
+        /* 3 */
+        -o-tab-size: 4;
+        tab-size: 4;
+        /* 3 */
+        font-family: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji',
+            'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+        /* 4 */
+        font-feature-settings: normal;
+        /* 5 */
+        font-variation-settings: normal;
+        /* 6 */
+        -webkit-tap-highlight-color: transparent;
+        /* 7 */
+    }
+    /*
+1. Remove the margin in all browsers.
+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
+*/
+    body {
+        margin: 0;
+        /* 1 */
+        line-height: inherit;
+        /* 2 */
+    }
+    /*
+1. Add the correct height in Firefox.
+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
+3. Ensure horizontal rules are visible by default.
+*/
+    hr {
+        height: 0;
+        /* 1 */
+        color: inherit;
+        /* 2 */
+        border-top-width: 1px;
+        /* 3 */
+    }
+    /*
+Add the correct text decoration in Chrome, Edge, and Safari.
+*/
+    abbr:where([title]) {
+        -webkit-text-decoration: underline dotted;
+        text-decoration: underline dotted;
+    }
+    /*
+Remove the default font size and weight for headings.
+*/
+    h1,
+    h2,
+    h3,
+    h4,
+    h5,
+    h6 {
+        font-size: inherit;
+        font-weight: inherit;
+    }
+    /*
+Reset links to optimize for opt-in styling instead of opt-out.
+*/
+    a {
+        color: inherit;
+        text-decoration: inherit;
+    }
+    /*
+Add the correct font weight in Edge and Safari.
+*/
+    b,
+    strong {
+        font-weight: bolder;
+    }
+    /*
+1. Use the user's configured `mono` font-family by default.
+2. Use the user's configured `mono` font-feature-settings by default.
+3. Use the user's configured `mono` font-variation-settings by default.
+4. Correct the odd `em` font sizing in all browsers.
+*/
+    code,
+    kbd,
+    samp,
+    pre {
+        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
+            'Liberation Mono', 'Courier New', monospace;
+        /* 1 */
+        font-feature-settings: normal;
+        /* 2 */
+        font-variation-settings: normal;
+        /* 3 */
+        font-size: 1em;
+        /* 4 */
+    }
+    /*
+Add the correct font size in all browsers.
+*/
+    small {
+        font-size: 80%;
+    }
+    /*
+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
+*/
+    sub,
+    sup {
+        font-size: 75%;
+        line-height: 0;
+        position: relative;
+        vertical-align: baseline;
+    }
+    sub {
+        bottom: -0.25em;
+    }
+    sup {
+        top: -0.5em;
+    }
+    /*
+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
+3. Remove gaps between table borders by default.
+*/
+    table {
+        text-indent: 0;
+        /* 1 */
+        border-color: inherit;
+        /* 2 */
+        border-collapse: collapse;
+        /* 3 */
+    }
+    /*
+1. Change the font styles in all browsers.
+2. Remove the margin in Firefox and Safari.
+3. Remove default padding in all browsers.
+*/
+    button,
+    input,
+    optgroup,
+    select,
+    textarea {
+        font-family: inherit;
+        /* 1 */
+        font-feature-settings: inherit;
+        /* 1 */
+        font-variation-settings: inherit;
+        /* 1 */
+        font-size: 100%;
+        /* 1 */
+        font-weight: inherit;
+        /* 1 */
+        line-height: inherit;
+        /* 1 */
+        color: inherit;
+        /* 1 */
+        margin: 0;
+        /* 2 */
+        padding: 0;
+        /* 3 */
+    }
+    /*
+Remove the inheritance of text transform in Edge and Firefox.
+*/
+    button,
+    select {
+        text-transform: none;
+    }
+    /*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Remove default button styles.
+*/
+    button,
+    [type='button'],
+    [type='reset'],
+    [type='submit'] {
+        -webkit-appearance: button;
+        /* 1 */
+        background-color: transparent;
+        /* 2 */
+        background-image: none;
+        /* 2 */
+    }
+    /*
+Use the modern Firefox focus style for all focusable elements.
+*/
+    :-moz-focusring {
+        outline: auto;
+    }
+    /*
+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
+*/
+    :-moz-ui-invalid {
+        box-shadow: none;
+    }
+    /*
+Add the correct vertical alignment in Chrome and Firefox.
+*/
+    progress {
+        vertical-align: baseline;
+    }
+    /*
+Correct the cursor style of increment and decrement buttons in Safari.
+*/
+    ::-webkit-inner-spin-button,
+    ::-webkit-outer-spin-button {
+        height: auto;
+    }
+    /*
+1. Correct the odd appearance in Chrome and Safari.
+2. Correct the outline style in Safari.
+*/
+    [type='search'] {
+        -webkit-appearance: textfield;
+        /* 1 */
+        outline-offset: -2px;
+        /* 2 */
+    }
+    /*
+Remove the inner padding in Chrome and Safari on macOS.
+*/
+    ::-webkit-search-decoration {
+        -webkit-appearance: none;
+    }
+    /*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Change font properties to `inherit` in Safari.
+*/
+    ::-webkit-file-upload-button {
+        -webkit-appearance: button;
+        /* 1 */
+        font: inherit;
+        /* 2 */
+    }
+    /*
+Add the correct display in Chrome and Safari.
+*/
+    summary {
+        display: list-item;
+    }
+    /*
+Removes the default spacing and border for appropriate elements.
+*/
+    blockquote,
+    dl,
+    dd,
+    h1,
+    h2,
+    h3,
+    h4,
+    h5,
+    h6,
+    hr,
+    figure,
+    p,
+    pre {
+        margin: 0;
+    }
+    fieldset {
+        margin: 0;
+        padding: 0;
+    }
+    legend {
+        padding: 0;
+    }
+    ol,
+    ul,
+    menu {
+        list-style: none;
+        margin: 0;
+        padding: 0;
+    }
+    /*
+Reset default styling for dialogs.
+*/
+    dialog {
+        padding: 0;
+    }
+    /*
+Prevent resizing textareas horizontally by default.
+*/
+    textarea {
+        resize: vertical;
+    }
+    /*
+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
+2. Set the default placeholder color to the user's configured gray 400 color.
+*/
+    input::-moz-placeholder,
+    textarea::-moz-placeholder {
+        opacity: 1;
+        /* 1 */
+        color: var(--color-gray-4);
+        /* 2 */
+    }
+    input::placeholder,
+    textarea::placeholder {
+        opacity: 1;
+        /* 1 */
+        color: var(--color-gray-4);
+        /* 2 */
+    }
+    /*
+Set the default cursor for buttons.
+*/
+    button,
+    [role='button'] {
+        cursor: pointer;
+    }
+    /*
+Make sure disabled buttons don't get the pointer cursor.
+*/
+    :disabled {
+        cursor: default;
+    }
+    /*
+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
+   This can trigger a poorly considered lint error in some tools but is included by design.
+*/
+    img,
+    svg,
+    video,
+    canvas,
+    audio,
+    iframe,
+    embed,
+    object {
+        display: block;
+        /* 1 */
+        vertical-align: middle;
+        /* 2 */
+    }
+    /*
+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
+*/
+    img,
+    video {
+        max-width: 100%;
+        height: auto;
+    }
+    /* Make elements with the HTML hidden attribute stay hidden by default */
+    [hidden] {
+        display: none;
+    }
+    *,
+    ::before,
+    ::after {
+        --tw-border-spacing-x: 0;
+        --tw-border-spacing-y: 0;
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+        --tw-pan-x: ;
+        --tw-pan-y: ;
+        --tw-pinch-zoom: ;
+        --tw-scroll-snap-strictness: proximity;
+        --tw-gradient-from-position: ;
+        --tw-gradient-via-position: ;
+        --tw-gradient-to-position: ;
+        --tw-ordinal: ;
+        --tw-slashed-zero: ;
+        --tw-numeric-figure: ;
+        --tw-numeric-spacing: ;
+        --tw-numeric-fraction: ;
+        --tw-ring-inset: ;
+        --tw-ring-offset-width: 0px;
+        --tw-ring-offset-color: #fff;
+        --tw-ring-color: rgb(59 130 246 / 0.5);
+        --tw-ring-offset-shadow: 0 0 #0000;
+        --tw-ring-shadow: 0 0 #0000;
+        --tw-shadow: 0 0 #0000;
+        --tw-shadow-colored: 0 0 #0000;
+        --tw-blur: ;
+        --tw-brightness: ;
+        --tw-contrast: ;
+        --tw-grayscale: ;
+        --tw-hue-rotate: ;
+        --tw-invert: ;
+        --tw-saturate: ;
+        --tw-sepia: ;
+        --tw-drop-shadow: ;
+        --tw-backdrop-blur: ;
+        --tw-backdrop-brightness: ;
+        --tw-backdrop-contrast: ;
+        --tw-backdrop-grayscale: ;
+        --tw-backdrop-hue-rotate: ;
+        --tw-backdrop-invert: ;
+        --tw-backdrop-opacity: ;
+        --tw-backdrop-saturate: ;
+        --tw-backdrop-sepia: ;
+    }
+    ::backdrop {
+        --tw-border-spacing-x: 0;
+        --tw-border-spacing-y: 0;
+        --tw-translate-x: 0;
+        --tw-translate-y: 0;
+        --tw-rotate: 0;
+        --tw-skew-x: 0;
+        --tw-skew-y: 0;
+        --tw-scale-x: 1;
+        --tw-scale-y: 1;
+        --tw-pan-x: ;
+        --tw-pan-y: ;
+        --tw-pinch-zoom: ;
+        --tw-scroll-snap-strictness: proximity;
+        --tw-gradient-from-position: ;
+        --tw-gradient-via-position: ;
+        --tw-gradient-to-position: ;
+        --tw-ordinal: ;
+        --tw-slashed-zero: ;
+        --tw-numeric-figure: ;
+        --tw-numeric-spacing: ;
+        --tw-numeric-fraction: ;
+        --tw-ring-inset: ;
+        --tw-ring-offset-width: 0px;
+        --tw-ring-offset-color: #fff;
+        --tw-ring-color: rgb(59 130 246 / 0.5);
+        --tw-ring-offset-shadow: 0 0 #0000;
+        --tw-ring-shadow: 0 0 #0000;
+        --tw-shadow: 0 0 #0000;
+        --tw-shadow-colored: 0 0 #0000;
+        --tw-blur: ;
+        --tw-brightness: ;
+        --tw-contrast: ;
+        --tw-grayscale: ;
+        --tw-hue-rotate: ;
+        --tw-invert: ;
+        --tw-saturate: ;
+        --tw-sepia: ;
+        --tw-drop-shadow: ;
+        --tw-backdrop-blur: ;
+        --tw-backdrop-brightness: ;
+        --tw-backdrop-contrast: ;
+        --tw-backdrop-grayscale: ;
+        --tw-backdrop-hue-rotate: ;
+        --tw-backdrop-invert: ;
+        --tw-backdrop-opacity: ;
+        --tw-backdrop-saturate: ;
+        --tw-backdrop-sepia: ;
+    }
+    .container {
+        width: 100%;
+    }
+    @media (min-width: 640px) {
+        .container {
+            max-width: 640px;
+        }
+    }
+    @media (min-width: 768px) {
+        .container {
+            max-width: 768px;
+        }
+    }
+    @media (min-width: 1024px) {
+        .container {
+            max-width: 1024px;
+        }
+    }
+    @media (min-width: 1280px) {
+        .container {
+            max-width: 1280px;
+        }
+    }
+    @media (min-width: 1536px) {
+        .container {
+            max-width: 1536px;
+        }
+    }
+    .sr-only {
+        position: absolute;
+        width: 1px;
+        height: 1px;
+        padding: 0;
+        margin: -1px;
+        overflow: hidden;
+        clip: rect(0, 0, 0, 0);
+        white-space: nowrap;
+        border-width: 0;
+    }
+    .visible {
+        visibility: visible;
+    }
+    .invisible {
+        visibility: hidden;
+    }
+    .absolute {
+        position: absolute;
+    }
+    .relative {
+        position: relative;
+    }
+    .bottom-0 {
+        bottom: 0px;
+    }
+    .left-1\/2 {
+        left: 50%;
+    }
+    .right-0 {
+        right: 0px;
+    }
+    .top-0 {
+        top: 0px;
+    }
+    .z-20 {
+        z-index: 20;
+    }
+    .m-4 {
+        margin: 1rem;
+    }
+    .m-auto {
+        margin: auto;
+    }
+    .mx-auto {
+        margin-left: auto;
+        margin-right: auto;
+    }
+    .mx-sm {
+        margin-left: var(--spacing-sm);
+        margin-right: var(--spacing-sm);
+    }
+    .my-0 {
+        margin-top: 0px;
+        margin-bottom: 0px;
+    }
+    .my-auto {
+        margin-top: auto;
+        margin-bottom: auto;
+    }
+    .my-lg {
+        margin-top: var(--spacing-lg);
+        margin-bottom: var(--spacing-lg);
+    }
+    .mb-0 {
+        margin-bottom: 0px;
+    }
+    .mb-0\.5 {
+        margin-bottom: 0.125rem;
+    }
+    .mb-6 {
+        margin-bottom: 1.5rem;
+    }
+    .mb-\[1px\] {
+        margin-bottom: 1px;
+    }
+    .mb-md {
+        margin-bottom: var(--spacing-md);
+    }
+    .ml-1 {
+        margin-left: 0.25rem;
+    }
+    .ml-2 {
+        margin-left: 0.5rem;
+    }
+    .ml-3 {
+        margin-left: 0.75rem;
+    }
+    .ml-auto {
+        margin-left: auto;
+    }
+    .ml-sm {
+        margin-left: var(--spacing-sm);
+    }
+    .ml-xs {
+        margin-left: var(--spacing-xs);
+    }
+    .mr-2 {
+        margin-right: 0.5rem;
+    }
+    .mr-auto {
+        margin-right: auto;
+    }
+    .mr-sm {
+        margin-right: var(--spacing-sm);
+    }
+    .mr-xs {
+        margin-right: var(--spacing-xs);
+    }
+    .mt-2 {
+        margin-top: 0.5rem;
+    }
+    .mt-4 {
+        margin-top: 1rem;
+    }
+    .mt-8 {
+        margin-top: 2rem;
+    }
+    .mt-\[-2px\] {
+        margin-top: -2px;
+    }
+    .mt-md {
+        margin-top: var(--spacing-md);
+    }
+    .mt-sm {
+        margin-top: var(--spacing-sm);
+    }
+    .mt-xs {
+        margin-top: var(--spacing-xs);
+    }
+    .inline-block {
+        display: inline-block;
+    }
+    .inline {
+        display: inline;
+    }
+    .flex {
+        display: flex;
+    }
+    .inline-flex {
+        display: inline-flex;
+    }
+    .grid {
+        display: grid;
+    }
+    .hidden {
+        display: none;
+    }
+    .aspect-auto {
+        aspect-ratio: auto;
+    }
+    .h-28 {
+        height: 7rem;
+    }
+    .h-3 {
+        height: 0.75rem;
+    }
+    .h-5 {
+        height: 1.25rem;
+    }
+    .h-\[12px\] {
+        height: 12px;
+    }
+    .h-\[15px\] {
+        height: 15px;
+    }
+    .h-\[20px\] {
+        height: 20px;
+    }
+    .h-\[32px\] {
+        height: 32px;
+    }
+    .h-\[38px\] {
+        height: 38px;
+    }
+    .h-auto {
+        height: auto;
+    }
+    .h-full {
+        height: 100%;
+    }
+    .h-md {
+        height: var(--spacing-md);
+    }
+    .h-screen {
+        height: 100vh;
+    }
+    .h-sm {
+        height: var(--spacing-sm);
+    }
+    .max-h-\[250px\] {
+        max-height: 250px;
+    }
+    .max-h-\[45rem\] {
+        max-height: 45rem;
+    }
+    .min-h-\[32px\] {
+        min-height: 32px;
+    }
+    .w-1\/3 {
+        width: 33.333333%;
+    }
+    .w-28 {
+        width: 7rem;
+    }
+    .w-5 {
+        width: 1.25rem;
+    }
+    .w-96 {
+        width: 24rem;
+    }
+    .w-\[12px\] {
+        width: 12px;
+    }
+    .w-\[15px\] {
+        width: 15px;
+    }
+    .w-\[20px\] {
+        width: 20px;
+    }
+    .w-\[24px\] {
+        width: 24px;
+    }
+    .w-\[30px\] {
+        width: 30px;
+    }
+    .w-fit {
+        width: -moz-fit-content;
+        width: fit-content;
+    }
+    .w-full {
+        width: 100%;
+    }
+    .w-md {
+        width: var(--spacing-md);
+    }
+    .w-sm {
+        width: var(--spacing-sm);
+    }
+    .min-w-\[16px\] {
+        min-width: 16px;
+    }
+    .min-w-\[32px\] {
+        min-width: 32px;
+    }
+    .max-w-2xl {
+        max-width: 42rem;
+    }
+    .max-w-5xl {
+        max-width: 64rem;
+    }
+    .max-w-\[200px\] {
+        max-width: 200px;
+    }
+    .max-w-\[21rem\] {
+        max-width: 21rem;
+    }
+    .max-w-full {
+        max-width: 100%;
+    }
+    .max-w-sm {
+        max-width: 24rem;
+    }
+    .flex-1 {
+        flex: 1 1 0%;
+    }
+    .flex-shrink-0 {
+        flex-shrink: 0;
+    }
+    .origin-top-right {
+        transform-origin: top right;
+    }
+    .-translate-x-1\/2 {
+        --tw-translate-x: -50%;
+        transform: translate(var(--tw-translate-x), var(--tw-translate-y))
+            rotate(var(--tw-rotate)) skewX(var(--tw-skew-x))
+            skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+            scaleY(var(--tw-scale-y));
+    }
+    .-rotate-90 {
+        --tw-rotate: -90deg;
+        transform: translate(var(--tw-translate-x), var(--tw-translate-y))
+            rotate(var(--tw-rotate)) skewX(var(--tw-skew-x))
+            skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+            scaleY(var(--tw-scale-y));
+    }
+    .rotate-180 {
+        --tw-rotate: 180deg;
+        transform: translate(var(--tw-translate-x), var(--tw-translate-y))
+            rotate(var(--tw-rotate)) skewX(var(--tw-skew-x))
+            skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+            scaleY(var(--tw-scale-y));
+    }
+    .rotate-45 {
+        --tw-rotate: 45deg;
+        transform: translate(var(--tw-translate-x), var(--tw-translate-y))
+            rotate(var(--tw-rotate)) skewX(var(--tw-skew-x))
+            skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+            scaleY(var(--tw-scale-y));
+    }
+    .rotate-90 {
+        --tw-rotate: 90deg;
+        transform: translate(var(--tw-translate-x), var(--tw-translate-y))
+            rotate(var(--tw-rotate)) skewX(var(--tw-skew-x))
+            skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+            scaleY(var(--tw-scale-y));
+    }
+    .transform {
+        transform: translate(var(--tw-translate-x), var(--tw-translate-y))
+            rotate(var(--tw-rotate)) skewX(var(--tw-skew-x))
+            skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
+            scaleY(var(--tw-scale-y));
+    }
+    @keyframes spin {
+        to {
+            transform: rotate(360deg);
+        }
+    }
+    .animate-spin {
+        animation: spin 1s linear infinite;
+    }
+    .cursor-not-allowed {
+        cursor: not-allowed;
+    }
+    .cursor-pointer {
+        cursor: pointer;
+    }
+    .resize {
+        resize: both;
+    }
+    .list-none {
+        list-style-type: none;
+    }
+    .appearance-none {
+        -webkit-appearance: none;
+        -moz-appearance: none;
+        appearance: none;
+    }
+    .grid-cols-1 {
+        grid-template-columns: repeat(1, minmax(0, 1fr));
+    }
+    .grid-cols-none {
+        grid-template-columns: none;
+    }
+    .flex-row {
+        flex-direction: row;
+    }
+    .flex-col {
+        flex-direction: column;
+    }
+    .flex-wrap {
+        flex-wrap: wrap;
+    }
+    .flex-nowrap {
+        flex-wrap: nowrap;
+    }
+    .items-center {
+        align-items: center;
+    }
+    .justify-start {
+        justify-content: flex-start;
+    }
+    .justify-end {
+        justify-content: flex-end;
+    }
+    .justify-center {
+        justify-content: center;
+    }
+    .justify-between {
+        justify-content: space-between;
+    }
+    .gap-\[10px\] {
+        gap: 10px;
+    }
+    .gap-x-2 {
+        -moz-column-gap: 0.5rem;
+        column-gap: 0.5rem;
+    }
+    .gap-x-2\.5 {
+        -moz-column-gap: 0.625rem;
+        column-gap: 0.625rem;
+    }
+    .gap-x-2xl {
+        -moz-column-gap: var(--spacing-2xl);
+        column-gap: var(--spacing-2xl);
+    }
+    .gap-x-md {
+        -moz-column-gap: var(--spacing-md);
+        column-gap: var(--spacing-md);
+    }
+    .gap-y-8 {
+        row-gap: 2rem;
+    }
+    .space-x-2 > :not([hidden]) ~ :not([hidden]) {
+        --tw-space-x-reverse: 0;
+        margin-right: calc(0.5rem * var(--tw-space-x-reverse));
+        margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
+    }
+    .space-x-3 > :not([hidden]) ~ :not([hidden]) {
+        --tw-space-x-reverse: 0;
+        margin-right: calc(0.75rem * var(--tw-space-x-reverse));
+        margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
+    }
+    .space-y-4 > :not([hidden]) ~ :not([hidden]) {
+        --tw-space-y-reverse: 0;
+        margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
+        margin-bottom: calc(1rem * var(--tw-space-y-reverse));
+    }
+    .overflow-hidden {
+        overflow: hidden;
+    }
+    .overflow-y-auto {
+        overflow-y: auto;
+    }
+    .whitespace-nowrap {
+        white-space: nowrap;
+    }
+    .rounded-full {
+        border-radius: 9999px;
+    }
+    .rounded-lg {
+        border-radius: 0.5rem;
+    }
+    .rounded-md {
+        border-radius: 0.375rem;
+    }
+    .border {
+        border-width: 1px;
+    }
+    .border-0 {
+        border-width: 0px;
+    }
+    .border-\[1\.5px\] {
+        border-width: 1.5px;
+    }
+    .border-t {
+        border-top-width: 1px;
+    }
+    .border-solid {
+        border-style: solid;
+    }
+    .border-none {
+        border-style: none;
+    }
+    .border-black {
+        --tw-border-opacity: 1;
+        border-color: rgb(0 0 0 / var(--tw-border-opacity));
+    }
+    .border-gray-200 {
+        border-color: var(--color-gray-2);
+    }
+    .border-gray-300 {
+        border-color: var(--color-gray-3);
+    }
+    .border-transparent {
+        border-color: transparent;
+    }
+    .bg-blue-50 {
+        --tw-bg-opacity: 1;
+        background-color: rgb(239 246 255 / var(--tw-bg-opacity));
+    }
+    .bg-body {
+        background-color: var(--color-body);
+    }
+    .bg-gray-100 {
+        background-color: var(--color-gray-1);
+    }
+    .bg-gray-200 {
+        background-color: var(--color-gray-2);
+    }
+    .bg-green-50 {
+        --tw-bg-opacity: 1;
+        background-color: rgb(240 253 244 / var(--tw-bg-opacity));
+    }
+    .bg-red-50 {
+        --tw-bg-opacity: 1;
+        background-color: rgb(254 242 242 / var(--tw-bg-opacity));
+    }
+    .bg-transparent {
+        background-color: transparent;
+    }
+    .bg-white {
+        --tw-bg-opacity: 1;
+        background-color: rgb(255 255 255 / var(--tw-bg-opacity));
+    }
+    .bg-yellow-50 {
+        --tw-bg-opacity: 1;
+        background-color: rgb(254 252 232 / var(--tw-bg-opacity));
+    }
+    .fill-gray-500 {
+        fill: var(--color-gray-5);
+    }
+    .fill-gray-700 {
+        fill: var(--color-gray-7);
+    }
+    .fill-primary {
+        fill: var(--color-primary);
+    }
+    .stroke-gray-400 {
+        stroke: var(--color-gray-4);
+    }
+    .stroke-gray-600 {
+        stroke: var(--color-gray-6);
+    }
+    .stroke-1 {
+        stroke-width: 1;
+    }
+    .object-cover {
+        -o-object-fit: cover;
+        object-fit: cover;
+    }
+    .object-center {
+        -o-object-position: center;
+        object-position: center;
+    }
+    .p-1 {
+        padding: 0.25rem;
+    }
+    .p-1\.5 {
+        padding: 0.375rem;
+    }
+    .p-2 {
+        padding: 0.5rem;
+    }
+    .p-4 {
+        padding: 1rem;
+    }
+    .p-5 {
+        padding: 0.8rem;
+    }
+    .p-sm {
+        padding: var(--spacing-sm);
+    }
+    .p-xs {
+        padding: var(--spacing-xs);
+    }
+    .px-1 {
+        padding-left: 0.25rem;
+        padding-right: 0.25rem;
+    }
+    .px-2 {
+        padding-left: 0.5rem;
+        padding-right: 0.5rem;
+    }
+    .px-4 {
+        padding-left: 1rem;
+        padding-right: 1rem;
+    }
+    .px-md {
+        padding-left: var(--spacing-md);
+        padding-right: var(--spacing-md);
+    }
+    .px-sm {
+        padding-left: var(--spacing-sm);
+        padding-right: var(--spacing-sm);
+    }
+    .py-1 {
+        padding-top: 0.25rem;
+        padding-bottom: 0.25rem;
+    }
+    .py-12 {
+        padding-top: 3rem;
+        padding-bottom: 3rem;
+    }
+    .py-2 {
+        padding-top: 0.5rem;
+        padding-bottom: 0.5rem;
+    }
+    .py-sm {
+        padding-top: var(--spacing-sm);
+        padding-bottom: var(--spacing-sm);
+    }
+    .py-xs {
+        padding-top: var(--spacing-xs);
+        padding-bottom: var(--spacing-xs);
+    }
+    .pb-2 {
+        padding-bottom: 0.5rem;
+    }
+    .pb-2xl {
+        padding-bottom: var(--spacing-2xl);
+    }
+    .pb-3 {
+        padding-bottom: 0.75rem;
+    }
+    .pb-4 {
+        padding-bottom: 1rem;
+    }
+    .pb-6 {
+        padding-bottom: 1.5rem;
+    }
+    .pl-3 {
+        padding-left: 0.75rem;
+    }
+    .pl-8 {
+        padding-left: 2rem;
+    }
+    .pr-2 {
+        padding-right: 0.5rem;
+    }
+    .pr-4 {
+        padding-right: 1rem;
+    }
+    .pr-5 {
+        padding-right: 1.25rem;
+    }
+    .pr-lg {
+        padding-right: var(--spacing-lg);
+    }
+    .pt-16 {
+        padding-top: 4rem;
+    }
+    .pt-28 {
+        padding-top: 7rem;
+    }
+    .pt-\[15px\] {
+        padding-top: 15px;
+    }
+    .pt-md {
+        padding-top: var(--spacing-md);
+    }
+    .text-left {
+        text-align: left;
+    }
+    .text-center {
+        text-align: center;
+    }
+    .text-2xl {
+        font-size: var(--font-2xl);
+        line-height: var(--leading-loose);
+    }
+    .text-\[12px\] {
+        font-size: 12px;
+    }
+    .text-base {
+        font-size: var(--font-md);
+        line-height: var(--leading-snug);
+    }
+    .text-lg {
+        font-size: var(--font-lg);
+        line-height: var(--leading-normal);
+    }
+    .text-sm {
+        font-size: var(--font-sm);
+        line-height: var(--leading-tight);
+    }
+    .text-xs {
+        font-size: var(--font-xs);
+        line-height: var(--leading-none);
+    }
+    .font-light {
+        font-weight: var(--font-light);
+    }
+    .font-medium {
+        font-weight: var(--font-medium);
+    }
+    .font-normal {
+        font-weight: var(--font-normal);
+    }
+    .font-semibold {
+        font-weight: var(--font-semibold);
+    }
+    .\!text-primary {
+        color: var(--color-primary) !important;
+    }
+    .text-black {
+        --tw-text-opacity: 1;
+        color: rgb(0 0 0 / var(--tw-text-opacity));
+    }
+    .text-blue-400 {
+        --tw-text-opacity: 1;
+        color: rgb(96 165 250 / var(--tw-text-opacity));
+    }
+    .text-blue-700 {
+        --tw-text-opacity: 1;
+        color: rgb(29 78 216 / var(--tw-text-opacity));
+    }
+    .text-blue-800 {
+        --tw-text-opacity: 1;
+        color: rgb(30 64 175 / var(--tw-text-opacity));
+    }
+    .text-gray-500 {
+        color: var(--color-gray-5);
+    }
+    .text-gray-600 {
+        color: var(--color-gray-6);
+    }
+    .text-gray-700 {
+        color: var(--color-gray-7);
+    }
+    .text-gray-800 {
+        color: var(--color-gray-8);
+    }
+    .text-gray-900 {
+        color: var(--color-gray-9);
+    }
+    .text-green-400 {
+        --tw-text-opacity: 1;
+        color: rgb(74 222 128 / var(--tw-text-opacity));
+    }
+    .text-green-500 {
+        --tw-text-opacity: 1;
+        color: rgb(34 197 94 / var(--tw-text-opacity));
+    }
+    .text-green-700 {
+        --tw-text-opacity: 1;
+        color: rgb(21 128 61 / var(--tw-text-opacity));
+    }
+    .text-green-800 {
+        --tw-text-opacity: 1;
+        color: rgb(22 101 52 / var(--tw-text-opacity));
+    }
+    .text-primary {
+        color: var(--color-primary);
+    }
+    .text-red-400 {
+        --tw-text-opacity: 1;
+        color: rgb(248 113 113 / var(--tw-text-opacity));
+    }
+    .text-red-700 {
+        --tw-text-opacity: 1;
+        color: rgb(185 28 28 / var(--tw-text-opacity));
+    }
+    .text-red-800 {
+        --tw-text-opacity: 1;
+        color: rgb(153 27 27 / var(--tw-text-opacity));
+    }
+    .text-secondary {
+        color: var(--color-secondary);
+    }
+    .text-white {
+        --tw-text-opacity: 1;
+        color: rgb(255 255 255 / var(--tw-text-opacity));
+    }
+    .text-yellow-400 {
+        --tw-text-opacity: 1;
+        color: rgb(250 204 21 / var(--tw-text-opacity));
+    }
+    .text-yellow-700 {
+        --tw-text-opacity: 1;
+        color: rgb(161 98 7 / var(--tw-text-opacity));
+    }
+    .text-yellow-800 {
+        --tw-text-opacity: 1;
+        color: rgb(133 77 14 / var(--tw-text-opacity));
+    }
+    .underline {
+        text-decoration-line: underline;
+    }
+    .line-through {
+        text-decoration-line: line-through;
+    }
+    .no-underline {
+        text-decoration-line: none;
+    }
+    .decoration-black {
+        text-decoration-color: #000;
+    }
+    .underline-offset-4 {
+        text-underline-offset: 4px;
+    }
+    .accent-gray-600 {
+        accent-color: var(--color-gray-6);
+    }
+    .opacity-0 {
+        opacity: 0;
+    }
+    .shadow-2xl {
+        --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
+        --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
+        box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
+            var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+    }
+    .outline {
+        outline-style: solid;
+    }
+    .outline-1 {
+        outline-width: 1px;
+    }
+    .outline-gray-200 {
+        outline-color: var(--color-gray-2);
+    }
+    .outline-transparent {
+        outline-color: transparent;
+    }
+    .ring-1 {
+        --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
+            var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+        --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
+            calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+        box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
+            var(--tw-shadow, 0 0 #0000);
+    }
+    .ring-black {
+        --tw-ring-opacity: 1;
+        --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
+    }
+    .ring-opacity-5 {
+        --tw-ring-opacity: 0.05;
+    }
+    .blur {
+        --tw-blur: blur(8px);
+        filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast)
+            var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert)
+            var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
+    }
+    .\!filter {
+        filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast)
+            var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert)
+            var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important;
+    }
+    .filter {
+        filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast)
+            var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert)
+            var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
+    }
+    .transition {
+        transition-property: color, background-color, border-color,
+            text-decoration-color, fill, stroke, opacity, box-shadow, transform,
+            filter, -webkit-backdrop-filter;
+        transition-property: color, background-color, border-color,
+            text-decoration-color, fill, stroke, opacity, box-shadow, transform,
+            filter, backdrop-filter;
+        transition-property: color, background-color, border-color,
+            text-decoration-color, fill, stroke, opacity, box-shadow, transform,
+            filter, backdrop-filter, -webkit-backdrop-filter;
+        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+        transition-duration: 150ms;
+    }
+    .transition-opacity {
+        transition-property: opacity;
+        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+        transition-duration: 150ms;
+    }
+    .ease-out {
+        transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+    }
+    /* font-size: 1.6rem; */
+    /* Colors */
+    --color-body: #fff;
+    --color-on-body: #222;
+    --color-surface: #e6e6e6;
+    --color-on-surface: #222;
+    --color-primary: #222;
+    --color-on-primary: #fff;
+    --color-secondary: #ff0000;
+    --color-on-secondary: #fff;
+    --color-gray-1: #f3f4f6;
+    --color-gray-2: #e5e7eb;
+    --color-gray-3: #d1d5db;
+    --color-gray-4: #9ca3af;
+    --color-gray-5: #6b7280;
+    --color-gray-6: #4b5563;
+    --color-gray-7: #374151;
+    --color-gray-8: #1f2937;
+    --color-gray-9: #111827;
+    /* Spacing: gaps, margin, padding, etc. */
+    --spacing-xxs: 0.15625em;
+    --spacing-xs: 0.3125em;
+    --spacing-sm: 0.625em;
+    --spacing-md: 1.25em;
+    --spacing-lg: 2.5em;
+    --spacing-xl: 3.75em;
+    --spacing-2xl: 4.25em;
+    --spacing-3xl: 4.75em;
+    /* Font Families */
+    --font-body: sans-serif;
+    /* Font Sizes */
+    --font-xs: 0.75em;
+    --font-sm: 0.875em;
+    --font-md: 1em;
+    --font-lg: 1.125em;
+    --font-xl: 1.25em;
+    --font-2xl: 1.5em;
+    --font-3xl: 1.875em;
+    --font-4xl: 2.25em;
+    --font-5xl: 3em;
+    /* Font Weights */
+    --font-thin: 100;
+    --font-extralight: 200;
+    --font-light: 300;
+    --font-normal: 400;
+    --font-medium: 500;
+    --font-semibold: 600;
+    --font-bold: 700;
+    --font-extrabold: 800;
+    --font-black: 900;
+    /* Line Heights */
+    --leading-none: 1;
+    --leading-tight: 1.25;
+    --leading-snug: 1.375;
+    --leading-normal: 1.5;
+    --leading-relaxed: 1.625;
+    --leading-loose: 2;
+    --leading-3: '.75em';
+    --leading-4: '1em';
+    --leading-5: '1.25em';
+    --leading-6: '1.5em';
+    --leading-7: '1.75em';
+    --leading-8: '2em';
+    --leading-9: '2.25em';
+    --leading-10: '2.5em';
+}
+
+.ds-widgets input[type='checkbox'] {
+    font-size: 80%;
+    margin: 0;
+    top: 0;
+}
+
+.block-display {
+    display: block;
+}
+
+.loading-spinner-on-mobile {
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+}
+
+.first\:ml-0:first-child {
+    margin-left: 0px;
+}
+
+.hover\:cursor-pointer:hover {
+    cursor: pointer;
+}
+
+.hover\:border-\[1\.5px\]:hover {
+    border-width: 1.5px;
+}
+
+.hover\:border-none:hover {
+    border-style: none;
+}
+
+.hover\:bg-gray-100:hover {
+    background-color: var(--color-gray-1);
+}
+
+.hover\:bg-green-100:hover {
+    --tw-bg-opacity: 1;
+    background-color: rgb(220 252 231 / var(--tw-bg-opacity));
+}
+
+.hover\:bg-transparent:hover {
+    background-color: transparent;
+}
+
+.hover\:text-blue-600:hover {
+    --tw-text-opacity: 1;
+    color: rgb(37 99 235 / var(--tw-text-opacity));
+}
+
+.hover\:text-gray-900:hover {
+    color: var(--color-gray-9);
+}
+
+.hover\:text-primary:hover {
+    color: var(--color-primary);
+}
+
+.hover\:no-underline:hover {
+    text-decoration-line: none;
+}
+
+.hover\:shadow-lg:hover {
+    --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1),
+        0 4px 6px -4px rgb(0 0 0 / 0.1);
+    --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color),
+        0 4px 6px -4px var(--tw-shadow-color);
+    box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
+        var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+}
+
+.hover\:outline-gray-600:hover {
+    outline-color: var(--color-gray-6);
+}
+
+.hover\:outline-gray-800:hover {
+    outline-color: var(--color-gray-8);
+}
+
+.focus\:border-none:focus {
+    border-style: none;
+}
+
+.focus\:bg-transparent:focus {
+    background-color: transparent;
+}
+
+.focus\:no-underline:focus {
+    text-decoration-line: none;
+}
+
+.focus\:outline-none:focus {
+    outline: 2px solid transparent;
+    outline-offset: 2px;
+}
+
+.focus\:ring-0:focus {
+    --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
+        var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+    --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
+        calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+    box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
+        var(--tw-shadow, 0 0 #0000);
+}
+
+.focus\:ring-2:focus {
+    --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
+        var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+    --tw-ring-shadow: var(--tw-ring-inset) 0 0 0
+        calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+    box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
+        var(--tw-shadow, 0 0 #0000);
+}
+
+.focus\:ring-green-600:focus {
+    --tw-ring-opacity: 1;
+    --tw-ring-color: rgb(22 163 74 / var(--tw-ring-opacity));
+}
+
+.focus\:ring-offset-2:focus {
+    --tw-ring-offset-width: 2px;
+}
+
+.focus\:ring-offset-green-50:focus {
+    --tw-ring-offset-color: #f0fdf4;
+}
+
+.active\:border-none:active {
+    border-style: none;
+}
+
+.active\:bg-transparent:active {
+    background-color: transparent;
+}
+
+.active\:no-underline:active {
+    text-decoration-line: none;
+}
+
+.active\:shadow-none:active {
+    --tw-shadow: 0 0 #0000;
+    --tw-shadow-colored: 0 0 #0000;
+    box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
+        var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+}
+
+.group:hover .group-hover\:opacity-100 {
+    opacity: 1;
+}
+
+@media (min-width: 640px) {
+    .sm\:flex {
+        display: flex;
+    }
+
+    .sm\:grid-cols-2 {
+        grid-template-columns: repeat(2, minmax(0, 1fr));
+    }
+
+    .sm\:px-6 {
+        padding-left: 1.5rem;
+        padding-right: 1.5rem;
+    }
+
+    .sm\:pb-24 {
+        padding-bottom: 6rem;
+    }
+
+    .sm\:pb-6 {
+        padding-bottom: 1.5rem;
+    }
+}
+
+@media (min-width: 768px) {
+    .md\:ml-6 {
+        margin-left: 1.5rem;
+    }
+
+    .md\:flex {
+        display: flex;
+    }
+
+    .md\:grid-cols-3 {
+        grid-template-columns: repeat(3, minmax(0, 1fr));
+    }
+
+    .md\:justify-between {
+        justify-content: space-between;
+    }
+}
+
+@media (min-width: 1024px) {
+    .lg\:w-full {
+        width: 100%;
+    }
+
+    .lg\:max-w-7xl {
+        max-width: 80rem;
+    }
+
+    .lg\:max-w-full {
+        max-width: 100%;
+    }
+
+    .lg\:px-8 {
+        padding-left: 2rem;
+        padding-right: 2rem;
+    }
+}
+
+@media (min-width: 1280px) {
+    .xl\:gap-x-4 {
+        -moz-column-gap: 1rem;
+        column-gap: 1rem;
+    }
+
+    .xl\:gap-x-8 {
+        -moz-column-gap: 2rem;
+        column-gap: 2rem;
+    }
+}
+
+@media (prefers-color-scheme: dark) {
+    .dark\:bg-gray-700 {
+        background-color: var(--color-gray-7);
+    }
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/styles/searchBar.module.css b/packages/extensions/venia-pwa-live-search/src/styles/searchBar.module.css
new file mode 100644
index 0000000000..d5633a3797
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/styles/searchBar.module.css
@@ -0,0 +1,119 @@
+.root {
+    composes: items-center from global;
+    composes: justify-items-center from global;
+    composes: justify-self-center from global;
+    composes: max-w-site from global;
+    composes: px-xs from global;
+    composes: py-0 from global;
+    composes: w-full from global;
+
+    @apply hidden;
+}
+
+.root_open {
+    composes: root;
+
+    composes: z-dropdown from global;
+    @apply grid;
+}
+
+.form {
+    composes: grid from global;
+    composes: items-center from global;
+    composes: justify-items-stretch from global;
+    composes: w-full from global;
+}
+
+.container {
+    composes: inline-flex from global;
+    composes: items-center from global;
+    composes: justify-center from global;
+    composes: max-w-[24rem] from global;
+    composes: pb-xs from global;
+    composes: relative from global;
+    composes: w-full from global;
+}
+
+.search {
+    composes: grid from global;
+    composes: relative from global;
+}
+
+.autocomplete {
+    composes: grid from global;
+    /* composes: relative from global; */
+    composes: z-menu from global;
+}
+
+.popover {
+    composes: absolute from global;
+    composes: bg-white from global;
+    composes: gap-3 from global;
+    composes: grid from global;
+    composes: left-0 from global;
+    composes: p-xs from global;
+    composes: rounded-b-md from global;
+    composes: rounded-t-none from global;
+    composes: shadow-inputFocus from global;
+    composes: text-sm from global;
+    composes: z-menu from global;
+    transition-property: opacity, transform, visibility;
+    top: 2.5rem;
+}
+
+.root_hidden {
+    composes: root;
+
+    composes: invisible from global;
+    composes: opacity-0 from global;
+    transform: translate3d(0, -2rem, 0);
+    transition-duration: 192ms;
+    transition-timing-function: var(--venia-global-anim-out);
+}
+
+.root_visible {
+    composes: root;
+
+    composes: opacity-100 from global;
+    composes: visible from global;
+    transform: translate3d(0, 0, 0);
+    transition-duration: 224ms;
+    transition-timing-function: var(--venia-global-anim-in);
+}
+
+.message {
+    composes: px-3 from global;
+    composes: py-0 from global;
+    composes: text-center from global;
+    composes: text-subtle from global;
+
+    composes: empty_hidden from global;
+}
+
+.suggestions {
+    composes: gap-2xs from global;
+    composes: grid from global;
+
+    composes: empty_hidden from global;
+}
+
+.product-price {
+    display: grid;
+    grid-area: product-price;
+    height: 100%;
+    justify-content: left !important;
+    width: 100%;
+}
+
+.livesearch_root .ds-sdk-add-to-cart-button button svg {
+    display: none !important;
+}
+
+.search input {
+    padding-left: calc(1.875rem * var(--iconsBefore, 0) + 0.625rem);
+    padding-right: calc(1.875rem * var(--iconsAfter, 0) + 0.625rem);
+}
+
+/* .popover {
+
+} */
diff --git a/packages/extensions/venia-pwa-live-search/src/styles/tokens.css b/packages/extensions/venia-pwa-live-search/src/styles/tokens.css
new file mode 100644
index 0000000000..c17957bc94
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/styles/tokens.css
@@ -0,0 +1,99 @@
+/* Tokens */
+.ds-widgets {
+    @import 'tailwindcss/base';
+    @import 'tailwindcss/components';
+    @import 'tailwindcss/utilities';
+
+    font-size: 1.6rem;
+
+    /* Colors */
+    --color-body: #fff;
+    --color-on-body: #222;
+
+    --color-surface: #e6e6e6;
+    --color-on-surface: #222;
+
+    --color-primary: #222;
+    --color-on-primary: #fff;
+
+    --color-secondary: #ff0000;
+    --color-on-secondary: #fff;
+
+    --color-gray-1: #f3f4f6;
+    --color-gray-2: #e5e7eb;
+    --color-gray-3: #d1d5db;
+    --color-gray-4: #9ca3af;
+    --color-gray-5: #6b7280;
+    --color-gray-6: #4b5563;
+    --color-gray-7: #374151;
+    --color-gray-8: #1f2937;
+    --color-gray-9: #111827;
+
+    /* Spacing: gaps, margin, padding, etc. */
+    --spacing-xxs: 0.15625em;
+    --spacing-xs: 0.3125em;
+    --spacing-sm: 0.625em;
+    --spacing-md: 1.25em;
+    --spacing-lg: 2.5em;
+    --spacing-xl: 3.75em;
+    --spacing-2xl: 4.25em;
+    --spacing-3xl: 4.75em;
+
+    /* Font Families */
+    --font-body: sans-serif;
+
+    /* Font Sizes */
+    --font-xs: 0.75em;
+    --font-sm: 0.875em;
+    --font-md: 1em;
+    --font-lg: 1.125em;
+    --font-xl: 1.25em;
+    --font-2xl: 1.5em;
+    --font-3xl: 1.875em;
+    --font-4xl: 2.25em;
+    --font-5xl: 3em;
+
+    /* Font Weights */
+    --font-thin: 100;
+    --font-extralight: 200;
+    --font-light: 300;
+    --font-normal: 400;
+    --font-medium: 500;
+    --font-semibold: 600;
+    --font-bold: 700;
+    --font-extrabold: 800;
+    --font-black: 900;
+
+    /* Line Heights */
+    --leading-none: 1;
+    --leading-tight: 1.25;
+    --leading-snug: 1.375;
+    --leading-normal: 1.5;
+    --leading-relaxed: 1.625;
+    --leading-loose: 2;
+    --leading-3: '.75em';
+    --leading-4: '1em';
+    --leading-5: '1.25em';
+    --leading-6: '1.5em';
+    --leading-7: '1.75em';
+    --leading-8: '2em';
+    --leading-9: '2.25em';
+    --leading-10: '2.5em';
+}
+
+.ds-widgets input[type='checkbox'] {
+    font-size: 80%;
+    margin: 0;
+    top: 0;
+}
+
+.block-display {
+    display: block;
+}
+
+.loading-spinner-on-mobile {
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+}
diff --git a/packages/extensions/venia-pwa-live-search/src/targets/intercept.js b/packages/extensions/venia-pwa-live-search/src/targets/intercept.js
new file mode 100644
index 0000000000..4366dc342c
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/targets/intercept.js
@@ -0,0 +1,14 @@
+module.exports = targets => {
+    const { Targetables } = require('@magento/pwa-buildpack');
+
+    const targetables = Targetables.using(targets);
+
+    targetables.setSpecialFeatures('esModules');
+
+    targets.of('@magento/peregrine').talons.tap(talons => {
+        talons.App.useApp.wrapWith(
+            `@magento/venia-pwa-live-search/src/wrappers/wrapUseApp`
+        );
+        return talons;
+    });
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/constants.js b/packages/extensions/venia-pwa-live-search/src/utils/constants.js
new file mode 100644
index 0000000000..b5392a26b2
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/constants.js
@@ -0,0 +1,26 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+export const DEFAULT_PAGE_SIZE = 24;
+export const DEFAULT_PAGE_SIZE_OPTIONS = '12,24,36';
+export const DEFAULT_MIN_QUERY_LENGTH = 3;
+export const PRODUCT_COLUMNS = {
+    desktop: 4,
+    tablet: 3,
+    mobile: 2
+};
+
+export const SEARCH_SORT_DEFAULT = [
+    { attribute: 'relevance', direction: 'DESC' }
+];
+export const CATEGORY_SORT_DEFAULT = [
+    { attribute: 'position', direction: 'ASC' }
+];
+
+export const SEARCH_UNIT_ID = 'livesearch-plp';
+export const BOOLEAN_YES = 'yes';
+export const BOOLEAN_NO = 'no';
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/decodeHtmlString.js b/packages/extensions/venia-pwa-live-search/src/utils/decodeHtmlString.js
new file mode 100644
index 0000000000..978a89d530
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/decodeHtmlString.js
@@ -0,0 +1,13 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+const decodeHtmlString = input => {
+    const doc = new DOMParser().parseFromString(input, 'text/html');
+    return doc.documentElement.textContent;
+};
+
+export { decodeHtmlString };
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/dom.js b/packages/extensions/venia-pwa-live-search/src/utils/dom.js
new file mode 100644
index 0000000000..846e9654b3
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/dom.js
@@ -0,0 +1,14 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+export const moveToTop = () => {
+    window.scrollTo({ top: 0 });
+};
+
+export const classNames = (...classes) => {
+    return classes.filter(Boolean).join(' ');
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/eventing/getCookie.js b/packages/extensions/venia-pwa-live-search/src/utils/eventing/getCookie.js
new file mode 100644
index 0000000000..98e58b564a
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/eventing/getCookie.js
@@ -0,0 +1,9 @@
+export const getDecodedCookie = key => {
+    const encodedCookie = document.cookie
+        .split('; ')
+        .find(row => row.startsWith(key))
+        .split('=')[1];
+    const decodedCookie = decodeURIComponent(encodedCookie);
+    const value = JSON.parse(decodedCookie);
+    return value;
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/eventing/usePageTypeFromUrl.js b/packages/extensions/venia-pwa-live-search/src/utils/eventing/usePageTypeFromUrl.js
new file mode 100644
index 0000000000..34f8042974
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/eventing/usePageTypeFromUrl.js
@@ -0,0 +1,26 @@
+// src/hooks/eventing/usePageTypeFromUrl.js
+import { useQuery } from '@apollo/client';
+import query from '../../queries/eventing/getPageType.gql';
+
+const pagetypeMap = {
+    CMS_PAGE: 'CMS',
+    CATEGORY: 'Category',
+    PRODUCT: 'Product',
+    '/cart': 'Cart',
+    '/checkout': 'Checkout'
+};
+
+const usePageTypeFromUrl = pathname => {
+    const { data } = useQuery(query.resolvePagetypeQuery, {
+        fetchPolicy: 'cache-and-network',
+        nextFetchPolicy: 'cache-first',
+        variables: { url: pathname }
+    });
+
+    const type = data?.urlResolver?.type;
+    const pageType = pagetypeMap[type] || pagetypeMap[pathname];
+
+    return pageType;
+};
+
+export default usePageTypeFromUrl;
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/getProductImage.js b/packages/extensions/venia-pwa-live-search/src/utils/getProductImage.js
new file mode 100644
index 0000000000..7a708bb2e0
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/getProductImage.js
@@ -0,0 +1,94 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+const getProductImageURLs = (images, amount = 3, topImageUrl) => {
+    const imageUrlArray = [];
+    //const url = new URL(window.location.href);
+    //original protocol
+    //const protocol = url.protocol;
+
+    //making protocol empty
+    //const protocol = '';
+    // const topImageUrl = "http://master-7rqtwti-wdxwuaerh4gbm.eu-4.magentosite.cloud/media/catalog/product/3/1/31t0a-sopll._ac_.jpg";
+    for (const image of images) {
+        const imageUrl = image.url?.replace(/^https?:\/\//, '');
+        if (imageUrl) {
+            //original
+            //imageUrlArray.push(`${protocol}//${imageUrl}`);
+
+            //to remove protocol
+            imageUrlArray.push(`${imageUrl}`);
+        }
+    }
+
+    if (topImageUrl) {
+        //original
+        // const topImageUrlFormatted = `${protocol}//${topImageUrl.replace(
+        //     /^https?:\/\//,
+        //     ''
+        // )}`;
+
+        //to remove protocol
+        const topImageUrlFormatted = `${topImageUrl.replace(
+            /^https?:\/\//,
+            ''
+        )}`;
+
+        const index = topImageUrlFormatted.indexOf(topImageUrlFormatted);
+        if (index > -1) {
+            imageUrlArray.splice(index, 1);
+        }
+
+        imageUrlArray.unshift(topImageUrlFormatted);
+    }
+
+    return imageUrlArray.slice(0, amount);
+};
+
+const resolveImageUrl = (url, opts) => {
+    const [base, query] = url.split('?');
+    const params = new URLSearchParams(query);
+
+    Object.entries(opts).forEach(([key, value]) => {
+        if (value !== undefined && value !== null) {
+            params.set(key, String(value));
+        }
+    });
+
+    return `${base}?${params.toString()}`;
+};
+
+const generateOptimizedImages = (imageUrls, baseImageWidth) => {
+    const baseOptions = {
+        fit: 'cover',
+        crop: false,
+        dpi: 1
+    };
+
+    const imageUrlArray = [];
+
+    for (const imageUrl of imageUrls) {
+        const src = resolveImageUrl(imageUrl, {
+            ...baseOptions,
+            width: baseImageWidth
+        });
+        const dpiSet = [1, 2, 3];
+        const srcset = dpiSet.map(dpi => {
+            return `${resolveImageUrl(imageUrl, {
+                ...baseOptions,
+                auto: 'webp',
+                quality: 80,
+                width: baseImageWidth * dpi
+            })} ${dpi}x`;
+        });
+        imageUrlArray.push({ src, srcset });
+    }
+
+    return imageUrlArray;
+};
+
+export { generateOptimizedImages, getProductImageURLs };
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/getProductPrice.js b/packages/extensions/venia-pwa-live-search/src/utils/getProductPrice.js
new file mode 100644
index 0000000000..3d01b9611d
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/getProductPrice.js
@@ -0,0 +1,83 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+import getSymbolFromCurrency from 'currency-symbol-map';
+
+const getProductPrice = (
+    product,
+    currencySymbol,
+    currencyRate,
+    useMaximum = false,
+    useFinal = false
+) => {
+    let priceType;
+    let price;
+    if ('product' in product) {
+        priceType = product?.product?.price_range?.minimum_price;
+
+        if (useMaximum) {
+            priceType = product?.product?.price_range?.maximum_price;
+        }
+
+        price = priceType?.regular_price;
+        if (useFinal) {
+            price = priceType?.final_price;
+        }
+    } else {
+        //getting error because the nullish coalescing operator (??) isn't supported by your Babel/Webpack setup yet.
+        // priceType =
+        //   product?.refineProduct?.priceRange?.minimum ??
+        //   product?.refineProduct?.price;
+
+        //workaround
+        priceType =
+            product &&
+            product.refineProduct &&
+            product.refineProduct.priceRange &&
+            product.refineProduct.priceRange.minimum
+                ? product.refineProduct.priceRange.minimum
+                : product &&
+                  product.refineProduct &&
+                  product.refineProduct.price
+                ? product.refineProduct.price
+                : undefined;
+
+        if (useMaximum) {
+            priceType = product?.refineProduct?.priceRange?.maximum;
+        }
+
+        price = priceType?.regular?.amount;
+        if (useFinal) {
+            price = priceType?.final?.amount;
+        }
+    }
+
+    // if currency symbol is configurable within Commerce, that symbol is used
+    let currency = price?.currency;
+
+    if (currencySymbol) {
+        currency = currencySymbol;
+    } else {
+        //getting error because the nullish coalescing operator (??) isn't supported by your Babel/Webpack setup yet.
+        //currency = getSymbolFromCurrency(currency) ?? '$';
+
+        // work around
+        currency =
+            getSymbolFromCurrency(currency) !== undefined &&
+            getSymbolFromCurrency(currency) !== null
+                ? getSymbolFromCurrency(currency)
+                : '$';
+    }
+
+    const convertedPrice = currencyRate
+        ? price?.value * parseFloat(currencyRate)
+        : price?.value;
+
+    return convertedPrice ? `${currency}${convertedPrice.toFixed(2)}` : '';
+};
+
+export { getProductPrice };
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/getUserViewHistory.js b/packages/extensions/venia-pwa-live-search/src/utils/getUserViewHistory.js
new file mode 100644
index 0000000000..997b6ef05d
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/getUserViewHistory.js
@@ -0,0 +1,27 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+const getUserViewHistory = () => {
+    const userViewHistory = localStorage?.getItem('ds-view-history-time-decay')
+        ? JSON.parse(localStorage.getItem('ds-view-history-time-decay'))
+        : null;
+
+    if (userViewHistory && Array.isArray(userViewHistory)) {
+        // https://git.corp.adobe.com/magento-datalake/magento2-snowplow-js/blob/main/src/utils.js#L177
+        // this shows localStorage is guaranteed sorted by unique by most recent timestamp as last index.
+
+        // MSRCH-2740: send the top 200 most recently viewed unique SKUs
+        return userViewHistory.slice(-200).map(v => ({
+            sku: v.sku,
+            dateTime: v.date
+        }));
+    }
+
+    return [];
+};
+
+export { getUserViewHistory };
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/handleUrlFilters.js b/packages/extensions/venia-pwa-live-search/src/utils/handleUrlFilters.js
new file mode 100644
index 0000000000..a40e661587
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/handleUrlFilters.js
@@ -0,0 +1,164 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+// Luma Specific URL handling
+import { DEFAULT_PAGE_SIZE } from '../utils/constants';
+
+const nonFilterKeys = {
+    search: 'q',
+    search_query: 'search_query',
+    pagination: 'p',
+    sort: 'product_list_order',
+    page_size: 'page_size'
+};
+
+const addUrlFilter = filter => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    const attribute = filter.attribute;
+    if (filter.range) {
+        const filt = filter.range;
+        if (getValueFromUrl(attribute)) {
+            params.delete(attribute);
+            params.append(attribute, `${filt.from}--${filt.to}`);
+        } else {
+            params.append(attribute, `${filt.from}--${filt.to}`);
+        }
+    } else {
+        const filt = filter.in || [];
+        const filterParams = params.getAll(attribute);
+        filt.map(f => {
+            if (!filterParams.includes(f)) {
+                params.append(attribute, f);
+            }
+        });
+    }
+    setWindowHistory(url.pathname, params);
+};
+
+const removeUrlFilter = (name, option) => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    const allValues = url.searchParams.getAll(name);
+    params.delete(name);
+    if (option) {
+        allValues.splice(allValues.indexOf(option), 1);
+        allValues.forEach(val => params.append(name, val));
+    }
+    setWindowHistory(url.pathname, params);
+};
+
+const removeAllUrlFilters = () => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    for (const key of url.searchParams.keys()) {
+        if (!Object.values(nonFilterKeys).includes(key)) {
+            params.delete(key);
+        }
+    }
+    setWindowHistory(url.pathname, params);
+};
+
+const handleUrlSort = sortOption => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    params.set('product_list_order', sortOption);
+    setWindowHistory(url.pathname, params);
+};
+
+const handleViewType = viewType => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    params.set('view_type', viewType);
+    setWindowHistory(url.pathname, params);
+};
+
+const handleUrlPageSize = pageSizeOption => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    if (pageSizeOption === DEFAULT_PAGE_SIZE) {
+        params.delete('page_size');
+    } else {
+        params.set('page_size', pageSizeOption.toString());
+    }
+    setWindowHistory(url.pathname, params);
+};
+
+const handleUrlPagination = pageNumber => {
+    const url = new URL(window.location.href);
+    const params = new URLSearchParams(url.searchParams);
+    if (pageNumber === 1) {
+        params.delete('p');
+    } else {
+        params.set('p', pageNumber.toString());
+    }
+    setWindowHistory(url.pathname, params);
+};
+
+const getFiltersFromUrl = filterableAttributes => {
+    const params = getSearchParams();
+
+    const filters = [];
+    for (const [key, value] of params.entries()) {
+        if (
+            filterableAttributes.includes(key) &&
+            !Object.values(nonFilterKeys).includes(key)
+        ) {
+            if (value.includes('--')) {
+                const range = value.split('--');
+                const filter = {
+                    attribute: key,
+                    range: { from: Number(range[0]), to: Number(range[1]) }
+                };
+                filters.push(filter);
+            } else {
+                const attributeIndex = filters.findIndex(
+                    filter => filter.attribute == key
+                );
+                if (attributeIndex !== -1) {
+                    filters[attributeIndex].in.push(value);
+                } else {
+                    const filter = { attribute: key, in: [value] };
+                    filters.push(filter);
+                }
+            }
+        }
+    }
+
+    return filters;
+};
+
+const getValueFromUrl = param => {
+    const params = getSearchParams();
+    const filter = params.get(param);
+    return filter || '';
+};
+
+const getSearchParams = () => {
+    const search = window.location.search;
+    return new URLSearchParams(search);
+};
+
+const setWindowHistory = (pathname, params) => {
+    if (params.toString() === '') {
+        window.history.pushState({}, '', `${pathname}`);
+    } else {
+        window.history.pushState({}, '', `${pathname}?${params.toString()}`);
+    }
+};
+
+export {
+    addUrlFilter,
+    getFiltersFromUrl,
+    getValueFromUrl,
+    handleUrlPageSize,
+    handleUrlPagination,
+    handleUrlSort,
+    handleViewType,
+    removeAllUrlFilters,
+    removeUrlFilter
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/htmlStringDecode.js b/packages/extensions/venia-pwa-live-search/src/utils/htmlStringDecode.js
new file mode 100644
index 0000000000..598408f6ae
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/htmlStringDecode.js
@@ -0,0 +1,13 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+const htmlStringDecode = input => {
+    const doc = new DOMParser().parseFromString(input, 'text/html');
+    return doc.documentElement.textContent;
+};
+
+export { htmlStringDecode };
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/modifyResults.js b/packages/extensions/venia-pwa-live-search/src/utils/modifyResults.js
new file mode 100644
index 0000000000..54bf08f902
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/modifyResults.js
@@ -0,0 +1,164 @@
+// Copyright 2024 Adobe
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying
+// it.
+
+// Clean a URL based on provided baseUrl(s)
+export const cleanUrl = (
+    url,
+    cleanWithProtocol = false,
+    baseUrl = '',
+    baseUrlWithoutProtocol = ''
+) => {
+    if (!url) return url;
+
+    try {
+        if (cleanWithProtocol) {
+            return baseUrl ? url.replace(baseUrl, '') : url;
+        }
+        return baseUrlWithoutProtocol
+            ? url.replace(baseUrlWithoutProtocol, '')
+            : url;
+    } catch {
+        return url;
+    }
+};
+
+export const cleanSwatchUrl = (
+    url,
+    cleanWithProtocol = true,
+    baseUrl = '',
+    baseUrlWithoutProtocol = ''
+) => {
+    if (!url) return url;
+
+    try {
+        if (cleanWithProtocol) {
+            if (baseUrl.endsWith('/')) {
+                const sanitizeBaseUrl = baseUrl.replace(/\/$/, '');
+                return sanitizeBaseUrl ? url.replace(sanitizeBaseUrl, '') : url;
+            }
+            return baseUrl ? url.replace(baseUrl, '') : url;
+        }
+        return baseUrlWithoutProtocol
+            ? url.replace(baseUrlWithoutProtocol, '')
+            : url;
+    } catch {
+        return url;
+    }
+};
+
+export const sanitizeImage = (
+    img,
+    cleanWithProtocol = false,
+    baseUrl,
+    baseUrlWithoutProtocol
+) => {
+    if (Array.isArray(img)) {
+        return img.map(i =>
+            i && i.url
+                ? {
+                      ...i,
+                      url: cleanUrl(
+                          i.url,
+                          cleanWithProtocol,
+                          baseUrl,
+                          baseUrlWithoutProtocol
+                      )
+                  }
+                : i
+        );
+    }
+    return img && img.url
+        ? {
+              ...img,
+              url: cleanUrl(
+                  img.url,
+                  cleanWithProtocol,
+                  baseUrl,
+                  baseUrlWithoutProtocol
+              )
+          }
+        : img;
+};
+
+export const sanitizeRefinedImages = (
+    refinedImages,
+    baseUrl,
+    baseUrlWithoutProtocol,
+    areSwatchImages = false
+) => {
+    if (!refinedImages || !Array.isArray(refinedImages)) return refinedImages;
+
+    return refinedImages.map(img => {
+        if (!img || !img.url) return img;
+
+        const cleanImageUrl = areSwatchImages
+            ? cleanSwatchUrl(img.url, true, baseUrl, baseUrlWithoutProtocol)
+            : cleanUrl(img.url, false, baseUrl, baseUrlWithoutProtocol);
+
+        return {
+            ...img,
+            url: cleanImageUrl
+        };
+    });
+};
+
+export const sanitizeProducts = (products, baseUrl, baseUrlWithoutProtocol) => {
+    if (!products || products.length === 0) return [];
+
+    return products.map(item => {
+        const prod = item.product;
+        const prodView = item.productView;
+
+        if (!prod) return item;
+
+        return {
+            ...item,
+            product: {
+                ...prod,
+                canonical_url: cleanUrl(
+                    prod.canonical_url,
+                    false,
+                    baseUrl,
+                    baseUrlWithoutProtocol
+                ),
+                image: sanitizeImage(
+                    prod.image,
+                    false,
+                    baseUrl,
+                    baseUrlWithoutProtocol
+                ),
+                small_image: sanitizeImage(
+                    prod.small_image,
+                    false,
+                    baseUrl,
+                    baseUrlWithoutProtocol
+                ),
+                thumbnail: sanitizeImage(
+                    prod.thumbnail,
+                    false,
+                    baseUrl,
+                    baseUrlWithoutProtocol
+                )
+            },
+            productView: {
+                ...prodView,
+                images: sanitizeImage(
+                    prodView?.images,
+                    true,
+                    baseUrl,
+                    baseUrlWithoutProtocol
+                ),
+                url: cleanUrl(
+                    prodView?.url,
+                    true,
+                    baseUrl,
+                    baseUrlWithoutProtocol
+                )
+            }
+        };
+    });
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/sort.js b/packages/extensions/venia-pwa-live-search/src/utils/sort.js
new file mode 100644
index 0000000000..7361d6a623
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/sort.js
@@ -0,0 +1,95 @@
+/*
+Copyright 2024 Adobe
+All Rights Reserved.
+
+NOTICE: Adobe permits you to use, modify, and distribute this file in
+accordance with the terms of the Adobe license agreement accompanying
+it.
+*/
+
+//hooks error - need to check
+//import { useTranslation } from '../context/translation';
+
+const defaultSortOptions = () => {
+    return [
+        { label: 'Most Relevant', value: 'relevance_DESC' },
+        { label: 'Price: Low to High', value: 'price_ASC' },
+        { label: 'Price: High to Low', value: 'price_DESC' }
+    ];
+};
+
+const getSortOptionsfromMetadata = (
+    sortMetadata,
+    displayOutOfStock,
+    categoryPath,
+    translation
+) => {
+    const sortOptions = categoryPath
+        ? [
+              {
+                  label: translation?.SortDropdown?.positionLabel || 'Position', // Now uses translation
+                  value: 'position_ASC'
+              }
+          ]
+        : [
+              {
+                  label:
+                      translation?.SortDropdown?.relevanceLabel ||
+                      'Most Relevant', // Now uses translation
+                  value: 'relevance_DESC'
+              }
+          ];
+
+    const displayInStockOnly = displayOutOfStock != '1'; // '!=' is intentional for conversion
+
+    if (sortMetadata && sortMetadata.length > 0) {
+        sortMetadata.forEach(e => {
+            if (
+                !e.attribute.includes('relevance') &&
+                !(e.attribute.includes('inStock') && displayInStockOnly) &&
+                !e.attribute.includes('position')
+                /* conditions for which we don't display the sorting option:
+                1) if the option attribute is relevance
+                2) if the option attribute is "inStock" and display out of stock products is set to no
+                3) if the option attribute is "position" and there is not a categoryPath (we're not in category browse mode) -> the conditional part is handled in setting sortOptions
+                */
+            ) {
+                if (e.numeric && e.attribute.includes('price')) {
+                    sortOptions.push({
+                        label: `${e.label}: Low to High`,
+                        value: `${e.attribute}_ASC`
+                    });
+                    sortOptions.push({
+                        label: `${e.label}: High to Low`,
+                        value: `${e.attribute}_DESC`
+                    });
+                } else {
+                    sortOptions.push({
+                        label: `${e.label}`,
+                        value: `${e.attribute}_DESC`
+                    });
+                }
+            }
+        });
+    }
+    return sortOptions;
+};
+
+const generateGQLSortInput = sortOption => {
+    // results sorted by relevance or position by default
+    if (!sortOption) {
+        return undefined;
+    }
+
+    // sort options are in format attribute_direction
+    const index = sortOption.lastIndexOf('_');
+    return [
+        {
+            attribute: sortOption.substring(0, index),
+            direction:
+                sortOption.substring(index + 1) === 'ASC' ? 'ASC' : 'DESC'
+        }
+    ];
+};
+
+export { defaultSortOptions, generateGQLSortInput, getSortOptionsfromMetadata };
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/useIntersectionObserver.js b/packages/extensions/venia-pwa-live-search/src/utils/useIntersectionObserver.js
new file mode 100644
index 0000000000..9788310dc6
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/useIntersectionObserver.js
@@ -0,0 +1,27 @@
+import { useEffect, useState } from 'react';
+
+export const useIntersectionObserver = (ref, options) => {
+    const { rootMargin } = options;
+    const [observerEntry, setObserverEntry] = useState(null);
+
+    useEffect(() => {
+        if (!ref?.current) return;
+        const observer = new IntersectionObserver(
+            ([entry]) => {
+                setObserverEntry(entry);
+                if (entry.isIntersecting) {
+                    observer.unobserve(entry.target);
+                }
+            },
+            { rootMargin }
+        );
+
+        observer.observe(ref.current);
+
+        return () => {
+            observer.disconnect();
+        };
+    }, [ref, rootMargin]);
+
+    return observerEntry;
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/utils/validateStoreDetails.js b/packages/extensions/venia-pwa-live-search/src/utils/validateStoreDetails.js
new file mode 100644
index 0000000000..6b07588dca
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/utils/validateStoreDetails.js
@@ -0,0 +1,39 @@
+const validStoreDetailsKeys = [
+    'environmentId',
+    'environmentType',
+    'websiteCode',
+    'storeCode',
+    'storeViewCode',
+    'config',
+    'context',
+    'apiUrl',
+    'apiKey',
+    'route',
+    'searchQuery',
+    'baseUrl',
+    'baseUrlwithoutProtocol'
+];
+
+export const sanitizeString = value => {
+    // just in case, https://stackoverflow.com/a/23453651
+    if (typeof value === 'string') {
+        // eslint-disable-next-line no-useless-escape
+        value = value.replace(/[^a-z0-9áéíóúñü \.,_-]/gim, '');
+        return value.trim();
+    }
+    return value;
+};
+
+export const validateStoreDetailsKeys = storeDetails => {
+    Object.keys(storeDetails).forEach(key => {
+        if (!validStoreDetailsKeys.includes(key)) {
+            // eslint-disable-next-line no-console
+            console.error(`Invalid key ${key} in StoreDetailsProps`);
+            // filter out invalid keys/value
+            delete storeDetails[key];
+            return;
+        }
+        storeDetails[key] = sanitizeString(storeDetails[key]);
+    });
+    return storeDetails;
+};
diff --git a/packages/extensions/venia-pwa-live-search/src/wrappers/wrapUseApp.js b/packages/extensions/venia-pwa-live-search/src/wrappers/wrapUseApp.js
new file mode 100644
index 0000000000..26a8a4e2b0
--- /dev/null
+++ b/packages/extensions/venia-pwa-live-search/src/wrappers/wrapUseApp.js
@@ -0,0 +1,28 @@
+//import useCustomUrl from '../hooks/useCustomUrl';
+//import useReferrerUrl from '../hooks/useReferrerUrl';
+import usePageView from '../hooks/eventing/usePageView';
+import useShopperContext from '../hooks/eventing/useShopperContext';
+import useStorefrontInstanceContext from '../hooks/eventing/useStorefrontInstanceContext';
+import useMagentoExtensionContext from '../hooks/eventing/useMagentoExtensionContext';
+//import useCart from '../hooks/useCart';
+import mse from '@adobe/magento-storefront-events-sdk';
+import msc from '@adobe/magento-storefront-event-collector';
+
+export default function wrapUseApp(origUseApp) {
+    if (!window.magentoStorefrontEvents) {
+        window.magentoStorefrontEvents = mse;
+    }
+    msc;
+
+    return function(props) {
+        useShopperContext();
+        useStorefrontInstanceContext();
+        useMagentoExtensionContext();
+        //useCart();
+        //useCustomUrl();
+        //useReferrerUrl();
+        usePageView();
+
+        return origUseApp(props);
+    };
+}