---
title: Use Coveo Search in the Salesforce Composable Storefront (PWA Kit)
slug: sal3s119
canonical_url: https://docs.coveo.com/en/sal3s119/
collection: coveo-for-commerce
source_format: adoc
---
# Use Coveo Search in the Salesforce Composable Storefront (PWA Kit)
The Salesforce Composable Storefront (also known as the PWA Kit) is built upon [React](https://reactjs.org/). [Coveo Atomic](https://docs.coveo.com/en/lcdf0264/) [supports React natively](https://docs.coveo.com/en/atomic/latest/usage/frameworks/atomic-react-wrapper), so it's the best practice to build a search UI in the Composable Storefront using the Atomic framework.
This article explains the steps required to do so.
> **Note**
>
> Instructions provided in this article apply only if you're using a Salesforce Commerce Cloud instance (previously known as Demandware).
## Create an app
. Clone the [Composable Storefront repo](https://github.com/SalesforceCommerceCloud/pwa-kit/) and go to the folder where you cloned it.
> **Note**
>
> Make sure you're using [Node.js](https://nodejs.org/) ^14.0.0.
. To create a demo app, run the following command in your terminal:
```bash
npx pwa-kit-create-app
```
This command will create a demo app for you.
During its execution, it will prompt you to choose the Commerce Cloud instance to use in the app.
For the sake of simplicity, you can choose `The Retail app with demo Commerce Cloud instance` to use a predefined cloud sandbox.
. Once the app has been created, go to the app folder:
```bash
cd pwa-kit-starter-project
```
## Adjust the app to use Coveo
. To use Atomic in your React project, update the package.json file with the following dependency:
```json
"dependencies": {
"@coveo/atomic-react": "^2.0.1",
"@coveo/headless": "^2.0.1"
}
```
> **Important**
>
> If this package throws errors while launching the app, you can try to eliminate them by changing the package version to the alpha version.
>
> To get the alpha version number, either visit the [Atomic React npm web page](https://www.npmjs.com/package/@coveo/atomic-react), or execute this command in the terminal: `npm view @coveo/atomic | grep alpha`.
. Run `npm install`.
> **Note**
>
> If the installation fails due to some dependencies requiring a more recent version of React, run the following command to upgrade React to that version.
> For example, if `React@>=18.0.0` is required, run:
>
> ```bash
npm install react@18.0.0 react-dom@18.0.0 --legacy-peer-deps
```
. Once all dependencies are installed, move the Atomic localization files to the `static` folder:
```bash
cp -r node_modules/@coveo/atomic-react/dist/lang app/static
```
. To adjust the server side rendering (SSR), open the `app/ssr.js` file and edit the `handler` function:
.. Find the directives section and add the following:
```bash
'connect-src': ["'self'", "'unsafe-eval'", 'analytics.cloud.coveo.com', 'platform.cloud.coveo.com', 'storage.googleapis.com']
```
.. Add a route for the default localization file:
```bash
app.get('/lang/en.json', runtime.serveStaticFile('static/lang/en.json'))
```
. To replace the default search, edit the `app/routes.jsx` file.
.. In the `Pages` section, add a new constant:
```javascript
const CoveoSearch = loadable(() => import('./pages/coveo-search'), {fallback});
```
.. In the `Routes` array, find the `/search` route and replace it with the following:
```javascript
{
path: '/search',
component: CoveoSearch
},
```
## Build a search UI
For its layouts, the Composable Storefront uses the [Chakra UI framework](https://chakra-ui.com/).
Combine the Chakra UI tags with the Atomic elements as shown in the code below.
. Create a `pages/coveo-search/index.jsx` file and paste the following code into it:
```javascript
import React from "react";
import PropTypes from "prop-types";
import {
loadFieldActions,
loadQueryActions,
loadSearchActions,
loadSearchAnalyticsActions
} from "@coveo/headless";
import { AtomicResultList } from "@coveo/atomic-react"; <1>
import {
Box,
Grid,
Stack,
Flex,
useMultiStyleConfig,
AspectRatio,
Text,
Link
} from "@chakra-ui/react";
import DynamicImage from "../../components/dynamic-image";
import { useIntl } from "react-intl";
import { productUrlBuilder } from "../../utils/url";
const CoveoSearch = () => {
const intl = useIntl();
const styles = useMultiStyleConfig("ProductTile");
return (
<>
<2>
(
<>
{/* Title */}
{r.raw.ec_name}
{/* Price */}
{
r.raw.ec_price
}
>
)}
/>
>
);
};
CoveoSearch.getTemplateName = () => "coveo-search";
CoveoSearch.shouldGetProps = ({ previousLocation, location }) => !previousLocation || previousLocation.pathname !== location.pathname || previousLocation.search !== location.search;
CoveoSearch.getProps = async ({ engine, location }) => {
const searchInterface = document.querySelector("atomic-search-interface");
const urlParams = new URLSearchParams(location.search);
let searchQuery = urlParams.get("q");
const newProps = { searchQuery };
if (!engine) {
const configuration = {
accessToken: "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
organizationId: "orgnameplaceholder"
}; <3>
await searchInterface.initialize(configuration);
newProps.engine = engine = searchInterface.engine;
const fieldActions = loadFieldActions(engine);
engine.dispatch(fieldActions.registerFieldsToInclude(
`ec_name,
ec_price,
ec_images,
ec_productid,
sf_c_currency,
sf_c_image,
sf_c_price,
title,
uri`.split(",")));
} <4>
// execute search
const searchActions = loadSearchActions(engine);
const queryActions = loadQueryActions(engine);
const analyticsActions = loadSearchAnalyticsActions(engine);
await engine.dispatch(queryActions.updateQuery({ q: searchQuery || "test" }));
const searchResults = await engine.dispatch(searchActions.executeSearch(analyticsActions.logSearchboxSubmit()));
newProps.searchResults = searchResults;
return newProps;
};
CoveoSearch.propTypes = {
engine: PropTypes.object,
isLoading: PropTypes.bool,
location: PropTypes.object,
searchQuery: PropTypes.string,
};
export default CoveoSearch;
```
<1> Imports one component from the `atomic-react` package.
Use as many components from this package as you want and combine them with pure HTML Atomic tags.
<2> Mounts the default Atomic theme.
Learn more about Atomic customization in [Themes and visual customization](https://docs.coveo.com/en/atomic/latest/usage/themes-and-visual-customization/).
<3> Specifies credentials for the target Coveo organization.
See [API key](https://docs.coveo.com/en/105/) and [search token](https://docs.coveo.com/en/56/) authentication.
<4> Retrieves the specified fields from the Coveo organization.
These fields are used throughout the UI layout, for example, in facets.
> **Important**
>
> To see the search results, make sure that your Coveo organization already has [data indexed from a Salesforce Commerce Cloud instance](https://docs.coveo.com/en/sal3s118/).
. To launch the application locally, run the `npm start` command.
The application will open in the browser, at the `+http://localhost:3000+` address by default.
. In the upper-right corner, you can see the search bar.
Try to type in "dress" or "shirt" and then select Enter to see the search results powered by Coveo.