BunPress Documentation

Search

On this page 33

BunPress includes built-in search functionality for your documentation site. This guide covers configuration and customization options.

Quick Start

Enable search in your configuration:

// bunpress.config.ts
export default {
  search: {
    enabled: true,
  },
}

Search Providers

BunPress includes a fast, client-side search:

export default {
  search: {
    provider: 'local', // default
  },
}

Algolia DocSearch

For larger documentation sites:

export default {
  search: {
    provider: 'algolia',
    algolia: {
      appId: 'YOUR_APP_ID',
      apiKey: 'YOUR_SEARCH_API_KEY',
      indexName: 'YOUR_INDEX_NAME',
    },
  },
}

Local Search Options

Indexing Configuration

export default {
  search: {
    provider: 'local',
    options: {
      // Include/exclude patterns
      include: ['**/*.md'],
      exclude: ['**/node_modules/**', '**/draft/**'],

      // Search fields
      searchFields: ['title', 'content', 'headings', 'keywords'],

      // Result options
      maxResults: 10,
      minQueryLength: 2,
    },
  },
}

searchFields names map onto each indexed section:

FieldWhat it matches
titleThe section's own heading (the page title for the lead section)
headingsThe title of the page the section belongs to
contentThe section's prose, with code blocks removed
keywordsTerms added in the page's frontmatter

Boosting

Prioritize certain content:

export default {
  search: {
    options: {
      boost: {
        title: 10,
        headings: 5,
        content: 1,
      },
    },
  },
}

UI Customization

Placeholder Text

export default {
  search: {
    placeholder: 'Search documentation...',
  },
}

Keyboard Shortcut

export default {
  search: {
    shortcut: '/', // Press / to focus search
    // or
    shortcut: ['ctrl', 'k'], // Ctrl+K
  },
}

Result Appearance

export default {
  search: {
    resultOptions: {
      showDescription: true,
      descriptionLength: 150,
      highlightMatches: true,
      showPath: true,
    },
  },
}

Styling

The dialog exposes both its own BPSearch-* classes and the stable aliases below. The aliases are what this guide targets, so they are safe to style.

Custom CSS

/_ Search input _/
.search-input {
  background: var(--vp-c-bg-soft);
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 0.5rem 1rem;
}

/_ Search modal _/
.search-modal {
  background: var(--vp-c-bg);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}

/_ Search results _/
.search-result {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--vp-c-divider);
}

.search-result:hover {
  background: var(--vp-c-bg-soft);
}

/_ Highlighted matches _/
.search-highlight {
  background: rgba(255, 213, 0, 0.3);
  padding: 0.1em 0.2em;
  border-radius: 2px;
}

Advanced Configuration

Custom Tokenizer

export default {
  search: {
    options: {
      tokenize: (text) => {
        // Custom tokenization logic
        return text
          .toLowerCase()
          .split(/[\s\-_]+/)
          .filter((token) => token.length > 1)
      },
    },
  },
}

Fuzzy Matching

export default {
  search: {
    options: {
      fuzzy: true,
      fuzziness: 2, // Max edit distance
    },
  },
}

Stemming

export default {
  search: {
    options: {
      stemmer: 'english', // Use English stemmer
    },
  },
}

Frontmatter Control

Exclude Pages

---
search: false
---

# This page won't be indexed

Custom Search Keywords

---
search:
  keywords:

    - alternative name
    - common misspelling

---

Search Title Override

---
search:
  title: Custom Search Title
---

Search Analytics

Track Searches

export default {
  search: {
    onSearch: (query, results) => {
      // Track search analytics
      analytics.track('search', {
        query,
        resultCount: results.length,
      })
    },
  },
}

onSearch and options.tokenize run in the browser, so they are serialized into the page. They may reference globals that exist there (like analytics above) but must not close over values from your config module — those do not survive the trip.

If you would rather not ship a function, listen for the event the dialog dispatches after every search:

document.addEventListener('bp:search', (event) => {
  const { query, results } = event.detail
})

Algolia DocSearch

Setup

  1. Apply at docsearch.algolia.com
  2. Configure once approved:
export default {
  search: {
    provider: 'algolia',
    algolia: {
      appId: 'YOUR_APP_ID',
      apiKey: 'YOUR_SEARCH_ONLY_API_KEY',
      indexName: 'your_index',
      searchParameters: {
        facetFilters: ['language:en'],
      },
    },
  },
}

Crawler Configuration

{
  "index_name": "your_index",
  "start_urls": ["https://your-docs.com/"],
  "selectors": {
    "lvl0": ".sidebar-heading.active",
    "lvl1": "article h1",
    "lvl2": "article h2",
    "lvl3": "article h3",
    "content": "article p, article li"
  }
}

Performance

Lazy Loading

export default {
  search: {
    lazy: true, // Load search index on demand
  },
}

Index Size

export default {
  search: {
    options: {
      // Reduce index size
      storeFields: ['title'], // `url` is always kept
      maxContentLength: 500, // Limit prose per section
    },
  },
}

Prebuilt Index

The index is written to search-index.json on every build, alongside the generated pages. Skip it when you do not need search in a given build:

bunpress build --no-search-index

Accessibility

Search is accessible by default:

  • Keyboard navigation
  • ARIA labels
  • Focus management
  • Screen reader support

Best Practices

  1. Meaningful titles: Use descriptive page titles
  2. Clear headings: Well-structured headings improve search
  3. Keywords: Add search keywords in frontmatter
  4. Test searches: Verify common queries return expected results
  5. Monitor analytics: Track search patterns to improve content