---
title: Build search interfaces (CSR)
slug: p25a2501
canonical_url: https://docs.coveo.com/en/p25a2501/
collection: coveo-for-commerce
source_format: adoc
---
# Build search interfaces (CSR)
Building a search interface with Coveo Headless involves two main components: a search box and a search page.
Headless provides two types of search box controllers: [`SearchBox`](https://docs.coveo.com/en/headless/latest/reference/types/Commerce.SearchBox.html) and [`StandaloneSearchBox`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.StandaloneSearchBox.html).
It also offers a [`Search`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Search.html) controller to manage the search page and results.
* `SearchBox`: Use this controller to create a search box component in your search interface, submit queries, and display [query suggestions](https://docs.coveo.com/en/1015/).
This controller is used on the search page itself.
* `StandaloneSearchBox`: Use this controller to create a standalone search box that redirects to your search page.
This controller is used on every page of your app except the search page.
* `Search`: Use this controller to manage search results, such as facets, sorting, and pagination, ensuring a seamless user experience.
Complete examples are available in the [Headless repository](https://github.com/coveo/ui-kit/tree/master/packages/samples/headless-commerce-react/src/pages/search-page.tsx).
## Prerequisite
Make sure that you understand how to [build commerce search pages](https://docs.coveo.com/en/o4ue0200/).
## Creating a search box
To create a search box, use the `SearchBox` and `StandaloneSearchBox` controllers.
### Using the `SearchBox` controller
The following code snippet shows how to create a [`SearchBox`](https://docs.coveo.com/en/headless/latest/reference/types/Commerce.SearchBox.html) controller.
```tsx
import { engine } from './Engine';
import { buildSearchBox } from '@coveo/headless/commerce';
const searchBox = buildSearchBox(engine); <1>
```
<1> Build the `SearchBox` controller by passing in the [previously initialized engine](https://docs.coveo.com/en/o6r70022#initialize-the-headless-commerce-engine).
Next, create a search box component that uses the `SearchBox` controller.
```tsx
import { SearchBox as HeadlessSearchBox } from '@coveo/headless/commerce';
import { useEffect, useState } from 'react';
interface ISearchBoxProps {
controller: HeadlessSearchBox;
}
export default function SearchBox(props: ISearchBoxProps) {
const {controller} = props;
const [state, setState] = useState(controller.state);
useEffect(() => { <1>
controller.state.value && controller.clear();
controller.subscribe(() => setState(controller.state));
}, [controller]);
return (
);
}
```
<1> Subscribe to the state of the `SearchBox` controller.
This allows you to update the search box component when the state of the controller changes.
<2> Create an input field to allow users to enter their search queries.
As the user types in the search box, call the `updateText` method on the `SearchBox` controller to update the query.
<3> Display a clear button when the search box is not empty.
When the user clicks the clear button, call the `clear` method on the `SearchBox` controller to clear the search box.
<4> Render a search button that calls the `submit` method on the `SearchBox` controller to submit the query.
<5> Display query suggestions when the user types in the search box.
When the user clicks a suggestion, call the `selectSuggestion` method on the `SearchBox` controller to submit the selected suggestion.
This component can now be included in your search page.
#### Using the `StandaloneSearchBox` controller
In addition to creating a search box component, create a lightweight standalone search box component that utilizes the [`StandaloneSearchBox`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.StandaloneSearchBox.html) controller to redirect to your search page.
This component should be included on every page of your app except the search page.
Before creating the component, initialize the controller.
```tsx
import { engine } from './Engine';
import { buildStandaloneSearchBox } from '@coveo/headless/commerce';
const standaloneSearchBox = buildStandaloneSearchBox(engine, { <1>
options: {
redirectionUrl: '/search'
}
});
```
<1> Build the `StandaloneSearchBox` controller by passing in the previously initialized engine and the redirection URL to the search page.
When the user submits a query in this search box, the `state.redirectTo` is updated to `/search`.
This update can be detected by subscribing to the controller state and then used to redirect the user to the search page.
Next, create a component that uses this `StandaloneSearchBox` controller.
```tsx
import { StandaloneSearchBox as HeadlessStandaloneSearchBox } from '@coveo/headless/commerce';
import { useEffect, useState } from 'react';
interface IStandaloneSearchBoxProps {
navigate: (url: string) => void; <1>
controller: HeadlessStandaloneSearchBox;
}
export default function StandaloneSearchBox(props: IStandaloneSearchBoxProps) {
const {navigate, controller} = props;
const [state, setState] = useState(controller.state);
useEffect(() => { <2>
controller.state.value && controller.clear();
controller.subscribe(() => setState(controller.state));
}, [controller]);
useEffect(() => { <3>
if (state.redirectTo === '/search') {
navigate(`${state.redirectTo}#q=${state.value}`);
controller.afterRedirection();
} else if (state.redirectTo !== '') {
window.location.href = state.redirectTo;
}
}, [state.redirectTo, navigate, state.value, controller]);
return (
);
}
```
<1> Define a `navigate` function to redirect to the search page.
<2> Subscribe to the state of the `StandaloneSearchBox` controller.
<3> Redirect to the search page when the user submits a query and the `redirectTo` property of the controller is set to `/search`.
Call the `afterRedirection` method on the controller to reset the state after the redirection.
<4> Create an input field to allow users to enter their search queries.
<5> Display a clear button when the search box is not empty.
<6> Render a search button that calls the `submit` method on the `StandaloneSearchBox` controller to submit the query.
<7> Display query suggestions when the user types in the search box.
When the user clicks a suggestion, call the `selectSuggestion` method on the `StandaloneSearchBox` controller to submit the selected suggestion as a query.
A complete example, including a sample implementation of the standalone search box component, is available in the [Headless repository](https://github.com/coveo/ui-kit/tree/master/packages/samples/headless-commerce-react/src/components/standalone-search-box/standalone-search-box.tsx).
## Displaying the search page with the `Search` controller
In addition to rendering the search box, you must display the search results on the search page.
First, initialize the [`Search`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Search.html) controller.
```tsx
import { engine } from './Engine';
import { buildSearch } from '@coveo/headless/commerce';
const searchController = buildSearch(engine);
```
Next, use this controller in a component to render the search page.
```tsx
import {
Cart,
Search as HeadlessSearch,
ProductListing,
} from '@coveo/headless/commerce';
import { useState, useEffect } from 'react';
import FacetGenerator from '../../facets/facet-generator/facet-generator';
import Pagination from '../../pagination/pagination';
import ProductList from '../../product-list/product-list';
import Sort from '../../sort/sort';
interface ISearchAndListingInterface {
searchOrListingController: HeadlessSearch | ProductListing;
cartController: Cart;
navigate: (pathName: string) => void;
}
export default function SearchAndListingInterface(
props: ISearchAndListingInterface
) {
const {searchOrListingController, cartController, navigate} = props;
const [searchOrListingState, setSearchOrListingState] = useState(
searchOrListingController.state
);
useEffect(() => { <1>
searchOrListingController.subscribe(() =>
setSearchOrListingState(searchOrListingController.state)
);
}, [searchOrListingController]);
return (
);
}
```
<1> Subscribe to the state of the `Search` controller.
<2> [Display the facets generated by the `FacetGenerator` sub-controller](https://docs.coveo.com/en/o7vb0270/).
<3> [Display the sorting options generated by the `Sort` sub-controller](https://docs.coveo.com/en/o7vb0270/).
<4> [Render the list of `products` returned by the search](https://docs.coveo.com/en/o8ce0239/).
<5> [Display the pagination generated by the `Pagination` sub-controller](https://docs.coveo.com/en/o7vb0270/).
> **Note**
>
> The previous component can be re-used for both displaying and interacting with results from both search and listing pages.
A complete example of how to build a search page is available in the [Headless repository](https://github.com/coveo/ui-kit/tree/master/packages/samples/headless-commerce-react/src/components/use-cases/search-and-listing-interface/search-and-listing-interface.tsx).
Within the sample project, you can find additional components that were omitted in this article, such as the [`BreadcrumbManager`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Search.html#breadcrumbmanager) (displays a summary of the currently active facet values) and [`Summary`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Search.html#summary) (provides a summary of search results such as the number of results returned).