Skip to main content
DocSearch can be easily integrated into any website using vanilla JavaScript. This guide shows you how to add DocSearch to static sites, HTML pages, or any JavaScript application.

Overview

The @docsearch/js package provides a simple JavaScript API that works in any browser environment. You can use it with or without a build tool.

Installation

Install DocSearch using your preferred package manager:
npm install @docsearch/js @docsearch/css
Then import in your JavaScript:
import docsearch from '@docsearch/js';
import '@docsearch/css';

Quick Start

1

Add a container element

Add a container element where DocSearch will render the search button:
<div id="docsearch"></div>
Use a container element (like <div>), not an <input>. DocSearch generates a fully accessible search button for you.
2

Initialize DocSearch

Call the docsearch() function with your configuration:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
});
3

Test it

Open your page and press Ctrl+K (or Cmd+K on Mac) to open the search modal. You can also click the search button that DocSearch creates.

Complete HTML Example

Here’s a complete working example using the CDN:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Documentation</title>
  
  <!-- DocSearch CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@4" />
  
  <style>
    body {
      font-family: system-ui, -apple-system, sans-serif;
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px;
    }
    
    header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 40px;
    }
  </style>
</head>
<body>
  <header>
    <h1>My Documentation</h1>
    <div id="docsearch"></div>
  </header>
  
  <main>
    <h2>Welcome</h2>
    <p>Start searching by clicking the search button or pressing Ctrl+K.</p>
  </main>
  
  <!-- DocSearch JS -->
  <script src="https://cdn.jsdelivr.net/npm/@docsearch/js@4"></script>
  
  <script>
    docsearch({
      container: '#docsearch',
      appId: 'YOUR_APP_ID',
      apiKey: 'YOUR_SEARCH_API_KEY',
      indexName: 'YOUR_INDEX_NAME',
    });
  </script>
</body>
</html>

Configuration Options

Basic Configuration

The minimum required configuration:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
});

Placeholder Text

Customize the search input placeholder:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  placeholder: 'Search documentation',
});

Search Parameters

Add Algolia search parameters:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  searchParameters: {
    facetFilters: ['language:en', 'version:v2'],
    hitsPerPage: 20,
  },
});

Transform Search Client

Modify the search client before queries:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  transformSearchClient: (searchClient) => {
    // Add custom agent
    searchClient.addAlgoliaAgent('my-site', '1.0.0');
    return searchClient;
  },
});

Transform Items

Post-process search results:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  transformItems: (items) => {
    return items.map((item) => ({
      ...item,
      url: item.url.replace('https://old-domain.com', 'https://new-domain.com'),
    }));
  },
});

Programmatic Control

The docsearch() function returns an instance with methods for programmatic control:
const instance = docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
});

// Open the modal programmatically
instance.open();

// Close the modal
instance.close();

// Check if modal is open
console.log(instance.isOpen); // true/false

// Check if component is ready
console.log(instance.isReady); // true/false

// Clean up when done
instance.destroy();

Lifecycle Callbacks

Listen to lifecycle events:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  onReady: () => {
    console.log('DocSearch is ready');
  },
  onOpen: () => {
    console.log('Modal opened');
  },
  onClose: () => {
    console.log('Modal closed');
  },
});

Ask AI Integration

Basic Ask AI

Enable AI-powered conversational search:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  askAi: 'YOUR_ASSISTANT_ID',
});

Ask AI with Configuration

Customize Ask AI behavior:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  askAi: {
    assistantId: 'YOUR_ASSISTANT_ID',
    appId: 'YOUR_APP_ID',
    apiKey: 'YOUR_SEARCH_API_KEY',
    indexName: 'YOUR_INDEX_NAME',
    suggestedQuestions: true,
  },
});

Open Ask AI Programmatically

const instance = docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  askAi: 'YOUR_ASSISTANT_ID',
});

// Open Ask AI mode with a pre-filled question
instance.openAskAi({ query: 'How do I get started?' });

Sidepanel Integration

For a better AI experience, use the sidepanel component:
1

Install sidepanel package

npm install @docsearch/sidepanel-js @docsearch/css
Or use the CDN:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@4/dist/sidepanel.css" />
<script src="https://cdn.jsdelivr.net/npm/@docsearch/sidepanel-js@4"></script>
2

Add sidepanel container

<div id="docsearch"></div>
<div id="docsearch-sidepanel"></div>
3

Initialize both components

import docsearch from '@docsearch/js';
import sidepanel from '@docsearch/sidepanel-js';
import '@docsearch/css/dist/style.css';
import '@docsearch/css/dist/sidepanel.css';

// Initialize sidepanel
const sidepanelInstance = sidepanel({
  container: '#docsearch-sidepanel',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  assistantId: 'YOUR_ASSISTANT_ID',
});

// Initialize search and connect to sidepanel
const searchInstance = docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  askAi: 'YOUR_ASSISTANT_ID',
  interceptAskAiEvent: (initialMessage) => {
    searchInstance.close();
    sidepanelInstance.open(initialMessage);
    return true; // Prevent default Ask AI modal
  },
});

