--- id: examples title: Examples and extensions description: Live demos showing how to use and extend DocSearch beyond documentation-only use cases. --- import { DocSearch } from '@docsearch/react'; import { DocSearch as DocSearchProvider } from '@docsearch/core'; import { DocSearchButton, DocSearchModal } from '@docsearch/modal'; import { DocSearchSidepanel } from '@docsearch/react/sidepanel'; import BrowserOnly from '@docusaurus/BrowserOnly'; import '@docsearch/css/dist/style.css'; import '@docsearch/css/dist/sidepanel.css'; > These examples are interactive. Click a button to open the modal and try a query. ## Basic keyword search Use the default experience with your index credentials. This works great for typical docs, blogs, and any site with a DocSearch-compliant index. ```jsx ``` --- ## Ask AI: ai-assisted answers Add Algolia Ask AI to get synthesized answers grounded in your indexed content. You can scope the LLM context using `searchParameters` like `facetFilters`, `filters`, `attributesToRetrieve`,`restrictSearchableAttributes`, and `distinct`. ```jsx ``` --- ## Sidepanel: persistent AI chat The sidepanel provides a persistent chat interface anchored to the side of the page, ideal for documentation sites where users want to ask follow-up questions without losing their place. Look for the button on the bottom right of the screen to try the demo. ```jsx ``` {() => ( )} --- ## Composable API: DocSearchButton + DocSearchModal Use the [Composable API](/docs/composable-api) to render the button and modal as separate components. This gives you explicit control over where each piece is rendered and when the modal code is loaded. ```jsx import { DocSearch } from '@docsearch/core'; import { DocSearchButton, DocSearchModal } from '@docsearch/modal'; import '@docsearch/css/style.css'; ; ``` {() => ( )} --- ## Custom hit rendering (`hitComponent`) Replace the default hit markup to match your brand and layout. Below is a minimal example of a custom component. ```jsx function CustomHit({ hit }) { // render a compact, branded hit card return (
{hit.type?.toUpperCase?.() || 'DOC'}
{hit.hierarchy?.lvl1 || 'untitled'}
{hit.hierarchy?.lvl2 && (
{hit.hierarchy.lvl2}
)} {hit.content && (
{hit.content}
)}
); } ; ``` { // render a compact, branded hit card return (
{hit.type?.toUpperCase?.() || 'DOC'}
{hit.hierarchy?.lvl1 || 'untitled'}
{hit.hierarchy?.lvl2 && (
{hit.hierarchy.lvl2}
)} {hit.content && (
{hit.content}
)}
); }} insights={true} translations={{ button: { buttonText: 'custom hits (demo)' } }} /> --- ## Opening links in new tabs By default, DocSearch opens search result links in the current window. If you want results to open in new tabs, you need to use both a custom `hitComponent` and the `navigator` prop to handle both click and keyboard navigation consistently. ```jsx // Custom hit component with target="_blank" function HitWithNewTab({ hit, children }) { return ( {children} ); } // Navigator configuration to handle keyboard navigation const newTabNavigator = { navigate: ({ itemUrl }) => window.open(itemUrl, '_blank'), navigateNewTab: ({ itemUrl }) => window.open(itemUrl, '_blank'), navigateNewWindow: ({ itemUrl }) => window.open(itemUrl, '_blank'), }; ; ``` ( {children} )} navigator={{ navigate: ({ itemUrl }) => window.open(itemUrl, '_blank'), navigateNewTab: ({ itemUrl }) => window.open(itemUrl, '_blank'), navigateNewWindow: ({ itemUrl }) => window.open(itemUrl, '_blank'), }} insights={true} translations={{ button: { buttonText: 'open in new tabs (demo)' } }} />

:::warning **Note**: Using only `hitComponent` with `target="_blank"` will work for mouse clicks, but keyboard navigation (arrows + Enter) requires the `navigator` prop to consistently open links in new tabs. ::: --- ## Bring-your-own-data shape with `transformItems` DocSearch is not limited to DocSearch-like records. Use `transformItems` to adapt any record shape into the internal structure DocSearch expects. This lets you build search for apps, help centers, changelogs, or any custom content. The snippet below maps a non-standard record to the internal format. Try it live: ```jsx items.map((item) => ({ objectID: item.objectID, content: item.content ?? '', url: item.domain + item.path, hierarchy: { lvl0: (item.breadcrumb || []).join(' > ') ?? '', lvl1: item.h1 ?? '', lvl2: item.h2 ?? '', lvl3: null, lvl4: null, lvl5: null, lvl6: null, }, url_without_anchor: item.domain + item.path, type: 'content', anchor: null, _highlightResult: item._highlightResult, _snippetResult: item._snippetResult, })) } insights={true} translations={{ button: { buttonText: 'transform items (demo)' } }} /> ``` items.map((item) => ({ objectID: item.objectID, content: item.content ?? '', url: item.domain + item.path, hierarchy: { lvl0: (item.breadcrumb || []).join(' > ') ?? '', lvl1: item.h1 ?? '', lvl2: item.h2 ?? '', lvl3: null, lvl4: null, lvl5: null, lvl6: null, }, url_without_anchor: item.domain + item.path, type: 'content', anchor: null, _highlightResult: item._highlightResult, _snippetResult: item._snippetResult, })) } insights={true} translations={{ button: { buttonText: 'transform items (demo)' } }} /> --- ## Tips - **Instrumentation**: enable `insights` to send usage analytics and iterate on relevance. - **Ask AI scoping**: use `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct` to control AI context and improve answer quality. - **Customization**: use `hitComponent`, `transformItems`, and `translations` to make DocSearch feel native to any product surface.