What Is The Headless Engine?
Think of the Headless Engine as the engine of any care. Without it working, you're going nowhere fast. It takes care of and organizes the use of the API token, Organization ID and so forth.
So, when it comes to setting up an Engine for our Sitecore JSS Next.JS application any time we create a component such as a navigation menu search bar, we need an engine and its corresponding context to support all of the Coveo components that are used as part of it.
For the purposes of this article, we're going to use the example of a navigation menu search box as our Sitecore component.
Let's Set Up The Component
The whole Next.JS component itself is relatively simple. As part of this project setup, we have installed @coveo/headless
.
import { Field } from '@sitecore-jss/sitecore-jss-nextjs';
import { buildSearchEngine } from '@coveo/headless';
type EngineProps = {
organizationId: Field<string>;
searchHub: Field<string>;
accessToken: Field<string>;
};
export async function initializeHeadlessEngine(props: EngineProps) {
return buildSearchEngine({
configuration: {
platformUrl: 'https://platform.cloud.coveo.com',
organizationId: props.organizationId.value,
accessToken: props.accessToken.value,
},
});
}
I will point out that in the above example a few things are known and as such, a few shortcuts were taken.
- The API key being used has minimal privileges (i.e. search only),
- A
Search Hub
is assigned to the API key to restrict whichQuery Pipeline
is used and thus restrict its access further, - All content retrieved is already public information.
Set Up The Headless Engine Context
With the engine in place, we need a way to generate the context from which all other Coveo components will grab the engine context.
import { createContext } from 'react';
const HeadlessEngineContext = createContext< /> | undefined>(undefined);
export default HeadlessEngineContext;
Set Up The Menu Search Bar Component
With the Engine component in place, we can now set up the primary component that authors would place onto a page, or in our case, inside of a menu.
import React, { useEffect } from 'react';
import { Field, LinkField, withDatasourceCheck } from '@sitecore-jss/sitecore-jss-nextjs';
import { initializeHeadlessEngine } from './Components/Engine';
import { SearchEngine } from '@coveo/headless';
import { ComponentWithContextProps } from 'lib/component-props';
import { loadSearchHubActions } from '@coveo/headless';
import StandaloneSearchBox from './Components/StandaloneSearchBox';
import HeadlessEngineContext from './Components/HeadlessEngineContext';
type MenuSearchBarProps = ComponentWithContextProps & {
fields: {
organizationId: Field<string>;
searchHub: Field<string>;
accessToken: Field<string>;
searchPage: LinkField;
};
};
const MenuSearchBar = ({ fields }: MenuSearchBarProps): JSX.Element => {
// Grab the default engine state.
const [engine, setEngine] = React.useState<SearchEngine | null>(null);
useEffect(() => {
// Initialize our engine with our fields from Sitecore
initializeHeadlessEngine(fields).then((engine) => {
setEngine(engine);
// Set the search hub.
const { setSearchHub } = loadSearchHubActions(engine);
engine.dispatch(setSearchHub(fields.searchHub.value));
});
}, [fields]);
if (engine) {
return (
// Use the HeadlessEngineContext to store our engine data.
<HeadlessEngineContext.Provider value={engine}>
...
// All components go within here
...
</HeadlessEngineContext.Provider>
);
} else {
return <div>Waiting for engine</div>;
}
};
export default withDatasourceCheck()<MenuSearchBarProps>(MenuSearchBar);
With that in place, we can go forth and add in any components we need to build the menu search bar. Whether that be the search box itself or additional features like Query Suggestions.