Custom Templates

Customize how results are rendered using the hitComponent and resultsFooterComponent options:

Custom Hit Component

docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  hitComponent: ({ hit, children }, { html }) => {
    return html`
      <a href="${hit.url}" class="custom-hit">
        <div class="hit-icon">📄</div>
        <div class="hit-content">
          ${children}
        </div>
      </a>
    `;
  },
});
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  resultsFooterComponent: ({ state }, { html }) => {
    const nbHits = state.context?.nbHits || 0;
    return html`
      <div class="custom-footer">
        <a href="/search?q=${state.query}">
          See all ${nbHits} results
        </a>
      </div>
    `;
  },
});

Translations

Customize UI text:
docsearch({
  container: '#docsearch',
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_SEARCH_API_KEY',
  indexName: 'YOUR_INDEX_NAME',
  translations: {
    button: {
      buttonText: 'Search',
      buttonAriaLabel: 'Search documentation',
    },
    modal: {
      searchBox: {
        resetButtonTitle: 'Clear query',
        cancelButtonText: 'Cancel',
      },
      startScreen: {
        recentSearchesTitle: 'Recent',
        noRecentSearchesText: 'No recent searches',
      },
      footer: {
        selectText: 'to select',
        navigateText: 'to navigate',
        closeText: 'to close',
      },
    },
  },
});

Module Bundler Example

If you’re using a bundler like Webpack, Vite, or Rollup:
main.js
import docsearch from '@docsearch/js';
import '@docsearch/css';

// Wait for DOM to be ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initSearch);
} else {
  initSearch();
}

function initSearch() {
  const instance = docsearch({
    container: '#docsearch',
    appId: 'YOUR_APP_ID',
    apiKey: 'YOUR_SEARCH_API_KEY',
    indexName: 'YOUR_INDEX_NAME',
    placeholder: 'Search docs',
    searchParameters: {
      facetFilters: ['language:en'],
    },
  });

  // Expose for debugging
  window.docsearch = instance;
}

Styling

Customize DocSearch appearance with CSS:
custom.css
/* Customize the search button */
.DocSearch-Button {
  background-color: #f5f5f5;
  border-radius: 8px;
}

.DocSearch-Button:hover {
  background-color: #e0e0e0;
}

/* Customize the modal */
.DocSearch-Modal {
  --docsearch-primary-color: #5468ff;
  --docsearch-text-color: #1c1e21;
  --docsearch-spacing: 12px;
  --docsearch-modal-width: 600px;
}

/* Customize search results */
.DocSearch-Hit {
  padding: 8px;
}

.DocSearch-Hit-title {
  font-weight: 600;
}

Complete Production Example

Here’s a complete example with all best practices:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Documentation</title>
  
  <!-- Preconnect to Algolia -->
  <link rel="preconnect" href="https://YOUR_APP_ID-dsn.algolia.net" crossorigin="anonymous" />
  
  <!-- DocSearch CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@4" />
  
  <style>
    /* Your custom styles */
  </style>
</head>
<body>
  <header>
    <h1>Documentation</h1>
    <div id="docsearch"></div>
  </header>
  
  <main>
    <!-- Your content -->
  </main>
  
  <!-- DocSearch JS -->
  <script src="https://cdn.jsdelivr.net/npm/@docsearch/js@4"></script>
  
  <script>
    (function() {
      'use strict';
      
      // Initialize when DOM is ready
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
      } else {
        init();
      }
      
      function init() {
        var instance = docsearch({
          container: '#docsearch',
          appId: 'YOUR_APP_ID',
          apiKey: 'YOUR_SEARCH_API_KEY',
          indexName: 'YOUR_INDEX_NAME',
          placeholder: 'Search docs',
          searchParameters: {
            facetFilters: ['language:en']
          },
          onReady: function() {
            console.log('DocSearch ready');
          },
          transformSearchClient: function(searchClient) {
            searchClient.addAlgoliaAgent('my-site', '1.0.0');
            return searchClient;
          }
        });
        
        // Expose for debugging (optional)
        window.docsearch = instance;
      }
    })();
  </script>
</body>
</html>

Troubleshooting

Search button not appearing

  1. Verify the container element exists: document.querySelector('#docsearch')
  2. Check browser console for errors
  3. Ensure DocSearch CSS is loaded
  4. Verify you’re calling docsearch() after DOM is ready
  1. Check if JavaScript errors are preventing execution
  2. Verify credentials are correct
  3. Test keyboard shortcut (Ctrl+K) and button click separately

No search results

  1. Verify your index has data in Algolia dashboard
  2. Check searchParameters.facetFilters aren’t too restrictive
  3. Test with a known indexed term
  4. Check browser network tab for API errors

Next Steps

API Reference

Explore all configuration options

Styling

Customize the appearance of DocSearch

Ask AI

Add AI-powered conversational search

React Integration

Use DocSearch with React

Build docs developers (and LLMs) love