Add search to your site

Attention: This documentation is for an add-on. Make sure to read Using the Next.js Blog Starter first.

Next.js Search Starter for Agility CMS

We built a lightweight Search component you can customize and include in Next.js websites!

Check out the repo at https://github.com/agility/agilitycms-nextjs-starter-with-search for a fully built website starter. 


Adding to your existing Next.js website

If you want to add this to your existing project, copy the following from the repo mentioned above.

/app/components/common/Search.tsx

This is the UI component built with Algolia's super fast Autocomplete library

Include the following within your application

<Search />
<MobileSearch />

/app/api/routes/search/route.ts

This is the API endpoint that handles the search, and also a webhook for updating the search index. 


Setting up a webhook in Agility CMS

For instructions on adding a webhook to your Agility CMS instance, see this documentation.

To enable the updating of the search Index, setup a webhook in Agility for when content is saved and published to;

https://www.yourwebsite/api/search


Customizing the Search Index

By default the search index is mapped to our free trial starter content. You can customize as your liking by adjusting the following

As you can see in the example below, we do the following to pull out content we wish to populate our search index with. These should be customized to your component models. 

1. Map all the content zones
2. Map all the page components in those zones
3. Return all the content found as strings
4. Join all the strings together

const pageContent = Object.keys(data.page.zones).map((zoneKey) => {
	const zone = data.page.zones[zoneKey];

	return zone.map((module: any) => {

		let response = '';
		if(module.module === 'PostDetails'){
			response = data.contentItem.fields.content
		}

		if(module.module === 'RichTextArea'){
			response = module.item.fields.textblob
		}

		if(module.module === 'TextBlockWithImage'){
			response = module.item.fields.content
		}

		const strippedContent = response.replace(/<\/?[^>]+(>|$)/g, "").replace(/[\r\n]+/g, " ");
		if(strippedContent !== ''){
			return strippedContent;
		}

	}).join(' '); // Join modules into a single string
}).join(' '); // Join zones into a single string

Configuring FlexSearch

Depending on what exactly you want to be able to search, you can configure the FlexSearch document model as needed.

new FlexSearch.Document({
	tokenize: 'full',
	document: {
		id: "id",
		index: ["title", "content", "url"],
		store: ["title","content", "url"],
	},
	context: {
		resolution: 9,
		depth: 2,
		bidirectional: true,
	},
});

1. index: Defines which fields should be indexed for searching.

• When you perform a search, FlexSearch looks up terms in the fields listed under index.

• The fields in index will be processed and optimized for fast searching.

• Example: If index: ["title", "content", "url"], it means FlexSearch will analyze the title, content, and url fields and allow searches to be performed based on the words within them.

2. store: Defines which fields should be stored and retrievable in search results.

• The store property specifies what data should be included in the search results.

• Without store, you might only get the document id as a result, and you’d have to look up the full data elsewhere.

• Example: If store: ["title", "content", "url"], when a search finds a match, the result will include these fields (instead of just the id).


If running in Vercel, Netlify or on an Edge Network

If running on an edge service where memory does not persist between requests, it is highly advised to use a hosted solution such as Algolia or SearchStax

Although these features will run on the edge, depending on the size of your website, performance issues may occur and additional compute resources may be spent unnecessarily.