` or `
` or `
default.js
@@ -117,7 +122,7 @@ new Crawler({docusaurus-v1.js
@@ -274,7 +279,7 @@ new Crawler({docusaurus-v2.js
@@ -296,12 +301,14 @@ new Crawler({ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'], recordExtractor: ({ $, helpers }) => { // priority order: deepest active sub list header -> navbar active item -> 'Documentation' + // Extracting the breadcrumb titles for better accessibility. + const navbarTitle = $('.navbar__item.navbar__link--active').text(); + const pageBreadcrumbTitles = $('.breadcrumbs__link') + .toArray() + .map((item) => $(item).text().trim()) + .filter(Boolean); const lvl0 = - $( - '.menu__link.menu__link--sublist.menu__link--active, .navbar__item.navbar__link--active' - ) - .last() - .text() || 'Documentation'; + [navbarTitle, ...pageBreadcrumbTitles].join(' / ') || 'Documentation'; return helpers.docsearch({ recordProps: { @@ -413,23 +420,23 @@ new Crawler({ // Get the top level menu item const lvl0 = $('details:has(a[aria-current="page"])') - .find("summary") - .find("span") - .text() || "Documentation"; + .find('summary') + .find('span') + .text() || 'Documentation'; return helpers.docsearch({ recordProps: { lvl0: { - selectors: "", + selectors: '', defaultValue: lvl0, }, - lvl1: "main h1", - lvl2: "main h2", - lvl3: "main h3", - lvl4: "main h4", - lvl5: "main h5", - lvl6: "main h6", - content: "main p, main li", + lvl1: 'main h1', + lvl2: 'main h2', + lvl3: 'main h3', + lvl4: 'main h4', + lvl5: 'main h5', + lvl6: 'main h6', + content: 'main p, main li', }, indexHeadings: true, aggregateContent: true, @@ -439,16 +446,8 @@ new Crawler({ ], initialIndexSettings: { YOUR_INDEX_NAME: { - attributesForFaceting: [ - 'type', - 'lang', - ], - attributesToRetrieve: [ - 'hierarchy', - 'content', - 'anchor', - 'url', - ], + attributesForFaceting: ['type', 'lang'], + attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], attributesToHighlight: ['hierarchy', 'content'], attributesToSnippet: ['content:10'], camelCaseAttributes: ['hierarchy', 'content'], @@ -813,37 +812,34 @@ new Crawler({ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'], recordExtractor: ({ $, helpers }) => { const lvl0 = - $(".rspress-nav-menu-item.rspress-nav-menu-item-active") + $('.rspress-nav-menu-item.rspress-nav-menu-item-active') .first() - .text() || "Documentation"; + .text() || 'Documentation'; return helpers.docsearch({ recordProps: { lvl0: { - selectors: "", + selectors: '', defaultValue: lvl0, }, - lvl1: ".rspress-doc h1", - lvl2: ".rspress-doc h2", - lvl3: ".rspress-doc h3", - lvl4: ".rspress-doc h4", - lvl5: ".rspress-doc h5", - lvl6: ".rspress-doc pre > code", // if you want to search code blocks, add this line - content: ".rspress-doc p, .rspress-doc li", + lvl1: '.rspress-doc h1', + lvl2: '.rspress-doc h2', + lvl3: '.rspress-doc h3', + lvl4: '.rspress-doc h4', + lvl5: '.rspress-doc h5', + lvl6: '.rspress-doc pre > code', // if you want to search code blocks, add this line + content: '.rspress-doc p, .rspress-doc li', }, indexHeadings: true, aggregateContent: true, - recordVersion: "v3", + recordVersion: 'v3', }); }, }, ], initialIndexSettings: { YOUR_INDEX_NAME: { - attributesForFaceting: [ - 'type', - 'lang', - ], + attributesForFaceting: ['type', 'lang'], attributesToRetrieve: [ 'hierarchy', 'content', diff --git a/packages/website/docs/tips.md b/packages/website/docs/tips.md index 57d1c4fa..7bcaebcb 100644 --- a/packages/website/docs/tips.md +++ b/packages/website/docs/tips.md @@ -1,71 +1,76 @@ --- title: Tips for a good search +description: Improve DocSearch relevance with clear content structure and crawler selectors. --- -DocSearch can work with almost any website, but we've found that some site structures yield more relevant results or faster indexing time. On this page we'll share some tips on how to make the most out of DocSearch. +DocSearch works with many website structures, but consistent structure can improve relevance and indexing time. Follow these recommendations to improve your DocSearch results. ## Use a `sitemap.xml` -If you provide a sitemap in your configuration, DocSearch will use it to directly browse the pages to index. Pages are still crawled which means we extract every compliant link. +If you provide a sitemap in your crawler configuration, DocSearch uses it to find pages to index. The crawler also follows eligible links on those pages. -We highly recommend you add a `sitemap.xml` to your website if you don't have one already. This will not only make the indexing faster, but also provide you more control over which pages to index. +Add a `sitemap.xml` to your website if you don't have one. A sitemap can reduce indexing time and gives you more control over which pages are indexed. -Sitemaps are also considered good practice for other aspects, including SEO ([more information on sitemaps][1]). +Sitemaps can also improve search engine optimization. For more information, see the [sitemaps specification][1]. ## Structure the hierarchy of information -DocSearch works better on structured documentation. Relevance of results is based on the structural hierarchy of content. In simpler terms, it means that we read the ``, ..., `` headings of your page to guess the hierarchy of information. This hierarchy brings contextual information to your records.
+DocSearch works better on structured documentation. Result relevance uses the structural hierarchy of your content. The crawler reads the `` through `` headings or equivalent selectors to build `hierarchy.lvl0` through `hierarchy.lvl6`.
-Documentation starts by explaining generic concepts first and then goes deeper into specifics. This is represented in your HTML markup by the hierarchy of headings you're using. For example, concepts discussed under a `` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+Documentation usually introduces general concepts before covering details. Represent this structure with an ordered heading hierarchy. For example, content under an `` is more specific than content under an `` on the same page. Content that appears earlier on the page ranks higher.
-DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+DocSearch uses this structure to improve relevance. V5 also uses the populated hierarchy levels to render result breadcrumbs. Keep headings in order and avoid skipping levels where possible so each result retains its page context.
-Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+Choose a documentation depth that gives each result enough context. For large pages, use four levels, from `lvl0` to `lvl3`. Use at least three levels.
-_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+You can use classes, such as ``, instead of `` elements.
## Set a unique class to the element holding the content
DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
-Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+A unique identifier makes your configuration more robust and limits indexing to relevant content. Use it to exclude unrelated headers, sidebars, and footers.
## Add anchors to headings
-When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+Add a custom anchor to each heading. Define anchors with an `id` or `name` HTML attribute so browsers can scroll directly to the corresponding position. Links can target an anchor with `#` followed by its value.
-DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+DocSearch uses these anchors to send users to the location of the selected result.
-## Marking the active page(s) in the navigation
+## Mark active pages in the navigation
-If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+If you use multi-level navigation, mark each active level with a custom CSS class. The crawler can use this class to determine where the current page fits in the website hierarchy.
For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
-The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+Use any valid CSS class name that can be part of a CSS selector.
## Consistency of your content
-Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+Use the same heading structure across documentation pages. Make each page topic and outline clear, and avoid selectors that create records without enough context, such as standalone introductions or asides.
-The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+Write selectors that match documentation pages but exclude landing pages, tables of contents, and other unrelated content. Add a dedicated class, such as `.DocSearch-content`, to the main documentation container.
-Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+Use consistent terms for the same concepts. You can also configure [synonyms][5] for terms your users search interchangeably.
-Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+## Avoid duplicate content
-## Avoid duplicates by promoting unicity
+Split broad topics into focused pages. Avoid catch-all pages that make it difficult to identify the relevant result.
-The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+Duplicate content adds noise and can mislead users. Don't repeat all documentation content on a landing or summary page. If you need duplicate records for separate datasets, such as different versions, use [facets][3] to distinguish them.
-Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+## Index metadata for v5
+
+Add each attribute used by the v5 `facets` option to `attributesForFaceting`. DocSearch supports up to five facet controls. For a result badge, index a short value such as `version`, include it in `attributesToRetrieve`, and pass its property path to `resultBadgeKey`. See the [v5 JavaScript API reference][4].
## Conciseness
-What is clearly thought out is clearly and concisely expressed.
+Keep content focused on one task or concept, and use short headings and paragraphs.
-We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+For more guidance, read [How to build a helpful search for technical documentation][2].
[1]: https://www.sitemaps.org/index.html
[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
[3]: https://www.algolia.com/doc/guides/searching/faceting/
+[4]: /docs/packages/js/api-reference#facets
+[5]: https://www.algolia.com/doc/guides/managing-results/must-do/searchable-attributes/#synonyms
diff --git a/packages/website/docs/v5-breaking-changes.mdx b/packages/website/docs/v5-breaking-changes.mdx
new file mode 100644
index 00000000..f3ec2ef5
--- /dev/null
+++ b/packages/website/docs/v5-breaking-changes.mdx
@@ -0,0 +1,236 @@
+---
+title: v5 breaking changes
+description: Complete user-facing breaking changes and compatibility notes for DocSearch v5.
+---
+
+This page lists the user-facing changes between the v4.6.0 package source and `5.0.0-beta.0`. Use it with the [v4 migration guide](./migrating-from-v4).
+
+## JavaScript entry points
+
+### The root export is AI-capable
+
+In v4, the root `@docsearch/js` export rendered the combined component and allowed Ask AI to be omitted. In v5, it renders `DocSearchAI`, and its `DocSearchProps` type requires `askAi`.
+
+Use the root entry when you configure Agent Studio:
+
+```js title="app.js"
+import docsearch from '@docsearch/js';
+```
+
+### Keyword-only search moved to `/docsearch`
+
+Use the new subpath when you don't need Ask AI:
+
+```js title="app.js"
+import docsearch from '@docsearch/js/docsearch';
+```
+
+This entry excludes Ask AI code.
+
+### The UMD bundle is split
+
+- `dist/umd/index.js` includes keyword search and Ask AI.
+- `dist/umd/docsearch.js` includes keyword search only.
+- Both bundles expose `window.docsearch`.
+- Loading both bundles causes the later script to replace the same global.
+
+### An exports map restricts JavaScript imports
+
+`@docsearch/js` now exports only `.` and `./docsearch`. Replace imports of internal distribution files with one of these public entry points. Direct CDN URLs to the two documented UMD files remain supported by the package layout.
+
+## React components
+
+### `DocSearch` is keyword-only
+
+V4's `DocSearch` accepted `askAi` and `interceptAskAiEvent`. V5's `DocSearch` contains keyword search only and no longer declares those props.
+
+### `DocSearchAI` owns the AI experience
+
+Use `DocSearchAI` for keyword search and Ask AI:
+
+```jsx title="Search.jsx"
+import { DocSearchAI } from '@docsearch/react';
+```
+
+`DocSearchAIProps` extends `DocSearchProps`, requires `askAi`, and adds `interceptAskAiEvent`.
+
+The package also adds `@docsearch/react/docsearchAi` and `@docsearch/react/askaiModal` subpaths.
+
+### The Ask AI modal is separate
+
+`DocSearchModal` is keyword-only. `DocSearchAskAiModal` contains the combined keyword and AI modal. Composable integrations that rendered `DocSearchModal` with `askAi` must switch to `DocSearchAskAiModal` and its required provider callbacks. Review the [Composable API](/docs/composable-api) instead of constructing these props without the provider.
+
+`@docsearch/modal` exports the AI modal from its root and from `@docsearch/modal/askai`.
+
+## Ask AI and Agent Studio
+
+### The legacy transport is removed
+
+V5 no longer requests a legacy Ask AI token or sends chat requests to the v4 Ask AI endpoint. All Ask AI conversations use the Agent Studio completions endpoint.
+
+Create and configure an assistant in [Agent Studio](/docs/agent-studio/getting-started) before upgrading.
+
+### `askAi.agentStudio` is removed
+
+The backend switch is no longer needed because Agent Studio is the only backend. Remove both `agentStudio: true` and `agentStudio: false`.
+
+### `askAi.useStagingEnv` is removed
+
+The staging endpoint switch isn't part of `DocSearchAskAi` in v5.
+
+### Flat Ask AI search parameters are removed
+
+`DocSearchAskAi.searchParameters` now always uses `AgentStudioSearchParameters`: an object keyed by index name.
+
+```js title="app.js"
+searchParameters: {
+ docs: {
+ filters: 'language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ distinct: true,
+ },
+}
+```
+
+Each value supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`. The Agent Studio type omits `facetFilters`.
+
+### Agent Studio credentials are sent directly
+
+Ask AI requests use the configured application ID and API key in `x-algolia-application-id` and `x-algolia-api-key` headers. Memory authentication adds `x-algolia-secure-user-token`. Check the permissions and domain restrictions of keys that were issued for the legacy transport.
+
+### Feedback uses Agent Studio
+
+Feedback now posts to Agent Studio and supports negative-feedback reason tags and notes. Stored conversation messages can contain `feedbackTags` and `feedbackNotes` in addition to the like or dislike value.
+
+### Agent Studio configuration is nested under `askAi`
+
+Dynamic `indices`, custom `tools`, `memory`, and keyword `promptSuggestions` belong inside the `askAi` object. `interceptAskAiEvent` remains a top-level integration callback.
+
+### Suggested questions have two sources
+
+- `askAi.suggestedQuestions` determines whether DocSearch loads published questions for the assistant from `algolia_ask_ai_suggested_questions` on the new-conversation screen.
+- `askAi.promptSuggestions` searches a configured index containing a `prompt` attribute and displays those prompts with keyword results.
+
+These options aren't interchangeable.
+
+## Search configuration
+
+### The Docusaurus adapter configuration changed
+
+The v5 adapter reads `themeConfig.docsearch` and rejects the former `themeConfig.algolia` key. It also requires `indices` and rejects `indexName` and root `searchParameters`.
+
+Replace `searchPagePath` with `searchPage`. Move `askAi.sidePanel` to the root `sidePanel` option. Remove legacy Ask AI credentials and the `askAi.agentStudio` switch. Follow [Migrate the Docusaurus adapter from v4](/docs/packages/docusaurus-adapter/migrating-from-v4) for before-and-after configurations.
+
+### At least one index is required at runtime
+
+Pass `indices` or `indexName`. V5 throws this error when neither produces an index:
+
+```text
+Must supply either `indexName` or `indices` for DocSearch to work
+```
+
+### `indexName` remains deprecated
+
+`indexName` still works; it isn't removed in v5. If present, DocSearch places it before all `indices` entries. Passing the same index through both options sends duplicate requests.
+
+### Root `searchParameters` remains deprecated
+
+The root option applies only to `indexName`. Move search parameters to each `DocSearchIndex` in `indices`.
+
+### Multiple indices share one result flow
+
+V5 creates one source for each index response and combines hit totals across responses. Result order follows the normalized index order. Review code that assumes one index or source identifier.
+
+## New keyword search behavior
+
+### Facets add requests and filters
+
+The new `facets` option fetches facet values with a zero-hit query for every configured index. DocSearch merges and sorts values, supports at most five keys after trimmed, lowercase duplicate checks, and displays only facets with values.
+
+A selected value is appended to that index's existing `facetFilters`. Account for the additional facet-value request in analytics, rate estimates, and search-client mocks.
+
+### Result badges require retrieved attributes
+
+The new `resultBadgeKey` reads a property path from each hit. The default `attributesToRetrieve` list doesn't include custom badge properties. Add them to each relevant index's `searchParameters.attributesToRetrieve`.
+
+### Result markup and grouping changed
+
+V5 refreshes the modal and result markup, renders breadcrumbs, introduces source panels, and adds facet and badge elements. CSS selectors, DOM tests, snapshots, and custom overrides that target v4 internals can break.
+
+Use public component props for behavior and review [Styling](/docs/packages/css/styling) for visual changes.
+
+## Styles and builds
+
+### Ask AI styles have a separate source bundle
+
+The complete `@docsearch/css` stylesheet still imports button, modal, and Ask AI rules. React also exposes split style entries:
+
+- `@docsearch/react/style/variables`
+- `@docsearch/react/style/button`
+- `@docsearch/react/style/modal`
+- `@docsearch/react/style/askai`
+- `@docsearch/react/style/sidepanel`
+
+If you assemble styles by component, add `style/askai` for `DocSearchAI` or `DocSearchAskAiModal`.
+
+### Generated React file names changed
+
+The documented package subpaths remain stable, but their targets changed from names such as `dist/esm/DocSearchModal.js` to generated entry files such as `dist/esm/modal.js`. Imports that bypassed the package exports can break.
+
+### The React `main` field now points to ESM
+
+`@docsearch/react` changes `main` from `dist/umd/index.js` to `dist/esm/index.js`. Consumers that resolve `main` instead of the package exports need an ESM-compatible build pipeline. The explicit `unpkg` and `jsdelivr` fields continue to point to `dist/umd/index.js`.
+
+### The browser target is ES2017
+
+V5's tsdown builds target ES2017. Provide transpilation or polyfills if your browser support policy extends below that target.
+
+## Public controls
+
+### JavaScript instances don't expose Sidepanel state
+
+`DocSearchInstance` exposes `open`, `close`, `openAskAi`, `destroy`, `isReady`, and `isOpen`. It doesn't expose `openSidepanel`, `isSidepanelOpen`, or `isSidepanelSupported`.
+
+### React refs include Sidepanel controls
+
+`DocSearchRef` exposes the JavaScript-style modal controls plus `openSidepanel`, `isSidepanelOpen`, and `isSidepanelSupported`. `openSidepanel` does nothing until a Sidepanel view registers. On mobile, `openAskAi` and standard Ask AI actions fall back to the modal.
+
+See [hybrid mode](/docs/hybrid-mode) for the supported integration.
+
+### Deprecated keyboard hook fields remain
+
+`UseDocSearchKeyboardEventsProps.onInput` and `searchButtonRef` are accepted for compatibility but are deprecated and aren't used by the v5 React hook implementation.
+
+## Compatibility
+
+### React peer range
+
+`@docsearch/react`, `@docsearch/core`, `@docsearch/modal`, and `@docsearch/sidepanel` declare these optional peers:
+
+- `react`: `>=16.8.0 <20.0.0`
+- `react-dom`: `>=16.8.0 <20.0.0`
+- `@types/react`: `>=16.8.0 <20.0.0`
+
+`@docsearch/react` also accepts optional `search-insights` versions `>=1 <3`.
+
+### Package versions must match
+
+The `5.0.0-beta.0` packages depend on matching beta versions of the other DocSearch packages. Don't mix v4 and v5 packages in a Composable API or Sidepanel tree.
+
+### CSS remains a separate install for top-level integrations
+
+Install `@docsearch/css@^5.0.0-beta`, then import `@docsearch/css`. For a CDN integration, load `dist/style.css` from the same caret beta range.
+
+## Additive v5 APIs
+
+These additions aren't breaking by themselves, but they replace common v4 custom implementations:
+
+- `facets` and `DocSearchFacet` for keyword filters.
+- `resultBadgeKey` for hit metadata.
+- `DocSearchAI` and `DocSearchAskAiModal` for AI-capable React views.
+- `AgentStudioIndices` and `AgentStudioSearchControls` for dynamic search tools.
+- `ToolCalls` and `ToolDefinition` for custom Agent Studio tools.
+- `Memory` for user-scoped Agent Studio memory.
+- `PromptSuggestions` for keyword-query prompt suggestions.
+- Ask AI feedback tags and notes.
+- Split JavaScript, React, and style entries for smaller keyword-only builds.
diff --git a/packages/website/docs/what-is-docsearch.md b/packages/website/docs/what-is-docsearch.md
index 5b9cc3c9..cd0ecc17 100644
--- a/packages/website/docs/what-is-docsearch.md
+++ b/packages/website/docs/what-is-docsearch.md
@@ -1,24 +1,27 @@
---
title: What is DocSearch?
+description: Understand how DocSearch provides search for technical documentation.
sidebar_label: What is DocSearch?
---
## Why?
-We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+We created DocSearch because developers spend a lot of time reading documentation, and finding relevant information in large documentation sites can be difficult. Building good search is a challenge.
-It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+Algolia has extensive experience building search interfaces. We use that experience to extract content from technical documentation and make it searchable from the first keystroke.
-## Quick description
+## Overview
-We split DocSearch into a crawler and a frontend library.
+DocSearch has two independent parts: indexing and the frontend search experience.
-- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
-- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+- The [Algolia Crawler][4] extracts your documentation into an Algolia index. Use the [Crawler interface][5] to edit the crawler configuration, monitor crawls, and trigger new crawls.
+- The [DocSearch v5 packages][7] query that index and render keyword search or Ask AI in your frontend. They are built on [Algolia Autocomplete][6].
+
+Crawler configuration and record schema versions don't select the installed DocSearch frontend package version. You can update the frontend package without changing how the crawler is scheduled.
## How to feature DocSearch?
-DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+DocSearch is free for eligible documentation sites. Read [the eligibility requirements][2] and apply. After approval and indexing, add a [DocSearch v5 package][7] or a supported framework integration to your website. Keep the "Search by Algolia" link displayed.
DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
@@ -30,3 +33,4 @@ You can now [apply to the program][3]
[4]: https://www.algolia.com/products/search-and-discovery/crawler/
[5]: https://dashboard.algolia.com/crawler
[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[7]: /docs/packages/overview
diff --git a/packages/website/docs/who-can-apply.md b/packages/website/docs/who-can-apply.md
index 320814d0..317b2249 100644
--- a/packages/website/docs/who-can-apply.md
+++ b/packages/website/docs/who-can-apply.md
@@ -1,30 +1,32 @@
---
title: Who can apply?
+description: Check whether your documentation project is eligible for DocSearch.
---
-**Open for all developer documentation and technical blogs.**
+**Open to developer documentation and technical blogs.**
-We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all online technical documentations and technical blogs.
+We built DocSearch to improve search on large technical documentation sites. We offer the free DocSearch program to public technical documentation and technical blogs.
We usually turn down applications when they are not production ready or have non-technical content on the website.
## Application process
-To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+To [apply][1] to the DocSearch program, follow the onboarding process in the Algolia dashboard. Submit your domain for validation against the program requirements. If your domain meets the criteria, you can create your DocSearch crawler.
-- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+- Use one of our [supported integrations][3] or a [DocSearch v5 package][5] after your content is indexed.
-- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+- Verify your domain ownership within 7 days of approval to continue using the crawler.
-- β
Please review [DocSearch Plan Terms and Conditions][2].
+- Review the [DocSearch Plan Terms and Conditions][2].
## Process duration
-DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+The application process includes automated validation. If we can't determine your eligibility automatically, we'll conduct a manual review that may take one to two business days.
-Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+Once approved, continue the onboarding process to create your DocSearch crawler. After the crawler indexes your data, choose the frontend package or framework integration separately. Updating the frontend doesn't change your crawler or index format.
[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
[3]: integrations.md
[4]: https://alg.li/discord
+[5]: /docs/packages/overview
diff --git a/packages/website/docusaurus.config.mjs b/packages/website/docusaurus.config.mjs
index f1605941..8c70af8f 100644
--- a/packages/website/docusaurus.config.mjs
+++ b/packages/website/docusaurus.config.mjs
@@ -50,7 +50,10 @@ export default {
'https://github.com/algolia/docsearch/edit/main/packages/website/',
versions: {
current: {
- label: 'Latest (v4.x)',
+ label: 'Beta (v5.0.0-beta.x)',
+ },
+ v4: {
+ label: 'Stable (v4.x)',
},
v3: {
label: 'Legacy (v3.x)',
@@ -138,9 +141,9 @@ export default {
],
},
announcementBar: {
- id: 'announcement-bar',
+ id: 'docsearch-v5-beta',
content:
- 'π Get Ask AI now! Turn your docs site search into an AI-powered assistant β faster answers, fewer tickets, better self-serve. Get Started Now',
+ 'DocSearch 5.0.0-beta is available. Migrate from v4 or choose a package.',
},
colorMode: {
defaultMode: 'light',
@@ -165,8 +168,12 @@ export default {
to: 'docs/v3/docsearch',
},
{
- label: 'DocSearch v4 - Beta',
- to: 'docs/docsearch',
+ label: 'DocSearch v4',
+ to: 'docs/v4/docsearch',
+ },
+ {
+ label: 'DocSearch v5 beta',
+ to: 'docs/packages/overview',
},
],
},
diff --git a/packages/website/sidebars.js b/packages/website/sidebars.js
index cc5d370b..c4fbae84 100644
--- a/packages/website/sidebars.js
+++ b/packages/website/sidebars.js
@@ -13,19 +13,87 @@ export default {
{
type: 'category',
label: 'Introduction',
- items: ['what-is-docsearch', 'who-can-apply'],
+ items: [
+ 'what-is-docsearch',
+ 'who-can-apply',
+ 'migrating-from-v4',
+ 'v5-breaking-changes',
+ ],
},
{
type: 'category',
- label: 'DocSearch v4',
+ label: 'Packages',
items: [
- 'docsearch',
- 'docusaurus-adapter',
+ 'packages/overview',
+ {
+ type: 'category',
+ label: '@docsearch/js',
+ items: ['packages/js/getting-started', 'packages/js/api-reference'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/react',
+ items: [
+ 'packages/react/getting-started',
+ 'packages/react/api-reference',
+ 'packages/react/examples',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/modal',
+ items: ['packages/modal/overview', 'packages/modal/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel',
+ items: [
+ 'packages/sidepanel/getting-started',
+ 'packages/sidepanel/advanced-use-cases',
+ 'packages/sidepanel/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel-js',
+ items: [
+ 'packages/sidepanel-js/getting-started',
+ 'packages/sidepanel-js/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/css',
+ items: ['packages/css/styling', 'packages/css/bundle-exports'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/core',
+ items: ['packages/core/overview', 'packages/core/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/docusaurus-adapter',
+ items: [
+ 'packages/docusaurus-adapter/getting-started',
+ 'packages/docusaurus-adapter/configuration-reference',
+ 'packages/docusaurus-adapter/migrating-from-v4',
+ ],
+ },
'composable-api',
- 'styling',
- 'api',
- 'examples',
- 'migrating-from-v3',
+ 'hybrid-mode',
+ ],
+ },
+ {
+ type: 'category',
+ label: 'Agent Studio',
+ items: [
+ 'agent-studio/getting-started',
+ 'agent-studio/dynamic-indices',
+ 'agent-studio/tools',
+ 'agent-studio/memory',
+ 'agent-studio/prompt-suggestions',
+ 'agent-studio/feedback',
],
},
{
@@ -33,34 +101,6 @@ export default {
label: 'MCP',
items: ['mcp/overview', 'mcp/installation', 'mcp/usage'],
},
- {
- type: 'category',
- label: 'Algolia Ask AI',
- items: [
- 'v4/askai',
- 'v4/askai-api',
- 'v4/askai-prompts',
- 'v4/askai-whitelisted-domains',
- 'v4/askai-models',
- 'v4/askai-markdown-indexing',
- 'v4/askai-errors',
- {
- type: 'link',
- label: 'Full Documentation',
- href: 'https://www.algolia.com/doc/guides/algolia-ai/askai',
- },
- ],
- },
- {
- type: 'category',
- label: 'Sidepanel',
- items: [
- 'sidepanel/getting-started',
- 'sidepanel/advanced-use-cases',
- 'sidepanel/hybrid',
- 'sidepanel/api-reference',
- ],
- },
{
type: 'category',
label: 'Algolia Crawler',
diff --git a/packages/website/src/components/Home.js b/packages/website/src/components/Home.js
index a8a4ea86..ee5dbb91 100644
--- a/packages/website/src/components/Home.js
+++ b/packages/website/src/components/Home.js
@@ -116,9 +116,9 @@ function Home() {
+ eyebrow="Interactive demo"
+ title="See DocSearch in action"
+ />
diff --git a/packages/website/versioned_docs/version-v4/api.mdx b/packages/website/versioned_docs/version-v4/api.mdx
new file mode 100644
index 00000000..ecf87ebb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/api.mdx
@@ -0,0 +1,935 @@
+---
+title: API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+
+
+
+## `container`
+
+> `type: string | HTMLElement` | **required**
+
+The container for the DocSearch search box. You can either pass a [CSS selector][5] or an [Element][6]. If there are several containers matching the selector, DocSearch picks up the first one.
+
+## `environment`
+
+> `type: typeof window` | `default: window` | **optional**
+
+The environment in which your application is running.
+
+This is useful if youβre using DocSearch in a different context than `window`.
+
+
+
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `indices`
+
+> `type: Array`
+
+The list of indices and their _optional_ `searchParameters` to be used for keyword search.
+
+[Algolia Search Parameters][7]
+
+:::tip
+
+The ordering matters in the list, as results are ordered based on `indices` order.
+
+:::
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+
+
+
+```js
+docsearch({
+ // ...
+ indices: ['YOUR_ALGOLIA_INDEX'],
+ // ...
+});
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```js
+docsearch({
+ // ...
+ indices: [
+ {
+ name: 'YOUR_ALGOLIA_INDEX',
+ searchParameters: {
+ facetFilters: ['language:en'],
+ // ...
+ },
+ },
+ ],
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```jsx
+
+```
+
+
+
+
+## `indexName`
+
+> `type: string` | **deprecated**
+
+:::warning[Deprecation warning]
+
+`indexName` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+Your Algolia index name.
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+## `placeholder`
+
+> `type: string` | `default: "Search docs"` | **optional**
+
+The placeholder of the input of the DocSearch pop-up modal. Note: If you add a placeholder, it will replace the dynamic placeholder based on `askAi`. It would be better to edit [translations](#translations) instead.
+
+## `askAi`
+
+> `type: AskAiObject` | `string` | **optional**
+
+Your Algolia Assistant ID.
+
+
+
+
+```js
+docsearch({
+ // ...
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ // ...
+});
+```
+
+or if you want to use different credentials for `askAi` and add search parameters
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ indexName: 'ANOTHER_INDEX_NAME',
+ apiKey: 'ANOTHER_SEARCH_API_KEY',
+ appId: 'ANOTHER_APP_ID',
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ // Filtering parameters
+ facetFilters: ['language:en', 'version:latest'],
+ filters: 'type:content AND language:en',
+
+ // Content control parameters
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+
+ // Deduplication
+ distinct: true,
+ },
+
+ // Enables/disables showing suggested questions on Ask AI's new conversation screen
+ // NOTE: Only available with version >= 4.3
+ suggestedQuestions: true,
+ },
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use different credentials for `askAi`
+
+```jsx
+= 4.3
+ suggestedQuestions: true,
+ }}
+/>
+```
+
+
+
+
+:::tip[Ask AI supports these essential search parameters for optimal performance:]
+
+- **Filtering**: `facetFilters: ['type:content']` - Filter by language, version, or content type
+- **Complex filtering**: `filters: 'type:content AND language:en'` - Apply complex filtering rules
+- **Content control**: `attributesToRetrieve: ['title', 'content', 'url']` - Control which attributes are retrieved
+- **Search scope**: `restrictSearchableAttributes: ['title', 'content']` - Limit search to specific fields
+- **Deduplication**: `distinct: true` - Remove duplicate results (`boolean | number | string`)
+
+These parameters provide the essential functionality for Ask AI while keeping the API simple and focused.
+
+:::
+
+### `askAi.agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`askAi.agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `askAi.agentStudio` is `true`, the Ask AI chat will use Algolia's [Agent Studio][12] as the chat backend instead of the Ask AI backend. Learn more on [Algolia Agent Studio Docs][13].
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+::::info[Search parameter shapes]
+
+- Standard Ask AI (`agentStudio` omitted or `false`): `searchParameters` is a flat object and supports `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- Agent Studio (`agentStudio: true`): `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+::::
+
+## `searchParameters`
+
+> `type: SearchParameters` | **optional** | **deprecated**
+
+:::warning[Deprecation warning]
+
+`searchParameters` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+The [Algolia Search Parameters][7].
+
+## `transformItems`
+
+> `type: function` | `default: items => items` | **optional**
+
+Receives the items from the search response, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them.
+
+
+
+
+```js
+docsearch({
+ // ...
+ transformItems(items) {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ }}
+/>
+```
+
+
+
+
+## `hitComponent`
+
+> `type: ({ hit, children }, { html }) => JSX.Element | string | Function` | `default: Hit` | **optional**
+
+The component to display each item. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ hit, children }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ hit, children }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the `hit` object which contains all the data for the search result, and `children` which is the default rendered content.
+
+See the [default implementation][8].
+
+
+
+
+```js
+docsearch({
+ // ...
+ hitComponent({ hit, children }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+
+ ${children}
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ π
+ {children}
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `transformSearchClient`
+
+> `type: function` | `default: DocSearchTransformClient => DocSearchTransformClient` | **optional**
+
+Useful for transforming the [Algolia Search Client][10], for example to [debounce search queries][9]
+
+## `disableUserPersonalization`
+
+> `type: boolean` | `default: false` | **optional**
+
+Disable saving recent searches and favorites to the local storage.
+
+## `initialQuery`
+
+> `type: string` | **optional**
+
+The search input initial query.
+
+## `navigator`
+
+> `type: Navigator` | **optional**
+
+An implementation of [Algolia Autocomplete][1]βs Navigator API to redirect the user when opening a link.
+
+Learn more on the [Navigator API][11] documentation.
+
+## `translations`
+
+> `type: Partial` | `default: docSearchTranslations` | **optional**
+
+Allow translations of any raw text and aria-labels present in the DocSearch button or modal components.
+
+
+docSearchTranslations
+
+
+```ts
+const translations: DocSearchTranslations = {
+ button: {
+ buttonText: 'Search',
+ buttonAriaLabel: 'Search',
+ },
+ modal: {
+ searchBox: {
+ clearButtonTitle: 'Clear',
+ clearButtonAriaLabel: 'Clear the query',
+ closeButtonText: 'Close',
+ closeButtonAriaLabel: 'Close',
+ placeholderText: undefined, // fallback: 'Search docs' or 'Search docs or ask AI a question'
+ placeholderTextAskAi: undefined, // fallback: 'Ask another question...'
+ placeholderTextAskAiStreaming: 'Answering...',
+ // can only be one of the following
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/enterkeyhint#value
+ enterKeyHint: 'search',
+ enterKeyHintAskAi: 'enter',
+ searchInputLabel: 'Search',
+ backToKeywordSearchButtonText: 'Back to keyword search',
+ backToKeywordSearchButtonAriaLabel: 'Back to keyword search',
+ newConversationPlaceholder: 'Ask a question',
+ conversationHistoryTitle: 'My conversation history',
+ startNewConversationText: 'Start a new conversation',
+ viewConversationHistoryText: 'Conversation history'
+ },
+ startScreen: {
+ recentSearchesTitle: 'Recent',
+ noRecentSearchesText: 'No recent searches',
+ saveRecentSearchButtonTitle: 'Save this search',
+ removeRecentSearchButtonTitle: 'Remove this search from history',
+ favoriteSearchesTitle: 'Favorite',
+ removeFavoriteSearchButtonTitle: 'Remove this search from favorites',
+ recentConversationsTitle: 'Recent conversations',
+ removeRecentConversationButtonTitle:
+ 'Remove this conversation from history',
+ },
+ errorScreen: {
+ titleText: 'Unable to fetch results',
+ helpText: 'You might want to check your network connection.',
+ },
+ noResultsScreen: {
+ noResultsText: 'No results found for',
+ suggestedQueryText: 'Try searching for',
+ reportMissingResultsText: 'Believe this query should return results?',
+ reportMissingResultsLinkText: 'Let us know.',
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'Ask AI: ',
+ noResultsAskAiPlaceholder: 'Didn't find it in the docs? Ask AI to help: ',
+ },
+ askAiScreen: {
+ disclaimerText:
+ 'Answers are generated with AI which can make mistakes. Verify responses.',
+ relatedSourcesText: 'Related sources',
+ thinkingText: 'Thinking...',
+ copyButtonText: 'Copy',
+ copyButtonCopiedText: 'Copied!',
+ copyButtonTitle: 'Copy',
+ likeButtonTitle: 'Like',
+ dislikeButtonTitle: 'Dislike',
+ thanksForFeedbackText: 'Thanks for your feedback!',
+ preToolCallText: 'Searching...',
+ duringToolCallText: 'Searching for ',
+ afterToolCallText: 'Searched for',
+ // If provided, these override the default rendering of aggregated tool calls:
+ aggregatedToolCallNode: undefined, // (queries: string[], onSearchQueryClick: (query: string) => void) => React.ReactNode
+ aggregatedToolCallText: undefined, // (queries: string[]) => { before?: string; separator?: string; lastSeparator?: string; after?: string }
+ // Text to show when user has stopped streaming a message
+ stoppedStreamingText: 'You stopped this response',
+ },
+ footer: {
+ selectText: 'Select',
+ submitQuestionText: 'Submit question',
+ selectKeyAriaLabel: 'Enter key',
+ navigateText: 'Navigate',
+ navigateUpKeyAriaLabel: 'Arrow up',
+ navigateDownKeyAriaLabel: 'Arrow down',
+ closeText: 'Close',
+ backToSearchText: 'Back to search',
+ closeKeyAriaLabel: 'Escape key',
+ poweredByText: 'Powered by',
+ },
+ newConversation: {
+ newConversationTitle: 'How can I help you today?',
+ newConversationDescription: 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.'
+ }
+ },
+};
+```
+
+
+
+
+## `getMissingResultsUrl`
+
+> `type: ({ query: string }) => string` | **optional**
+
+Function to return the URL of your documentation repository.
+
+
+
+
+```js
+docsearch({
+ // ...
+ getMissingResultsUrl({ query }) {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ }}
+/>
+```
+
+
+
+
+When provided, an informative message wrapped with your link will be displayed on no results searches. The default text can be changed using the [translations](#translations) property.
+
+
+
+
+
+## `keyboardShortcuts`
+
+> `type: KeyboardShortcuts` | **optional**
+
+Configuration for keyboard shortcuts that trigger the search modal.
+
+### Default behavior:
+
+- `Ctrl/Cmd+K` - Opens and closes the search modal
+- `/` - Opens the search modal (doesn't close)
+
+### Interface:
+
+```typescript
+interface KeyboardShortcuts {
+ 'Ctrl/Cmd+K'?: boolean; // default: true
+ '/'?: boolean; // default: true
+}
+```
+
+
+
+
+```js
+// Default - all shortcuts enabled
+docsearch({
+ // ...
+});
+
+// Disable slash shortcut
+docsearch({
+ // ...
+ keyboardShortcuts: { '/': false },
+});
+
+// Disable Ctrl/Cmd+K shortcut (also hides button hint)
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false },
+});
+
+// Disable all keyboard shortcuts
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false, '/': false },
+});
+```
+
+
+
+
+
+```jsx
+{
+ /* Default - all shortcuts enabled */
+}
+ ;
+
+{
+ /* Disable slash shortcut */
+}
+ ;
+
+{
+ /* Disable Ctrl/Cmd+K shortcut (also hides button hint) */
+}
+ ;
+
+{
+ /* Disable all keyboard shortcuts */
+}
+ ;
+```
+
+
+
+
+:::info[Keyboard Shortcut Behavior]
+
+- **Ctrl/Cmd+K**: Toggle shortcut that both opens and closes the modal
+- **/**: Character shortcut that only opens the modal (prevents interference with search typing)
+- **Escape**: Always works to close the modal regardless of Configuration
+
+:::
+
+## `resultsFooterComponent`
+
+> `type: ({ state }, { html }) => JSX.Element | string | Function` | **optional**
+
+The component to display below the search results. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ state }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ state }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the [current state](https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/types/AutocompleteState.ts) which allows you to retrieve the number of hits returned, the query etc.
+
+
+
+
+```js
+docsearch({
+ // ...
+ resultsFooterComponent({ state }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `maxResultsPerGroup`
+
+> `type: number` | **optional**
+
+The maximum number of results to display per search group. Default is 5.
+
+[You can find a working example without JSX in this sandbox](https://codesandbox.io/s/docsearch-v3-maxresultspergroup-without-jsx-ct9m22?file=/src/index.js)
+
+
+
+
+```js
+docsearch({
+ // ...
+ maxResultsPerGroup: 7,
+});
+```
+
+
+
+
+
+## `recentSearchesLimit`
+
+> `type: number` | `default: 7` | **optional**
+
+The maximum number of recent searches that are stored for the user. Default is 7.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesLimit: 12,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `recentSearchesWithFavoritesLimit`
+
+> `type: number` | `default: 4` | **optional**
+
+The maximum number of recent searches that are stored when the user has favorited searches. Default is 4.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesWithFavoritesLimit: 5,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `portalContainer` (React-only)
+
+> `type: Element | DocumentFragment` | `default: document.body` | **optional**
+
+The element where the DocSearch modal will be portaled. Use this when you need the overlay to render in a custom DOM nodeβfor example when working inside a shadow root, a specific layout container, or a modal manager. When omitted, the modal portals to `document.body`.
+
+:::warning
+
+This prop only exists in `@docsearch/react`. If you are using **`@docsearch/js`**, use the [`container`](#container) option insteadβthe value you pass there is both the **mount point** of the search button _and_ the portal target for the modal.
+
+:::
+
+
+
+
+```jsx
+// assume you have a dedicated modal root in your html
+;
+
+const portalEl = document.getElementById('modal-root');
+
+ ;
+```
+
+
+
+
+
+```js
+docsearch({
+ // the element that will **contain the button** and **host the modal portal**
+ container: '#modal-root',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+});
+```
+
+
+
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[6]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[7]: https://www.algolia.com/doc/api-reference/search-api-parameters/
+[8]: https://github.com/algolia/docsearch/blob/main/packages/docsearch-react/src/Hit.tsx
+[9]: https://codesandbox.io/s/docsearch-v3-debounced-search-gnx87
+[10]: https://www.algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/?client=javascript
+[11]: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/keyboard-navigation/
+[12]: https://www.algolia.com/products/ai/agent-studio
+[13]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/composable-api.mdx b/packages/website/versioned_docs/version-v4/composable-api.mdx
new file mode 100644
index 00000000..314b6e1b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/composable-api.mdx
@@ -0,0 +1,315 @@
+---
+title: Composable API
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+The Composable API is available from version `>= 4.3`
+:::
+
+DocSearch has a new Composable API for rendering the DocSearch button and modal. This API was
+introduced to help with more explicit control over where and how the components are rendered within a page.
+
+## Introduction
+
+The Composable API was introduced to help give more flexibility on how you render and use DocSearch on your website. With it,
+you have more control of where, when and how you want to bundle the components and render them.
+
+With Composable API comes two new NPM packages:
+
+- `@docsearch/core` - Shared core logic for managing different states of DocSearch
+- `@docsearch/modal` - The actual components used for the DocSearch Modal
+
+:::warning
+Because of the nature of composability, this API is only available within React, and not within the `@docsearch/js` package.
+:::
+
+## Getting Started
+
+In order to start using the Composable API, you will need to install the following three packages:
+
+
+
+
+```bash
+npm install @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+The most simple implementation would be as follows:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+:::info
+The actual components MUST be rendered within the `` Provider in order for them to communicate with the global state.
+:::
+
+This setup is slightly more involved with now rendering three different components:
+
+- `` is the parent element which controls and shares all state with the child components
+- ` ` is the actual button element that is rendered and triggers the DocSearch Modal to open
+- ` ` is the main modal containing the search form, search results, and Ask AI
+
+
+### Ask AI
+
+Using Ask AI with the Composable API is quite similar to the normal way of using DocSearch. All that is needed is the `askAi` configuration:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+You can find more information on Ask AI, and its setup in its [dedicated docs][2].
+
+### Advanced
+
+```tsx
+export default function AdvancedSearch(): JSX.Element {
+ return (
+
+
+
+
+ );
+}
+```
+
+### Bundle saving exports
+
+To help aid in trimming initial bundle size, the `@docsearch/modal` package exposes explicit file exports as well:
+
+```ts
+import { DocSearchButton } from '@docsearch/modal/button';
+import { DocSearchModal } from '@docsearch/modal/modal';
+```
+
+Here is a basic example of delaying the loading of the `DocSearchModal` code until the search button is clicked:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton } from '@docsearch/modal/button';
+import type { DocSearchModal as DocSearchModalType } from '@docsearch/modal/modal';
+import { useState } from 'react';
+
+let DocSearchModal: typeof DocSearchModalType | null = null;
+
+async function importDocSearchModalIfNeeded() {
+ if (DocSearchModal) {
+ return;
+ }
+
+ const { DocSearchModal: Modal } = await import('@docsearch/modal/modal');
+
+ DocSearchModal = Modal;
+}
+
+export default function DynamicModal() {
+ const [modalLoaded, setModalLoaded] = useState(false);
+
+ const loadModal = () => {
+ importDocSearchModalIfNeeded().then(() => {
+ setModalLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {modalLoaded && DocSearchModal && (
+
+ )}
+
+ );
+}
+```
+
+## Components
+
+### ` `
+
+The ` ` component from the `@docsearch/core` package is the main state handler for all of DocSearch.
+It utilizes [React Context][1] to enable sharing its state across nested components.
+
+#### Props
+
+```ts
+interface DocSearchProps {
+ // React children to be rendered within the DocSearch Provider
+ children: Array | JSX.Element | React.ReactNode | null;
+ // Theme to be set enabling style changes for `light` or `dark` themes
+ theme?: 'light' | 'dark';
+ // Initial starting query for keyword search
+ initialQuery?: string;
+ // Manage supported keyboard shortcuts for opening/closing the DocSearch Modal
+ keyboardShortcuts?: {
+ 'Ctrl/Cmd+K': boolean,
+ '/': boolean,
+ };
+}
+```
+
+### ` `
+
+The main DocSearch search button to trigger the DocSearch Modal.
+
+#### Props
+
+```ts
+interface DocSearchButtonProps {
+ // Optional callback for when the button is clicked. The original click event is passed.
+ onClick?: (event: React.MouseEvent) => void;
+ // Translation strings specific to the button.
+ translations: {
+ buttonText?: string;
+ buttonAriaLabel?: string;
+ };
+}
+```
+
+### ` `
+
+The main keyword search Modal used to search your documentation.
+
+#### Props
+
+```ts
+interface DocSearchModalProps {
+ /**
+ * Algolia application id used by the search client.
+ */
+ appId: string;
+ /**
+ * Public api key with search permissions for the index.
+ */
+ apiKey: string;
+ /**
+ * Name of the algolia index to query.
+ *
+ * @deprecated `indexName` will be removed in a future version. Please use `indices` property going forward.
+ */
+ indexName?: string;
+ /**
+ * List of indices and _optional_ searchParameters to be used for search.
+ *
+ * @see {@link https://docsearch.algolia.com/docs/api#indices}
+ */
+ indices?: Array;
+ /**
+ * Configuration or assistant id to enable ask ai mode. Pass a string assistant id or a full config object.
+ */
+ askAi?: DocSearchAskAi | string;
+ // ...
+}
+```
+
+More property documentation can be found in the [DocSearch API Reference][3] page.
+
+[1]: https://react.dev/reference/react/createContext
+[2]: /docs/v4/v4/askai
+[3]: /docs/api
diff --git a/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
new file mode 100644
index 00000000..cc913ea4
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
@@ -0,0 +1,96 @@
+---
+title: New Crawler UI/UX
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+The Algolia Crawler Visual UI provides an updated, user-friendly way to manage your crawl settings and monitor your indexing process. This guide covers the main features of the new interface.
+
+## DocSearch Tab
+
+The Crawler UI now includes a dedicated **DocSearch** tab. This tab provides everything you need to implement DocSearch on your site, including:
+
+- **Implementation code**: Copy-paste ready code snippets for integrating DocSearch into your frontend.
+- **API keys**: Your unique Application ID and Search API Key for connecting to your Algolia index.
+- **Quick links**: Access to review your records, explore documentation, and join the support Discord.
+
+
+
+
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `Monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+You can update your crawler configuration in two ways:
+
+**Visual Configuration UI:**
+Quickly edit common options without writing code using the new Visual Configuration interface.
+
+
+
+
+
+**Code Editor:**
+For advanced configuration, use the live code editor to directly modify your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to debug selectors or see how the crawler interprets your site.
+
+
+
+
+
+## Suggestions
+
+The **Suggestions** section in the Crawler UI provides actionable feedback to help you improve your crawl and data extraction. After each crawl, you'll see recommendations for:
+
+- Fixing redirect or domain issues
+- Addressing ignored or failed URLs
+- Adding missing sitemaps
+
+Each suggestion includes a description, a solution, and quick links to relevant documentation or monitoring tools, so you can resolve issues efficiently and optimize your search experience.
+
+
+
+
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/crawler.mdx b/packages/website/versioned_docs/version-v4/crawler.mdx
new file mode 100644
index 00000000..f2e4b3f9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler.mdx
@@ -0,0 +1,120 @@
+---
+title: DocSearch x Algolia Crawler
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][3] team know.
+
+You can also read our [Crawler FAQ](https://www.algolia.com/doc/tools/crawler/troubleshooting/crawl-status/), to understand how it behaves:
+
+- [One of my pages wasn't crawled](https://www.algolia.com/doc/tools/crawler/troubleshooting/extraction-issues/#a-page-wasnt-crawled)
+- [Why are my pages skipped?](https://www.algolia.com/doc/tools/crawler/troubleshooting/fetching-issues/)
+
+For questions related to the DocSearch program, please see our [DocSearch program FAQ](/docs/docsearch-program).
+
+## How often will you crawl my website?
+
+Crawls are scheduled at a random time once a week. You can [configure this schedule from the config file](https://www.algolia.com/doc/tools/crawler/apis/configuration/schedule/) or trigger one manually from [the Crawler interface][2].
+
+## Why do I have duplicate content in my results?
+
+This can happen when you have more than one URL pointing to the same content, for example with `./docs`, `./docs/` and `./docs/index.html`.
+
+We recommend configuring canonical URLs on your website, you can read more on the ["Consolidate duplicate URLs" guide by Google](https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls).
+
+Ultimately, it is possible to set the [`exclusionPatterns`](https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/) to all the patterns you want to exclude.
+
+## Are the [`docsearch-scraper`](https://github.com/algolia/docsearch-scraper) and [`docsearch-configs`](https://github.com/algolia/docsearch-configs) repository still maintained?
+
+We've deprecated our legacy infrastructure, but you can still use it to [run your own instance](/docs/legacy/run-your-own) and plug it to [DocSearch v3](/docs/v3/docsearch)!
+
+## How to migrate
+
+> Every owner should have received a migration email from Algolia with the details. If you were not part of the previous `index` owners, or the maintainer has changed, you can request access via [our support page](https://www.algolia.com/support/).
+
+All the steps are detailed in the email you've received, but in order to use the new infrastructure you need to:
+
+- Join the Algolia application with the invite included in the email
+- Update your frontend integration with the credentials received in the email.
+
+
+
+
+```js app.js
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_NEW_ALGOLIA_APP_ID',
+ apiKey: 'YOUR_NEW_ALGOLIA_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME', // it does not change
+});
+```
+
+
+
+
+
+```jsx App.js
+
+```
+
+
+
+
+
+## What should I do with my legacy config and credentials?
+
+You can forget about them, we will do the cleaning once all of our users have migrated to the new infrastructure!
+
+You should use [the dedicated web interface][2] to make any changes to your index.
+
+## Why do I see two Algolia apps in my dashboard?
+
+We did not remove access to the legacy DocSearch application (`BH4D9OD16A`) to give you the time to get familiar with our new infrastructure. `BH4D9OD16A` will remain available until the migration has been completed for all the DocSearch users.
+
+## Search yields no results
+
+If your search does not yield any results, but there is no error in [your browser developer tools](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), there might be an issue with your index.
+
+Make sure that:
+
+1. [Your Crawler config](/docs/record-extractor) matches your website structure
+
+We provide [config templates](/docs/templates) for many website generators, but you can also use them as a base. To debug your selectors, we recommend using [the URL tester](/docs/manage-your-crawls/#url-tester).
+
+2. Your index settings are up to date (you'll see a banner in [the search preview](/docs/manage-your-crawls/#search-preview) if not)
+
+The Crawler only applies `index settings` at index creation time, to keep the Algolia dashboard as the source of truth. If you have drastically changed your config, or moved to a website generator, we recommend you to delete your index from the Algolia dashboard before starting a new crawl.
+
+## Can I delete my crawler?
+
+No. Well, you can but once you do things will not work correctly. We automatically create a default crawler that is associated with your DocSearch application and deleting it with the intention of creating a new one will not work as expected.
+
+## What if I delete my DocSearch Crawler?
+
+The fastest way will be to connect with us on our [Discord](https://alg.li/discord). Alternatively, email us at the address below and we will get to it as soon as we can.
+
+## Can I use the Crawler on password protected sites?
+
+The Crawler as used with DocSearch applications cannot be used for password protected sites that require a login. If you need this functionality, you need to utilize a regular Algolia plan https://www.algolia.com/pricing and add a crawler to it. Note that while it is free to add a pay-as-you-go crawler, the free tier does have limitations.
+
+## Links related to the migration
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+[1]: https://alg.li/discord
+[2]: https://dashboard.algolia.com/crawler
+[3]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/create-crawler.mdx b/packages/website/versioned_docs/version-v4/create-crawler.mdx
new file mode 100644
index 00000000..5e7c5124
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/create-crawler.mdx
@@ -0,0 +1,78 @@
+---
+title: Create a New Crawler
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+# Create a New Crawler
+
+:::info
+New DocSearch apps created after **July 2nd, 2024** can now use the Algolia Crawler UI to set up and manage their crawls. This guide walks you through the process of adding your domain, verifying ownership, creating a crawler, and running your first test crawl. You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+
+If you signed up before July 2nd, 2024, you can still use the Crawler UI, but creating and managing a Crawler is more streamlined for users who joined after that date.
+
+Learn more about the [New Crawler UI/UX features](./crawler-configuration-visual).
+:::
+
+## Add domains
+
+1. Sign in to the [Algolia dashboard](https://dashboard.algolia.com/crawler).
+2. In the left sidebar, select **Data sources**.
+3. Select **Crawler**:
+ - Click **Add your domain** and enter the domains or subdomains you want to crawl (e.g., `example.com`, `www.example.com`).
+ - If youβve already added a domain, click the **Domains** tab.
+4. Click **Add domain**.
+
+
+
+
+
+> **Note:** You must verify your domain within a 7-day grace period after adding it. Additionally, your domain must be approved for use by the DocSearch team before you can proceed with crawling.
+
+## Verify your domain
+
+You must verify ownership of each domain you want to crawl. The default method is email verification, but you can also use a meta tag, HTML file, robots.txt, or DNS record.
+
+### Meta tag
+1. In the **Meta tag** tab, click **Copy** to copy the verification tag.
+2. Add the tag to your site's `` section.
+3. Publish your site and click **Verify now** in the Crawler dashboard.
+
+### HTML file
+1. In the **HTML file** tab, click **Copy** to copy the verification file content.
+2. Save it as a new HTML file and upload it to your web server.
+3. Add the fileβs URL in the dashboard and click **Verify now**.
+
+### robots.txt
+1. In the **Robots.txt** tab, click **Copy** to copy the verification code.
+2. Paste it into your site's `robots.txt` file.
+3. Publish and click **Verify now**.
+
+### DNS
+1. In the **DNS** tab, copy the provided DNS TXT record.
+2. Add it to your DNS providerβs settings.
+3. Click **Verify now** after the record propagates (may take up to 72 hours).
+
+## Create a new crawler
+
+Once your domain is verified and approved by our DocSearch team:
+1. Go to the **Crawler** page in the dashboard.
+2. Click **New Crawler** and fill in:
+ - **Crawler name** (descriptive)
+ - **App ID** (your Algolia application ID)
+ - **Start URL** (usually your home page)
+ - **Crawler template** (choose a template or default)
+3. Click **Create** to finish and run a test crawl.
+
+## Run the test crawl
+
+The initial crawl will visit up to 100 URLs to test access and extraction. You can monitor progress in the **Overview** page. After completion, review the extracted records in the Algolia dashboard.
+
+## Next steps
+
+- Edit your crawler configuration for scheduled crawls, inclusion/exclusion rules, and extraction settings.
+- Use the Crawlerβs suggestions for further optimization.
+- For more details, see the [official Algolia documentation](https://www.algolia.com/doc/tools/crawler/getting-started/create-crawler/).
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/docsearch-program.md b/packages/website/versioned_docs/version-v4/docsearch-program.md
new file mode 100644
index 00000000..29d65ae2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch-program.md
@@ -0,0 +1,131 @@
+---
+title: DocSearch program
+---
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][4] team know.
+
+For questions related to the DocSearch x Algolia Crawler, please see our [Crawler FAQ](/docs/crawler).
+
+## What do I need to install on my side?
+
+You just need to [implement DocSearch in your frontend](/docs/docsearch) with the credentials received by email when your application has been deployed.
+
+DocSearch leverages the [Algolia Crawler](https://www.algolia.com/products/search-and-discovery/crawler/), which offers a web [interface](https://dashboard.algolia.com/crawler) to create, monitor, edit, start your Crawlers. If you have any questions regarding it, please see our [Crawler FAQ](/docs/crawler).
+
+## How much does it cost?
+
+It's free!
+
+We know that paying for search infrastructure is a cost not all open source projects can afford. That's why we decided to keep DocSearch free for everyone. All we ask in exchange is that you keep the "Search by [Algolia][2]" logo displayed next to the search results.
+
+If this is not possible for you, you're free to [open your own Algolia account](https://www.algolia.com/pricing) and run [DocSearch on your own][3] without this limitation. In that case, though, depending on the size of your documentation, you might need a paid account (free accounts can hold as much as 10k records).
+
+## What data are you collecting?
+
+We save the data we extract from your website markup, which we put in a custom JSON format instead of HTML. This is the data we put in the Algolia DocSearch index. The selectors in your config define what data to scrape.
+
+As the website owner, we also give you access to your own Algolia application. This will let you see how your website is indexed in Algolia, detailed analytics about the anonymized searches in your website, team managements, and more!
+
+## Where is my data hosted?
+
+We host the DocSearch data on Algolia's servers, with replications around the globe. You can find more details about the actual [server specs here](https://www.algolia.com/doc/guides/infrastructure/servers/), and more complete information in our [privacy policy](https://www.algolia.com/policies/privacy).
+
+## How do I upgrade my DocSearch app?
+
+Depending on what you are looking for you have a few options!
+
+### Upgrade #1: I want a specific feature, like Rules, added to my existing DocSearch application
+
+[Reach out to us](https://algolia.com/support) and we may be able to help!
+
+### Upgrade #2: I want to remove the Algolia logo
+
+This would disqualify you from the free DocSearch program. We do offer an open-source
+[legacy version](https://docsearch.algolia.com/docs/legacy/run-your-own) of the DocSearch Crawler that you can use and
+host yourself or you can use our [API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript) but you will need to use a new Algolia application and pay for its usage.
+
+### Upgrade #3: Algolia is awesome, I want to use it for my whole site
+
+That's awesome! Please reach out to our [sales team](https://www.algolia.com/contactus/)
+who can help you figure out the right plan for you. Once you have your new application
+created you can simply copy and paste [your Crawler config](https://docsearch.algolia.com/docs/templates) into your new application's
+Crawler.
+
+## Can I use DocSearch on non-doc pages?
+
+The free DocSearch we provide will **only** crawl open-source projects documentation pages or technical blogs. To use it on other parts of your website, you'll need to create your own Algolia account and either:
+
+- Run the [DocSearch crawler][3] on your own
+- Use one of our other [framework integrations or API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript)
+
+## Can you index code samples?
+
+Yes, but we do not recommend it.
+
+Code samples are a great way for humans to understand how people use a specific method. It often requires boilerplate code though, repeated across examples, which adds noise to the results.
+
+## A documentation website I like does not use DocSearch. What can I do?
+
+We'd love to help!
+
+If one of your favorite tool documentation websites is missing DocSearch, we encourage you to file an issue in their repository explaining how DocSearch could help. Feel free to [let us know on Discord][1] as well and we'll provide all the help we can.
+
+## How did we build this website?
+
+We build this website with [Docusaurus v2](https://docusaurus.io/). We were helped by a great man who inspired us a lot, Endi. We want [to pay a tribute to this exceptional human being that will be always part of the DocSearch project](https://docusaurus.io/blog/2020/01/07/tribute-to-endi). Rest in peace mate!
+
+## Can I share the `apiKey` in my repo?
+
+The `apiKey` the DocSearch team provides is [a search-only key](https://www.algolia.com/doc/guides/security/api-keys/#search-only-api-key) and can be safely shared publicly. You can track it in your version control system (e.g. git). If you are running the scraper on your own, please make sure to create a search-only key and [do not share your Admin key](https://www.algolia.com/doc/guides/security/api-keys/#admin-api-key).
+
+## Why is the email API key different in the dashboard?
+
+Every Algolia app comes with a default "Search API Key" which can be seen in the dashboard. That key allow you to list indices, settings, and search on **every** index owned by your application. In the case of a DocSearch application, in your acceptance email we provide a search **ONLY** API key scoped to only your DocSearch index. If for any reason you need to recover the API key sent in the email, just connect with our [support](https://algolia.com/support) team.
+
+## How do I rotate my API keys?
+
+Please reach out to our [support](https://algolia.com/support) team.
+
+## Can I have multiple projects under the same Algolia application?
+
+We recommend having a single Algolia application per project. Please [apply](https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply) if you'd like to use DocSearch in an other project of yours.
+
+### Why?
+
+The information of the initially applied project is used everywhere when we deploy your app:
+
+- The scope of your API keys
+- The name of your Algolia application/Crawler
+- The indices we generate
+- The allowed domains of your Crawler
+
+This allows us to easily scope issues when reaching out for support.
+
+## Support
+
+:::caution
+
+Please make sure to **first read the documentation before reaching out**.
+
+Here are some links to help you:
+
+- [The Algolia Crawler documentation](https://www.algolia.com/doc/tools/crawler/getting-started/overview/)
+- [The Algolia Crawler FAQ](/docs/crawler)
+- [The DocSearch FAQ](/docs/docsearch-program)
+- [The Algolia documentation](https://www.algolia.com/doc/)
+
+You can also take a look at [the Algolia academy](https://academy.algolia.com/trainings) to understand more about Algolia.
+
+:::
+
+Please be informed that while Algolia does not provide support for DocSearch itself, we can support requests for the following products:
+
+- The Algolia Crawler, reach out [via the support page](https://algolia.com/support).
+- The Algolia Dashboard, reach out [via the support page](https://algolia.com/support).
+
+For any issue related to [the DocSearch UI library](https://github.com/algolia/docsearch), please open a [GitHub issue](https://github.com/algolia/docsearch/issues).
+
+[1]: https://alg.li/discord
+[2]: https://www.algolia.com/
+[3]: /docs/legacy/run-your-own
+[4]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/docsearch.mdx b/packages/website/versioned_docs/version-v4/docsearch.mdx
new file mode 100644
index 00000000..9c17704f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch.mdx
@@ -0,0 +1,418 @@
+---
+title: Getting Started with v4
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+DocSearch v4 provides a significant upgrade over previous versions, offering enhanced accessibility, responsiveness, and an improved search experience for your documentation. Built on [Algolia Autocomplete][1], DocSearch v4 ensures a seamless integration trusted by leading documentation sites worldwide.
+
+## Installation
+
+> Looking for the Composable API documentation? You can find it [here][17].
+
+DocSearch packages are available on the [npm registry][10].
+
+### Docusaurus users
+
+If your docs site is powered by Docusaurus, use [`@docsearch/docusaurus-adapter`](/docs/docusaurus-adapter) for the latest DocSearch features (including new Ask AI capabilities such as sidepanel support), while keeping `@docusaurus/preset-classic`.
+
+
+
+
+```bash
+yarn add @docsearch/js@4
+# or with npm
+npm install @docsearch/js@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+```bash
+yarn add @docsearch/react@4
+# or
+npm install @docsearch/react@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``:
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+
+### Optimize first query performance
+
+Enhance your users' first search experience by using `preconnect`, see [Performance optimization](#preconnect) below
+
+## Implementation
+
+
+
+
+DocSearch requires a dedicated container in your HTML
+
+```html
+
+```
+
+Initialize DocSearch by passing your container:
+
+```js app.js
+import docsearch from '@docsearch/js';
+
+import '@docsearch/css';
+
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+});
+```
+
+DocSearch generates an accessible, fully-functional search input for you automatically.
+
+
+
+
+
+Integrating DocSearch into your React app is straightforward:
+
+```jsx App.js
+import { DocSearch } from '@docsearch/react';
+
+import '@docsearch/css';
+
+function App() {
+ return (
+
+ );
+}
+
+export default App;
+```
+
+DocSearch generates a fully accessible search input out-of-the-box.
+
+
+
+
+
+### Quick Testing (without credentials)
+
+If you'd like to test DocSearch immediately without your own credentials, use our demo configuration:
+
+
+
+
+```js
+docsearch({
+ appId: 'PMZUYBQDAK',
+ apiKey: '24b09689d5b4223813d9b8e48563c8f6',
+ indexName: 'docsearch',
+ askAi: 'askAIDemo',
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+Or use our new dedicated [DocSearch Playground](https://community.algolia.com/docsearch-playground/)
+
+### Using DocSearch with Ask AI
+
+DocSearch v4 introduces support for Ask AI, Algolia's advanced, AI-powered search capability. Ask AI enhances the user experience by providing contextually relevant and intelligent responses directly from your documentation. You can also use the same `askAi` configuration object to route chat through Agent Studio.
+
+To enable Ask AI, you can add your Algolia Assistant ID as a string, or use an object for more advanced configuration (such as specifying a different index, credentials, search parameters, or enabling Agent Studio):
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+});
+```
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ indexName: 'YOUR_MARKDOWN_INDEX', // Optional: use a different index for Ask AI
+ apiKey: 'YOUR_SEARCH_API_KEY', // Optional: use a different API key for Ask AI
+ appId: 'YOUR_APP_ID', // Optional: use a different App ID for Ask AI
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'], // Optional: filter Ask AI context
+ },
+ suggestedQuestions: true // Optional: enable loading suggested questions on the Ask AI new conversation screen
+ },
+});
+```
+
+
+
+
+- Use the string form for a simple setup.
+- Use the object form to customize which index, credentials, or filters Ask AI uses.
+- The suggested questions feature is controlled on the [Dashboard](https://dashboard.algolia.com) in the Ask AI section.
+
+### Using Agent Studio with DocSearch
+
+To use [Algolia Agent Studio](https://www.algolia.com/doc/guides/algolia-ai/agent-studio) as the chat backend, set `agentStudio: true` inside the `askAi` object.
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+- `agentStudio` is configured inside `askAi`, not as a top-level DocSearch prop.
+- When `agentStudio: true`, `searchParameters` must be keyed by index name.
+- Agent Studio search parameters support `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+### Filtering search results
+
+#### Keyword search
+
+If your website uses [DocSearch meta tags][13] or if you've added [custom variables to your config][14], you'll be able to use the [`facetFilters`][16] option to scope your search results to a [`facet`][15]
+
+This is useful to limit the scope of the search to one language or one version.
+
+
+
+
+```js
+docsearch({
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+#### Ask AI
+
+Filtering also applies when using Ask AI. This is useful to limit the scope of the LLM's search to only relevant results.
+
+:::info
+We recommend using the `facetFilters` option when using Ask AI with multiple languages or any multi-faceted index.
+:::
+
+
+
+```js
+docsearch({
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+ },
+});
+```
+
+
+
+```jsx
+
+```
+
+
+
+
+:::tip
+You can use `facetFilters: ['type:content']` to ensure Ask AI only uses records where the `type` attribute is `content` (i.e., only records that actually have content). This is useful if your index contains records for navigation, metadata, or other non-content types.
+:::
+
+### Sending events
+
+You can send search events to your DocSearch index by passing in the `insights` parameter when creating your DocSearch instance.
+
+
+
+
+```diff
+docsearch({
+ // other options
++ insights: true,
+});
+```
+
+
+
+
+
+```diff
+
+```
+
+
+
+
+
+## Performance optimization
+
+### Preconnect
+
+Improve the loading speed of your initial search request by adding this snippet into your website's `` section:
+
+```html
+
+```
+
+This helps the browser establish a quick connection with Algolia, enhancing user experience, especially on mobile devices.
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/integrations
+[6]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[7]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[8]: https://codesandbox.io/s/docsearch-js-v3-playground-z9oxj
+[9]: https://codesandbox.io/s/docsearch-react-v3-playground-619yg
+[10]: https://www.npmjs.com/
+[11]: /docs/api#container
+[12]: /docs/api
+[13]: /docs/required-configuration#introduce-global-information-as-meta-tags
+[14]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: https://www.algolia.com/doc/guides/managing-results/refine-results/filtering/#facetfilters
+[17]: /docs/composable-api
diff --git a/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
new file mode 100644
index 00000000..4ae81493
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
@@ -0,0 +1,61 @@
+---
+title: Docusaurus Adapter (Recommended)
+---
+
+If you use Docusaurus, install and configure `@docsearch/docusaurus-adapter` to get the latest DocSearch features on your current Docusaurus version.
+
+## Why this adapter exists
+
+Docusaurus ships an excellent built-in Algolia integration (`@docusaurus/theme-search-algolia`), but Docusaurus (Meta-maintained) and DocSearch don't always release on the same cadence.
+
+The DocSearch adapter lets us ship new DocSearch features (including Ask AI sidepanel support) without forcing users to wait for a Docusaurus integration update.
+
+In practice, this means:
+
+- Faster access to new DocSearch capabilities.
+- Better compatibility for Ask AI + sidepanel features.
+- A dedicated search integration path maintained in the DocSearch project.
+
+## Install
+
+```bash
+yarn add @docsearch/docusaurus-adapter
+# or
+npm install @docsearch/docusaurus-adapter
+```
+
+## Configuration
+
+Keep `@docusaurus/preset-classic`, add the adapter plugin, and configure search under `themeConfig.docsearch` (preferred):
+
+```js title="docusaurus.config.mjs"
+export default {
+ plugins: ['@docsearch/docusaurus-adapter'],
+ themeConfig: {
+ docsearch: {
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+ askAi: {
+ assistantId: 'YOUR_ASSISTANT_ID',
+ sidePanel: true,
+ },
+ contextualSearch: true,
+ },
+ },
+};
+```
+
+## `docsearch` vs `algolia` keys
+
+- `themeConfig.docsearch` is the canonical key.
+- `themeConfig.algolia` is supported as a backward-compatible alias.
+- Do not define both keys at the same time.
+
+Using `themeConfig.docsearch` helps avoid built-in Docusaurus search-theme validation conflicts when you want newer DocSearch options like `askAi.sidePanel`.
+
+## Customizing Search UI (SearchBar/SearchPage)
+
+If you want to customize search behavior or UI, customize the adapter theme components (`@theme/SearchBar` and `@theme/SearchPage`) from the adapter integration path.
+
+This keeps your customization aligned with DocSearch feature updates and avoids coupling to the built-in Docusaurus Algolia theme implementation.
diff --git a/packages/website/versioned_docs/version-v4/examples.mdx b/packages/website/versioned_docs/version-v4/examples.mdx
new file mode 100644
index 00000000..6241cd50
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/examples.mdx
@@ -0,0 +1,428 @@
+---
+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.
diff --git a/packages/website/versioned_docs/version-v4/how-does-it-work.mdx b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
new file mode 100644
index 00000000..3cc42427
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
@@ -0,0 +1,51 @@
+---
+title: How does it work?
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+Getting up and ready with DocSearch is a straightforward process that requires three steps: you apply, we configure the crawler and the Algolia app for you, and you integrate our UI in your frontend. You only need to copy and paste a JavaScript snippet.
+
+
+
+## You apply
+
+The first thing you'll need to do is to apply for DocSearch by [filling out the form on this page][1] (double check first that [you qualify][2]). We are receiving a lot of requests, so this form makes sure we won't be forgetting anyone.
+
+We guarantee that we will answer every request, but as we receive a lot of applications, please give us a couple of days to get back to you :)
+
+## We create your Algolia application and a dedicated crawler
+
+Once we receive [your application][1], we'll have a look at your website, create an Algolia application and a dedicated [crawler][5] for it. Your crawler comes with [a configuration file][6] which defines which URLs we should crawl or ignore, as well as the specific CSS selectors to use for selecting headers, subheaders, etc.
+
+This step still requires some manual work and human brain, but thanks to the +4,000 configs we already created, we're able to automate most of it. Once this creation finishes, we'll run a first indexing of your website and have it run automatically at a random time of the week.
+
+**With the Crawler, comes [a dedicated interface][8] for you to:**
+
+- Start, schedule and monitor your crawls
+- Edit and test your config file directly with [DocSearch v3][7]
+
+**With the Algolia application comes access to the dashboard for you to:**
+
+- Browse your index and see how your content is indexed
+- Various analytics to understand how your search performs and ensure that your users are able to find what theyβre searching for
+- Trials for other Algolia features
+- Team management
+
+## You update your website
+
+We'll then get back to you with the JavaScript snippet you'll need to add to your website. This will bind your [DocSearch component][7] to display results from your Algolia index on each keystroke in a pop-up modal.
+
+Now that DocSearch is set, you don't have anything else to do. We'll keep crawling your website and update your search results automatically. All we ask is that you keep the "Search by Algolia" logo next to your search results.
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: /docs/who-can-apply
+[3]: https://github.com/algolia/docsearch-configs/tree/master/configs
+[4]: /docs/styling
+[5]: https://www.algolia.com/products/search-and-discovery/crawler/
+[6]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[7]: /docs/v3/docsearch
+[8]: https://crawler.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/integrations.md b/packages/website/versioned_docs/version-v4/integrations.md
new file mode 100644
index 00000000..59806313
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/integrations.md
@@ -0,0 +1,45 @@
+---
+title: Supported Integrations
+---
+
+We worked with **documentation website generators** to have DocSearch directly embedded as a first class citizen in the websites they produce.
+
+## Our great integrations
+
+So, if you're using one of the following tools, check out their documentation to see how to enable DocSearch on your website:
+
+- [Docusaurus v1][1] - [How to enable search][2]
+- [Docusaurus v2 & v3][3] - [DocSearch adapter (recommended)][23] / [Using Algolia DocSearch][4]
+- [VuePress][5] - [Algolia Search][6]
+- [VitePress][21] - [Search][22]
+- [Starlight][7] - [Algolia Search][8]
+- [LaRecipe][9] - [Algolia Search][10]
+- [Orchid][11] - [Algolia Search][12]
+- [Smooth DOC][13] - [DocSearch][14]
+- [Docsy][15] - [Configure Algolia DocSearch][16]
+- [Lotus Docs][19] - [Enabling the DocSearch Plugin][20]
+- [Sphinx](https://www.sphinx-doc.org/en/master/) - [Algolia DocSearch for Sphinx](https://sphinx-docsearch.readthedocs.io/)
+
+If you're maintaining a similar tool and want us to add you to the list, [feel free to make a pull request](https://github.com/algolia/docsearch/edit/main/packages/website/docs/integrations.md) and [contribute to Code Exchange](https://www.algolia.com/developers/code-exchange/contribute/). We're happy to help.
+
+[1]: https://v1.docusaurus.io/
+[2]: https://v1.docusaurus.io/docs/en/search
+[3]: https://docusaurus.io/
+[4]: https://docusaurus.io/docs/search#using-algolia-docsearch
+[5]: https://vuepress.vuejs.org/
+[6]: https://vuepress.vuejs.org/theme/default-theme-config.html#algolia-search
+[7]: https://starlight.astro.build/
+[8]: https://starlight.astro.build/guides/site-search/#algolia-docsearch
+[9]: https://larecipe.saleem.dev/docs/2.2/overview
+[10]: https://larecipe.saleem.dev/docs/2.2/search#available-engines
+[11]: https://orchid.run
+[12]: https://orchid.run/plugins/orchidsearch#algolia-docsearch
+[13]: https://next-smooth-doc.vercel.app/
+[14]: https://next-smooth-doc.vercel.app/docs/docsearch/
+[15]: https://www.docsy.dev/
+[16]: https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch
+[19]: https://lotusdocs.dev/docs/
+[20]: https://lotusdocs.dev/docs/guides/features/docsearch/#enabling-the-docsearch-plugin
+[21]: https://vitepress.dev/
+[22]: https://vitepress.dev/reference/default-theme-search#algolia-search
+[23]: /docs/docusaurus-adapter
diff --git a/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
new file mode 100644
index 00000000..3dbf5caa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
@@ -0,0 +1,67 @@
+---
+title: "[Pre-v4] Manage your crawls"
+---
+
+:::caution
+This UI is deprecated and no longer maintained. For the latest instructions, please use the new documentation: [Crawler Configuration Visual UI](./crawler-configuration-visual). You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+:::
+
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+DocSearch comes with the [Algolia Crawler web interface](https://crawler.algolia.com/) that allows you to configure how and when your Algolia index will be populated.
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+The live editor allows you to update your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## Search preview
+
+From the [`editor`](#update-your-config), you have access to a `Search preview` tab to browse search results with [`DocSearch v3`](/docs/v3/docsearch).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to [debug selectors](https://www.algolia.com/doc/tools/crawler/getting-started/crawler-configuration/#debugging-selectors) or how we crawl your website.
+
+
+
+
diff --git a/packages/website/versioned_docs/version-v4/mcp/installation.mdx b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
new file mode 100644
index 00000000..300b20c2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
@@ -0,0 +1,32 @@
+---
+title: Install DocSearch MCP
+sidebar_label: Installation
+---
+
+import MCPInstall from '@site/src/components/mcp/MCPInstall';
+
+DocSearch MCP is a remote MCP server. Point any MCP-compatible client at this endpoint β no authentication required:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+The fastest path is the **DocSearch CLI** β one command that configures your client for you. Prefer to set things up yourself? Install it as a **plugin** (ships the MCP server plus client guidance like rules, skills, and commands) or **manually** (just the MCP server config). Pick your client below.
+
+
+
+## Verify the install
+
+Ask your MCP client a public documentation question, for example:
+
+```text
+Use DocSearch MCP to find the current Next.js middleware matcher docs.
+```
+
+The client should call the DocSearch tools and answer with content from the matching documentation, ideally with source links.
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/overview.mdx b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
new file mode 100644
index 00000000..1d3aeae5
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: DocSearch MCP
+sidebar_label: Overview
+---
+
+DocSearch MCP lets AI clients search current public developer documentation from the DocSearch corpus.
+
+Use it when you want an assistant to answer questions from public docs instead of relying only on model training data. The public endpoint does not require authentication:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+## What it does
+
+DocSearch MCP exposes documentation search through the [Model Context Protocol](https://modelcontextprotocol.io/). MCP-compatible clients connect to the endpoint and call DocSearch tools while answering your questions.
+
+The endpoint is focused on public developer documentation. You do not need an Algolia application ID, search API key, or DocSearch application to use it.
+
+## How it works
+
+Most lookups are a single call: name the product and ask your question, and DocSearch finds the right documentation set and returns the matching content together.
+
+When a question spans several products, or you want to inspect and hand-pick documentation sets first, there is a two-step flow: resolve the documentation sets, then query the ones you choose.
+
+## Available tools
+
+### `algolia_docsearch_search_docs`
+
+The one-shot tool, and the right default for most lookups. Give it a `library` (the product, SDK, or platform) and a `query` (your question); it resolves the best matching documentation set and returns ranked content in a single call. If the library is ambiguous, it returns candidate documentation sets to choose from instead.
+
+### `algolia_docsearch_resolve_docset`
+
+Step 1 of the manual flow. Finds the documentation sets that best match a product, library, or platform and returns candidates β each with a `docset_id`, title, description, and ranking signals to help pick the best match.
+
+### `algolia_docsearch_query_docs`
+
+Step 2 of the manual flow. Retrieves documentation content for one or more `docset_id`s returned by `algolia_docsearch_resolve_docset`. Pass several at once when a question spans multiple products.
+
+## Next steps
+
+- [Install DocSearch MCP](/docs/mcp/installation)
+- [Use DocSearch MCP](/docs/mcp/usage)
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/usage.mdx b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
new file mode 100644
index 00000000..fb7b8a9b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
@@ -0,0 +1,113 @@
+---
+title: Use DocSearch MCP
+sidebar_label: Usage
+---
+
+DocSearch MCP works best when your client knows to search public documentation before answering library, framework, API, or SDK questions.
+
+## Ask documentation questions
+
+After installation, ask your client about public developer docs in natural language:
+
+```text
+How do I configure middleware matchers in Next.js?
+```
+
+```text
+Show me the current Stripe webhook signature verification docs.
+```
+
+```text
+What is the current setup for Algolia InstantSearch React?
+```
+
+If your client does not automatically use MCP tools, mention DocSearch MCP explicitly:
+
+```text
+Use DocSearch MCP to look up React Server Components data fetching.
+```
+
+## Use the Claude Code command
+
+The Claude Code plugin includes a manual command:
+
+```text
+/algolia-docsearch:docs [topic]
+```
+
+Examples:
+
+```text
+/algolia-docsearch:docs Next.js middleware matcher
+/algolia-docsearch:docs Stripe webhook signature verification
+/algolia-docsearch:docs Algolia InstantSearch React configure search client
+```
+
+## Tool flow
+
+DocSearch MCP exposes three tools. Most of the time the client only needs the one-shot tool; the two-step flow is for multi-product questions or when you want to hand-pick documentation sets.
+
+You can ask in natural language β full sentences and questions work well. For the one-shot tool, keep `library` to the product name and put the actual question in `query`.
+
+### One-shot: `algolia_docsearch_search_docs`
+
+The client names the product and asks the question in a single call:
+
+```json
+{
+ "library": "Next.js",
+ "query": "how do middleware matchers work"
+}
+```
+
+It returns ranked documentation content for the best matching set. If the library is ambiguous, it returns candidate documentation sets instead so the client can pick one and fall back to `algolia_docsearch_query_docs`.
+
+### Two-step: resolve, then query
+
+For questions that span several products, or when the client wants to choose documentation sets explicitly:
+
+1. `algolia_docsearch_resolve_docset` finds documentation sets:
+
+```json
+{
+ "query": "Next.js app router"
+}
+```
+
+It returns candidates, each with a `docset_id`.
+
+2. `algolia_docsearch_query_docs` retrieves content for the chosen `docset_id`(s):
+
+```json
+{
+ "query": "middleware matcher config",
+ "docsetIds": ["nextjs"]
+}
+```
+
+Pass multiple `docsetIds` when a question spans more than one product.
+
+## Tips
+
+- Be specific about the product and topic you want.
+- Include a version when it matters.
+- Ask for source URLs if you want the client to show where the answer came from.
+- If the first result is too broad, ask for a narrower topic.
+
+## Troubleshooting
+
+### The client does not call DocSearch MCP
+
+Make sure the MCP server is enabled in your client and named `algolia-docsearch`. If you installed the plugin, check that the plugin is enabled too.
+
+### The result is about the wrong product
+
+Ask again with the official product name. For the one-shot tool, set `library` to the vendor's product name (for example, `Algolia InstantSearch` rather than `search`).
+
+### The client cannot connect
+
+Confirm that your client supports remote HTTP MCP servers and that the configured URL is:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
diff --git a/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
new file mode 100644
index 00000000..e8edf61e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
@@ -0,0 +1,87 @@
+---
+title: Migrating from the legacy scraper
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+With the new version of the [DocSearch UI][1], we wanted to go further and provide better tooling for you to create and maintain your config file, and some extra Algolia features that you all have been requesting for a long time!
+
+## What's new?
+
+### Scraper
+
+The DocSearch infrastructure now leverages the [Algolia Crawler][2]. We've teamed up with our friends and created a new [DocSearch helper][4], that extracts records as we were previously doing with our beloved [DocSearch scraper][3]!
+
+The best part is that you no longer need to install any tooling on your side if you want to maintain or update your index!
+
+We now provide a web interface **[legacy][7]** or **[new](https://dashboard.algolia.com/crawler)** that will allow you to:
+
+- Start, schedule and monitor your crawls
+- Edit your config file from our live editor
+- Test your results directly with [DocSearch v3][1] or [DocSearch v4][32]
+
+### Algolia application and credentials
+
+We've received a lot of requests asking for:
+
+- A way to manage team members
+- Browse and see how Algolia records are indexed
+- See and subscribe to other Algolia features
+
+They are now all available, in **your own Algolia application**, for free :D
+
+## FAQ
+
+You can find answers related to the DocSearch migration in our [Crawler FAQ page](/docs/crawler).
+
+### Useful links
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+## Config file key mapping
+
+Below are the keys that can be found in the [`legacy` DocSearch configs][14] and their translation to an [Algolia Crawler config][16]. For more detailed information on the Algolia Crawler, see [the official documentation][15].
+
+| `legacy` | `current` | description |
+| --- | --- | --- |
+| `start_urls` | [`startUrls`][20] | Now accepts URLs only, see [`helpers.docsearch`][30] to handle custom variables |
+| `page_rank` | [`pageRank`][31] | Can be added to the `recordProps` in [`helpers.docsearch`][30], should be passed as a **string** |
+| `js_render` | [`renderJavaScript`][21] | Unchanged |
+| `js_wait` | [`renderJavascript.waitTime`][22] | See documentation of [`renderJavaScript`][21] |
+| `index_name` | **removed**, see [`actions`][23] | Handled directly in the [`actions`][23] |
+| `sitemap_urls` | [`sitemaps`][24] | Unchanged |
+| `stop_urls` | [`exclusionPatterns`][25] | Supports [`micromatch`][27] |
+| `selectors_exclude` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `custom_settings` | [`initialIndexSettings`][26] | Unchanged |
+| `scrape_start_urls` | **removed** | Can be handled with [`exclusionPatterns`][25] |
+| `strip_chars` | **removed** | `#` are removed automatically from anchor links, edge cases should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `conversation_id` | **removed** | Not needed anymore |
+| `nb_hits` | **removed** | Not needed anymore |
+| `sitemap_alternate_links` | **removed** | Not needed anymore |
+| `stop_content` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+
+[1]: /docs/v3/docsearch
+[2]: https://www.algolia.com/products/search-and-discovery/crawler/
+[3]: /docs/legacy/run-your-own
+[4]: /docs/record-extractor
+[7]: https://crawler.algolia.com/
+[14]: /docs/legacy/config-file
+[15]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[16]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[20]: https://www.algolia.com/doc/tools/crawler/apis/configuration/start-urls/
+[21]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[22]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/#parameter-param-waittime
+[23]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-indexname
+[24]: https://www.algolia.com/doc/tools/crawler/apis/configuration/sitemaps/
+[25]: https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/
+[26]: https://www.algolia.com/doc/tools/crawler/apis/configuration/initial-index-settings/
+[27]: https://github.com/micromatch/micromatch
+[28]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[29]: /docs/record-extractor
+[30]: /docs/record-extractor#introduction
+[31]: /docs/record-extractor#pagerank
+[32]: /docs/docsearch
diff --git a/packages/website/docs/migrating-from-v3.md b/packages/website/versioned_docs/version-v4/migrating-from-v3.md
similarity index 100%
rename from packages/website/docs/migrating-from-v3.md
rename to packages/website/versioned_docs/version-v4/migrating-from-v3.md
diff --git a/packages/website/versioned_docs/version-v4/record-extractor.md b/packages/website/versioned_docs/version-v4/record-extractor.md
new file mode 100644
index 00000000..64c34ca7
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/record-extractor.md
@@ -0,0 +1,345 @@
+---
+title: Record Extractor
+---
+
+## Introduction
+
+:::info
+
+This documentation will only contain information regarding the **helpers.docsearch** method, see **[Algolia Crawler Documentation][7]** for more information on the **[Algolia Crawler][8]**.
+
+:::
+
+Pages are extracted by a [`recordExtractor`][9]. These extractors are assigned to [`actions`][12] via the [`recordExtractor`][9] parameter. This parameter links to a function that returns the data you want to index, organized in an array of JSON objects.
+
+_The helpers are a collection of functions to help you extract content and generate Algolia records._
+
+### Useful links
+
+- [Extracting records with the Algolia Crawler][11]
+- [`recordExtractor` parameters][10]
+
+## Usage
+
+The most common way to use the DocSearch helper, is to return its result to the [`recordExtractor`][9] function.
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Manipulate the DOM with Cheerio
+
+The [`Cheerio instance ($)`](https://cheerio.js.org/) allows you to manipulate the DOM:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ $(".my-warning-message").remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Provide fallback selectors
+
+Fallback selectors can be useful when retrieving content that might not exist in some pages:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ // `.exists h1` will be selected if `.exists-probably h1` does not exists.
+ lvl0: {
+ selectors: [".exists-probably h1", ".exists h1"],
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ // `.exists p, .exists li` will be selected.
+ content: [
+ ".does-not-exists p, .does-not-exists li",
+ ".exists p, .exists li",
+ ],
+ },
+ });
+},
+```
+
+### Provide raw text (`defaultValue`)
+
+_Only the `lvl0` and [custom variables][13] selectors support this option_
+
+You might want to structure your search results differently than your website, or provide a `defaultValue` to a potentially non-existent selector:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably h1",
+ defaultValue: "myRawTextIfDoesNotExists",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably .language",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ },
+ });
+},
+```
+
+### Indexing content for faceting
+
+_These selectors also support [`defaultValue`](#provide-raw-text-defaultvalue) and [fallback selectors](#provide-fallback-selectors)_
+
+You might want to index content that will be used as filters in your frontend (e.g. `version` or `lang`), you can define any custom variable to the `recordProps` object to add them to your Algolia records:
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ foo: ".bar",
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".does-not-exists",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ version: {
+ // You can send raw values without `selectors`
+ defaultValue: ["latest", "stable"],
+ },
+ },
+ });
+},
+```
+
+The following `version`, `lang` and `foo` attributes will be available in your records:
+
+```json
+foo: "valueFromBarSelector",
+language: ["en", "en-US"],
+version: ["latest", "stable"]
+```
+
+You can now use them to [filter your search in the frontend][16]
+
+### Boost search results with `pageRank`
+
+This parameter allows you to boost records using a custom ranking attribute built from the current `pathsToMatch`. Pages with highest [`pageRank`](#pagerank) will be returned before pages with a lower [`pageRank`](#pagerank). The default value is 0 and you can pass any numeric value **as a string**, including negative values.
+
+Search results are sorted by weight (desc), so you can have both boosted and non boosted results. The weight of each result will be computed for a given query based on multiple factors: match level, position, etc. and the pageRank value will be added to this final weight. The pageRank on its own may not be enough to influence the results of your query depending on how your [overall ranking is set up](https://www.algolia.com/doc/guides/managing-results/relevance-overview/in-depth/ranking-criteria/). If changing the pageRank value doesn't influence your search results enough, even with large values, move weight.pageRank higher in the Ranking and Sorting page for your index.
+
+You can view the computed weight directly from the Algolia dashboard (dashboard.algolia.com->search->perform a search->mouse hover over the "ranking criteria" icon bottom right of each record). That will give you an idea of what pageRank value is acceptable for your case.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers, url }) => {
+ const isDocPage = /\/[\w-]+\/docs\//.test(url.pathname);
+ const isBlogPage = /\/[\w-]+\/blog\//.test(url.pathname);
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ pageRank: isDocPage ? "-2000" : isBlogPage ? "-1000" : "0",
+ },
+ });
+ },
+},
+```
+
+### Reduce the number of records
+
+If you encounter the `Extractors returned too many records` error when your page outputs more than 750 records, the [`aggregateContent`](#aggregatecontent) option helps you reduce the number of records at the `content` level of the extractor.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ aggregateContent: true,
+ });
+ },
+},
+```
+
+### Reduce the record size
+
+If you encounter the `Records extracted are too big` error when crawling your website, it is usually because there is too much information in your records, or because your page is too large. The [`recordVersion`](#recordversion) option helps you reduce the records size by removing informations that are only used with [DocSearch v2](/docs/legacy/dropdown).
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ recordVersion: "v3",
+ });
+ },
+},
+```
+
+## `recordProps` API Reference
+
+### `lvl0`
+
+> `type: Lvl0` | **required**
+
+```ts
+type Lvl0 = {
+ selectors: string | string[];
+ defaultValue?: string;
+};
+```
+
+### `lvl1`, `content`
+
+> `type: string | string[]` | **required**
+
+### `lvl2`, `lvl3`, `lvl4`, `lvl5`, `lvl6`
+
+> `type: string | string[]` | **optional**
+
+### `pageRank`
+
+> `type: number` | **optional**
+
+See the [live example](#boost-search-results-with-pagerank)
+
+### Custom variables
+
+> `type: string | string[] | CustomVariable` | **optional**
+
+```ts
+type CustomVariable =
+ | {
+ defaultValue: string | string[];
+ }
+ | {
+ selectors: string | string[];
+ defaultValue?: string | string[];
+ };
+```
+
+Custom variables are used to [`filter your search`](/docs/v3/docsearch#filtering-your-search), you can define them in the [`recordProps`](#indexing-content-for-faceting)
+
+## `helpers.docsearch` API Reference
+
+### `aggregateContent`
+
+> `type: boolean` | default: `true` | **optional**
+
+[This option](#reduce-the-number-of-records) groups the Algolia records created at the `content` level of the selector into a single record for its matching heading.
+
+### `recordVersion`
+
+> `type: 'v3' | 'v2'` | default: `v2` | **optional**
+
+This option removes content from the Algolia records that are only used for [DocSearch v2](/docs/legacy/dropdown). If you are using [the latest version of DocSearch](/docs/v3/docsearch), you can [set it to `v3`](#reduce-the-record-size).
+
+### `indexHeadings`
+
+> `type: boolean | { from: number, to: number }` | default: `true` | **optional**
+
+This option tells the crawler if the `headings` (`lvlX`) should be indexed.
+
+- When `false`, only records for the `content` level will be created.
+- When `from, to` is provided, only records for the `lvlX` to `lvlY` will be created.
+
+[1]: /docs/v3/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/migrating-from-legacy
+[6]: /docs/legacy/run-your-own
+[7]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[8]: https://www.algolia.com/products/search-and-discovery/crawler/
+[9]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[10]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor-2
+[11]: https://www.algolia.com/doc/tools/crawler/guides/extracting-data/#extracting-records
+[12]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/
+[13]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: /docs/v3/docsearch/#filtering-your-search
diff --git a/packages/website/versioned_docs/version-v4/required-configuration.mdx b/packages/website/versioned_docs/version-v4/required-configuration.mdx
new file mode 100644
index 00000000..9b33aed2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/required-configuration.mdx
@@ -0,0 +1,189 @@
+---
+title: Required configuration
+---
+
+This section gives you the best practices to optimize our crawl. Adopting the following specification is required to let our crawler build the best experience from your website. You will need to update your website and follow these rules.
+
+:::info
+
+If your website is generated, thanks to one of [our supported tools][1], you do not need to change your website as it is already compliant with our requirements.
+
+:::
+
+## The generic configuration example
+
+You can find the default DocSearch config template below and tweak it with some examples from our [`complex extractors` section][12].
+
+If you are using one of [our integrations][13], please see [the templates page][11].
+
+
+docsearch-default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ startUrls: ['https://YOUR_START_URL.io/'],
+ sitemaps: ['https://YOUR_START_URL.io/sitemap.xml'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_START_URL.io/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+### Overview of a clear layout
+
+A website implementing these best practices will look simple and clear, as shown below:
+
+
+
+The main blue element will be your `.DocSearch-content` container. More details in the following guidelines.
+
+### Use the right classes as [`recordProps`][2]
+
+You can add some specific static classes to help us find your content role. These classes can not involve any style changes. These dedicated classes will help us to create a great learn-as-you-type experience from your documentation.
+
+- Add a static class `DocSearch-content` to the main container of your textual content. Most of the time, this tag is a `` or an `` HTML element.
+
+- Every searchable `lvl` element outside this main documentation container (for instance in a sidebar) must be a `global` selector. They will be globally picked up and injected to every record built from your page. Be careful, the level value matters and every matching element must have an increasing level along the HTML flow. A level `X` (for `lvlX`) should appear after a level `Y` while `X > Y`.
+
+- `lvlX` selectors should use the standard title tags like `h1`, `h2`, `h3`, etc. You can also use static classes. Set a unique `id` or `name` attribute to these elements as detailed below.
+
+- Every DOM element matching the `lvlX` selectors must have a unique `id` or `name` attribute. This will help the redirection to directly scroll down to the exact place of the matching elements. These attributes define the right anchor to use.
+
+- Every textual element (recordProps `content`) must be wrapped in a `` or `
` tag. This content must be atomic and split into small entities. Be careful to never nest one matching element into another one as it will create duplicates.
+
+- Stay consistent and do not forget that we need to have some consistency along the HTML flow.
+
+## Introduce global information as meta tags
+
+Our crawler automatically extracts information from our DocSearch specific meta tags:
+
+```html
+
+
+```
+
+The crawl adds the `content` value of these `meta` tags to all records extracted from the page. The meta tags `name` must follow the `docsearch:$NAME` pattern. `$NAME` is the name of the attribute set to all records.
+
+The `docsearch:version` meta tag can be a set [of comma-separated tokens][5], each of which is a version relevant to the page. These tokens must be compliant with [the SemVer specification][6] or only contain alphanumeric characters (e.g. `latest`, `next`, etc.). As facet filters, these version tokens are case-insensitive.
+
+For example, all records extracted from a page with the following meta tag:
+
+```html
+
+```
+
+The `version` attribute of these records will be :
+
+```json
+version:["2.0.0-alpha.62", "latest"]
+```
+
+You can then [transform these attributes as `facetFilters`][3] to [filter over them from the UI][10].
+
+## Nice to have
+
+- Your website should have [an updated sitemap][7]. This is key to let our crawler know what should be updated. Do not worry, we will still crawl your website and discover embedded hyperlinks to find your great content.
+
+- Every page needs to have their full context available. Using global elements might help (see above).
+
+- Make sure your documentation content is also available without JavaScript rendering on the client-side. If you absolutely need JavaScript turned on, you need to [set `renderJavaScript: true` in your configuration][8].
+
+Any questions? Connect with us on [Discord][14] or [support][9].
+
+[1]: /docs/integrations
+[2]: record-extractor#recordprops-api-reference
+[3]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[5]: https://html.spec.whatwg.org/dev/common-microsyntaxes.html#comma-separated-tokens
+[6]: https://semver.org/
+[7]: https://www.sitemaps.org/
+[8]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[9]: https://support.algolia.com/
+[10]: /docs/v3/docsearch#filtering-your-search
+[11]: /docs/templates
+[12]: /docs/record-extractor#introduction
+[13]: /docs/integrations
+[14]: https://alg.li/discord
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
new file mode 100644
index 00000000..b22ca01f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
@@ -0,0 +1,144 @@
+---
+title: Advanced use cases
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+This guide will cover some advanced implementations/use cases for the Sidepanel. The examples below assume you're using the Sidepanel React package,
+available from `@docsearch/sidepanel`. The `@docsearch/sidepanel` package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Complex implementation
+
+Below is an example of a more complex implementation with `searchParameters`, a different `variant`, and some translations.
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+function App() {
+ return (
+
+
+
+
+ );
+}
+```
+
+## Dynamic importing
+
+Sidepanel is built in a way that allows for dynamic importing of its components to help reduce bundle size. Below is a brief example of how to do so:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton } from '@docsearch/sidepanel/button';
+import type { Sidepanel as SidepanelType } from '@docsearch/sidepanel/sidepanel';
+import { useState } from 'react';
+
+let Sidepanel: typeof SidepanelType | null = null;
+
+async function importSidepanelIfNeeded() {
+ if (Sidepanel) {
+ return;
+ }
+
+ const { Sidepanel: Panel } = await import('@docsearch/sidepanel/sidepanel');
+
+ Sidepanel = Panel;
+}
+
+export default function DynamicSidepanel() {
+ const [sidepanelLoaded, setSidepanelLoaded] = useState(false);
+
+ const loadSidepanel = () => {
+ importSidepanelIfNeeded().then(() => {
+ setSidepanelLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {sidepanelLoaded && Sidepanel && (
+
+ )}
+
+ );
+}
+```
+
+## Hybrid Mode
+
+Hybrid Mode allows you to combine the Sidepanel and the original DocSearch Modal in one integrated experience.
+
+You can trigger the Modal for search and the Sidepanel for AI-powered assistance.
+
+Learn more in the [Hybrid Mode guide][1].
+
+[1]: /docs/sidepanel/hybrid
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
new file mode 100644
index 00000000..6e3a1b5e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
@@ -0,0 +1,186 @@
+---
+title: Sidepanel API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `assistantId`
+
+> `type: string` | **required**
+
+The ID for which Ask AI assistant to use.
+
+## `indexName`
+
+> `type: string` | **required**
+
+The name of the index to be used with the Ask AI service.
+
+## `agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `agentStudio` is true, the Ask AI chat will use Algolia's [Agent Studio][2] as the chat backend instead of the Ask AI backend. More can be learned about setting up Agent Studio on their dedicated [documentation page][3].
+
+## `searchParameters`
+
+> `type: AskAiSearchParameters | Record>` | **optional**
+
+Additional search parameters used to scope Ask AI or Agent Studio retrieval.
+
+- When `agentStudio` is omitted or `false`, pass a flat object such as `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- When `agentStudio` is `true`, `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+```tsx
+
+```
+
+```tsx
+
+```
+
+## `variant`
+
+> `type: 'floating' | 'inline'` | default: `'floating'` | **optional**
+
+Variant of the Sidepanel positioning.
+
+- `inline` pushes page content when opened.
+- `floating` is positioned above all other content on the page.
+
+## `side`
+
+> `type: 'right' | 'left'` | default: `'right'` | **optional**
+
+The side of the page which the panel will originate from.
+
+## `width`
+
+> `type: number | string` | default: `'360px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its default state.
+
+## `expandedWidth`
+
+> `type: number | string` | default: `'580px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its expanded state.
+
+## `suggestedQuestions`
+
+> `type: boolean` | default: `false` | **optional**
+
+Enables displaying suggested questions on new conversation screen.
+
+More information on setting up Suggested Questions can be found on [Algolia Docs][1]
+
+## `keyboardShortcuts`
+
+> `type: { 'Ctrl/Cmd+I': boolean }` | **optional**
+
+Configuration for keyboard shortcuts. Allows enabling/disabling specific shortcuts.
+
+### Default behavior
+
+- `Ctrl/Cmd+I` - Opens and closes the Sidepanel
+
+### Interface
+
+```ts
+interface SidepanelShortcuts {
+ 'Ctrl/Cmd+I'?: boolean; // default: true
+}
+```
+
+## `theme`
+
+> `type: 'light' | 'dark'` | default: `'light'` | **optional**
+
+## `portalContainer` (React only)
+
+> `type: Element | DocumentFragment` | default: `document.body` | **optional**
+
+The container element where the panel should be portaled to. Use this when you need the Sidepanel to render in a custom DOM node.
+
+:::warning
+This prop only exists in the React based versions of Sidepanel. If you are using the `@docsearch/sidepanel-js` package, use the `container` option instead.
+:::
+
+
+
+ ```tsx
+ // assume you have a dedicated DOM node in your HTML
+
+
+ const portalEl = document.getElementById('sidepanel-root');
+
+
+ ```
+
+
+
+ ```js
+ sidepanel({
+ // The element that will contain the Sidepanel Button and Sidepanel
+ container: '#sidepanel-root',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+ })
+ ```
+
+
+
+[1]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/suggested-questions
+[2]: https://www.algolia.com/products/ai/agent-studio
+[3]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
new file mode 100644
index 00000000..13d31f95
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
@@ -0,0 +1,136 @@
+---
+title: Get started with Sidepanel
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Sidepanel is available from version `>= 4.4`
+:::
+
+## Introduction
+
+DocSearch Sidepanel is a new experience separate from the DocSearch Modal experience. Sidepanel is built entirely for usage with Ask AI and can be used completely standalone or in [Hybrid mode][1] with the Modal.
+
+## Installation
+
+To get started with Sidepanel, first you will need to install the needed packages:
+
+
+
+
+```bash
+npm install @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+npm install @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+yarn add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+pnpm add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+bun add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+### Without package manager
+
+```html
+
+
+
+
+```
+
+## Implementation
+
+The simplest implementation of Sidepanel would be as follows:
+
+
+
+```tsx
+import { DocSearchSidepanel } from '@docsearch/react/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function App() {
+ return (
+
+ );
+}
+```
+
+
+
+You will need a `container` DOM node to render the Sidepanel into:
+
+```html
+
+```
+
+```js
+import sidepanel from '@docsearch/sidepanel-js';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+sidepanel({
+ container: '#docsearch-sidepanel',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+});
+```
+
+
+
+This is just the most basic form of implementation. To learn about other implementation methods, you can read our [Advanced use cases][2].
+
+To learn more about the different configuration options for Sidepanel, you can read our [Sidepanel API References][3].
+
+[1]: /docs/sidepanel/hybrid
+[2]: /docs/sidepanel/advanced-use-cases
+[3]: /docs/sidepanel/api-reference
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
new file mode 100644
index 00000000..0be6f2cb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
@@ -0,0 +1,100 @@
+---
+title: Hybrid Mode
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Currently Hybrid Mode is only available when using the React usage approach. Hybrid Mode is not available in the JavaScript-only (vanilla) integration.
+:::
+
+## Introduction
+
+Sidepanel can run alongside the DocSearch Modal through what we call "Hybrid Mode." When a user initiates an Ask AI action from within
+the DocSearch Modal, such as submitting a prompt or selecting an AI-related suggestion, the interface automatically transitions into the Sidepanel for
+the continuation of the conversation.
+
+## Set up
+
+To set up the Hybrid Mode experience, you will need the following:
+
+- [DocSearch Modal][1] packages installed
+- Sidepanel Component package installed
+
+The Sidepanel Component package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+Once everything is installed, you can set up Hybrid Mode as such:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function HybridMode() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+There is no manual opt-in for Hybrid Mode to work. When both the Modal and Sidepanel are rendered inside the same `` context, Hybrid Mode is enabled automatically. No additional configuration is required.
+
+[1]: /docs/docsearch#installation
diff --git a/packages/website/versioned_docs/version-v4/styling.md b/packages/website/versioned_docs/version-v4/styling.md
new file mode 100644
index 00000000..554fe0c0
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/styling.md
@@ -0,0 +1,48 @@
+---
+title: Styling
+---
+
+:::info
+
+The following content is for **[DocSearch v4][2]**. If you are using **[DocSearch v3][3]**, see the **[legacy][4]** documentation.
+
+:::
+
+## Introduction
+
+DocSearch v4 comes with a theme package called `@docsearch/css`, which offers a sleek out of the box theme!
+
+:::note
+
+This package is a dependency of [`@docsearch/js`][1] and [`@docsearch/react`][1], you don't need to install it if you are using a package manager!
+
+:::
+
+## Installation
+
+```bash
+yarn add @docsearch/css@4
+# or
+npm install @docsearch/css@4
+```
+
+If you donβt want to use a package manager, you can use a standalone endpoint:
+
+```html
+
+```
+
+## Files
+
+```
+@docsearch/css
+βββ dist/style.css # all styles
+βββ dist/_variables.css # CSS variables
+βββ dist/button.css # CSS for the button
+βββ dist/modal.css # CSS for the modal
+```
+
+[1]: /docs/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/v3/docsearch
diff --git a/packages/website/versioned_docs/version-v4/templates.mdx b/packages/website/versioned_docs/version-v4/templates.mdx
new file mode 100644
index 00000000..b14126d9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/templates.mdx
@@ -0,0 +1,1069 @@
+---
+title: Config Templates
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+To help you create the best search experience for your users, we provide out-of-the-box crawler config templates for multiple websites generators. If you'd like to add a new template to our list, or believe we should update an existing one, please [let us know on Discord][1] or [open a pull request][2].
+
+> If you want to better understand the default parameters of the configs below, take a look at the [Crawler documentation](https://www.algolia.com/doc/tools/crawler/apis/configuration/).
+
+## Getting Started
+
+Once approved for DocSearch, we will automatically create a Crawler on your behalf, include your URL, and the Algolia credentials for your appId, apiKey, and indexName. If we detect that you are using any of the predefined generators, we'll attempt to automatically assign the proper template that matches your generator. However, this is not guaranteed. If no specific generator is detected, we will apply the default template seen below.
+
+## Updating the Template
+
+You can manually update the crawler template by going to dashboard.algolia.com, click "Data sources", select your crawler, and go to the editor page. From there you can edit the JavaScript directly. Note that you can make draft changes without saving, test the changes using the "URL Tester", and then "Save" once you're happy with your changes.
+
+## Default Template
+
+
+default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ indexPrefix: 'crawler_',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL'],
+ renderJavaScript: false,
+ sitemaps: [],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v1 Template
+
+
+docusaurus-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/docs/',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/blog/',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/docs/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Docs',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['docs'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/blog/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Blog',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['blog'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang', 'language', 'version', 'tags'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v2 & v3 Template
+
+
+docusaurus-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // priority order: deepest active sub list header -> navbar active item -> 'Documentation'
+ // Extracting the breadcrumb titles for better accessibility.
+ const navbarTitle = $(".navbar__item.navbar__link--active").text();
+ const pageBreadcrumbTitles = $(".breadcrumbs__link")
+ .toArray()
+ .map((item) => $(item).text().trim())
+ .filter(Boolean);
+ const lvl0 =
+ [navbarTitle, ...pageBreadcrumbTitles].join(" / ") || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: lvl0,
+ },
+ lvl1: ['header h1', 'article h1'],
+ lvl2: 'article h2',
+ lvl3: 'article h3',
+ lvl4: 'article h4',
+ lvl5: 'article h5, article td:first-child',
+ lvl6: 'article h6',
+ content: 'article p, article li, article td:last-child',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ 'language',
+ 'version',
+ 'docusaurus_tag',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+## Astro Starlight Template
+
+
+starlight.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Get the top level menu item
+ const lvl0 =
+ $('details:has(a[aria-current="page"])')
+ .find("summary")
+ .find("span")
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: "main h1",
+ lvl2: "main h2",
+ lvl3: "main h3",
+ lvl4: "main h4",
+ lvl5: "main h5",
+ lvl6: "main h6",
+ content: "main p, main li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v1 Template
+
+
+vuepress-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: 'p.sidebar-heading.open',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content__default h1',
+ lvl2: '.content__default h2',
+ lvl3: '.content__default h3',
+ lvl4: '.content__default h4',
+ lvl5: '.content__default h5',
+ content: '.content__default p, .content__default li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v2 Template
+
+
+vuepress-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vitepress Template
+
+
+vitepress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content h1',
+ lvl2: '.content h2',
+ lvl3: '.content h3',
+ lvl4: '.content h4',
+ lvl5: '.content h5',
+ content: '.content p, .content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Rspress Template
+
+
+rspress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ const lvl0 =
+ $(".rspress-nav-menu-item.rspress-nav-menu-item-active")
+ .first()
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: ".rspress-doc h1",
+ lvl2: ".rspress-doc h2",
+ lvl3: ".rspress-doc h3",
+ lvl4: ".rspress-doc h4",
+ lvl5: ".rspress-doc h5",
+ lvl6: ".rspress-doc pre > code", // if you want to search code blocks, add this line
+ content: ".rspress-doc p, .rspress-doc li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: "v3",
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## pkgdown Template
+
+
+pkgdown.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/index.html',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/reference',
+ 'https://YOUR_WEBSITE_URL/articles',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ exclusionPatterns: [
+ '**/reference/',
+ '**/reference/index.html',
+ '**/articles/',
+ '**/articles/index.html',
+ ],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/index.html**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ defaultValue: 'YOUR_INDEX_NAME Home page',
+ },
+ lvl1: '.contents h2',
+ lvl2: '.contents h3',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li, .contents .pre',
+ tags: {
+ defaultValue: ['homepage'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/reference**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.ref-arguments th',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['reference'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/articles**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.contents h2, .contents h3',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['articles'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+[1]: https://alg.li/discord
+[2]: https://github.com/algolia/docsearch
diff --git a/packages/website/versioned_docs/version-v4/tips.md b/packages/website/versioned_docs/version-v4/tips.md
new file mode 100644
index 00000000..57d1c4fa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/tips.md
@@ -0,0 +1,71 @@
+---
+title: Tips for a good search
+---
+
+DocSearch can work with almost any website, but we've found that some site structures yield more relevant results or faster indexing time. On this page we'll share some tips on how to make the most out of DocSearch.
+
+## Use a `sitemap.xml`
+
+If you provide a sitemap in your configuration, DocSearch will use it to directly browse the pages to index. Pages are still crawled which means we extract every compliant link.
+
+We highly recommend you add a `sitemap.xml` to your website if you don't have one already. This will not only make the indexing faster, but also provide you more control over which pages to index.
+
+Sitemaps are also considered good practice for other aspects, including SEO ([more information on sitemaps][1]).
+
+## Structure the hierarchy of information
+
+DocSearch works better on structured documentation. Relevance of results is based on the structural hierarchy of content. In simpler terms, it means that we read the ``, ..., `` headings of your page to guess the hierarchy of information. This hierarchy brings contextual information to your records.
+
+Documentation starts by explaining generic concepts first and then goes deeper into specifics. This is represented in your HTML markup by the hierarchy of headings you're using. For example, concepts discussed under a `` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+
+DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+
+Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+
+_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+
+## Set a unique class to the element holding the content
+
+DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
+
+Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+
+## Add anchors to headings
+
+When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+
+DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+
+## Marking the active page(s) in the navigation
+
+If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+
+For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
+
+The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+
+## Consistency of your content
+
+Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+
+The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+
+Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+
+Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+
+## Avoid duplicates by promoting unicity
+
+The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+
+Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+
+## Conciseness
+
+What is clearly thought out is clearly and concisely expressed.
+
+We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+
+[1]: https://www.sitemaps.org/index.html
+[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
+[3]: https://www.algolia.com/doc/guides/searching/faceting/
diff --git a/packages/website/docs/v4/askai-api.mdx b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
similarity index 97%
rename from packages/website/docs/v4/askai-api.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-api.mdx
index a01ff9e1..3edf58b2 100644
--- a/packages/website/docs/v4/askai-api.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
@@ -23,4 +23,4 @@ The official documentation includes:
- Integration examples with Next.js and Vercel AI SDK
- Error handling and best practices
-For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/askai).
+For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/v4/askai).
diff --git a/packages/website/docs/v4/askai-errors.mdx b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-errors.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
index 60b6d10b..53eb6f47 100644
--- a/packages/website/docs/v4/askai-errors.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
@@ -161,5 +161,5 @@ The request exceeded the model's maximum context length. This happens when the c
[1]: /docs/api#askai
[2]: https://sitesearch.algolia.com/docs/experiences/search-askai#configuration
[3]: https://www.algolia.com/doc/guides/algolia-ai/askai/reference/api
-[4]: /docs/v4/askai-whitelisted-domains
+[4]: /docs/v4/v4/askai-whitelisted-domains
[5]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/models
diff --git a/packages/website/docs/v4/askai-markdown-indexing.mdx b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-markdown-indexing.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
index 4160f9ef..4900f1b9 100644
--- a/packages/website/docs/v4/askai-markdown-indexing.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
@@ -39,7 +39,7 @@ The easiest way to set up markdown indexing is through the Crawler UI, which aut
- **Content Tag**: Specify the HTML content selector (typically `main`)
- **Template**: Choose the template that matches your documentation framework:
- **Docusaurus** - For Docusaurus sites
- - **VitePress** - For VitePress sites
+ - **VitePress** - For VitePress sites
- **Astro/Starlight** - For Astro/Starlight sites
- **Non-DocSearch (Generic)** - For custom sites or other frameworks
@@ -245,7 +245,7 @@ class CustomAskAI {
async sendMessage(conversationId, messages, searchParameters = {}) {
const token = await this.getToken();
-
+
const response = await fetch(`${this.baseUrl}/chat`, {
method: 'POST',
headers: {
@@ -270,14 +270,14 @@ class CustomAskAI {
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
-
+
return {
async *[Symbol.asyncIterator]() {
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
-
+
const chunk = decoder.decode(value, { stream: true });
if (chunk.trim()) {
yield chunk;
@@ -323,7 +323,7 @@ for await (const chunk of stream) {
- Integration with existing chat systems
- Custom analytics and monitoring
-> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/askai-api).
+> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/v4/askai-api).
**Using Facet Filters with Your Markdown Index:**
diff --git a/packages/website/docs/v4/askai-models.mdx b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
similarity index 71%
rename from packages/website/docs/v4/askai-models.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-models.mdx
index fff60ff5..63f10810 100644
--- a/packages/website/docs/v4/askai-models.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
@@ -2,7 +2,7 @@
title: Bring Your Own LLM
---
-import { ProvidersTable } from '../../src/components/ProvidersTable'
+import { ProvidersTable } from '@site/src/components/ProvidersTable';
Ask AI currently supports a Bring Your Own LLM (BYOLLM) model selection, allowing you to connect your preferred provider.
diff --git a/packages/website/docs/v4/askai-prompts.mdx b/packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-prompts.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
diff --git a/packages/website/docs/v4/askai-whitelisted-domains.mdx b/packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-whitelisted-domains.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
diff --git a/packages/website/docs/v4/askai.mdx b/packages/website/versioned_docs/version-v4/v4/askai.mdx
similarity index 98%
rename from packages/website/docs/v4/askai.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai.mdx
index 0cc29de5..9a561f57 100644
--- a/packages/website/docs/v4/askai.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai.mdx
@@ -118,5 +118,5 @@ This view gives you a centralized place to organize, reuse, and fine-tune your a
## Next steps
-- [Prompting with Ask AI](/docs/v4/askai-prompts)
-- [Ask AI Whitelisted Domains](/docs/v4/askai-whitelisted-domains)
+- [Prompting with Ask AI](/docs/v4/v4/askai-prompts)
+- [Ask AI Whitelisted Domains](/docs/v4/v4/askai-whitelisted-domains)
diff --git a/packages/website/versioned_docs/version-v4/what-is-docsearch.md b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
new file mode 100644
index 00000000..c371ae12
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
@@ -0,0 +1,32 @@
+---
+title: What is DocSearch?
+sidebar_label: What is DocSearch?
+---
+
+## Why?
+
+We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+
+It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+
+## Quick description
+
+We split DocSearch into a crawler and a frontend library.
+
+- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
+- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+
+## How to feature DocSearch?
+
+DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+
+DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
+
+You can now [apply to the program][3].
+
+[1]: https://opencollective.com/algolia
+[2]: /docs/who-can-apply
+[3]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[4]: https://www.algolia.com/products/search-and-discovery/crawler/
+[5]: https://dashboard.algolia.com/crawler
+[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
diff --git a/packages/website/versioned_docs/version-v4/who-can-apply.md b/packages/website/versioned_docs/version-v4/who-can-apply.md
new file mode 100644
index 00000000..cec7c5ae
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/who-can-apply.md
@@ -0,0 +1,30 @@
+---
+title: Who can apply?
+---
+
+**Open for all developer documentation and technical blogs.**
+
+We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all public online technical documentations and technical blogs.
+
+We usually turn down applications when they are not production ready or have non-technical content on the website.
+
+## Application process
+
+To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+
+- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+
+- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+
+- β
Please review [DocSearch Plan Terms and Conditions][2].
+
+## Process duration
+
+DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+
+Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
+[3]: integrations.md
+[4]: https://alg.li/discord
diff --git a/packages/website/versioned_sidebars/version-v4-sidebars.json b/packages/website/versioned_sidebars/version-v4-sidebars.json
new file mode 100644
index 00000000..74276efe
--- /dev/null
+++ b/packages/website/versioned_sidebars/version-v4-sidebars.json
@@ -0,0 +1,81 @@
+{
+ "docs": [
+ {
+ "type": "category",
+ "label": "Introduction",
+ "items": ["what-is-docsearch", "who-can-apply"]
+ },
+ {
+ "type": "category",
+ "label": "DocSearch v4",
+ "items": ["docsearch", "docusaurus-adapter", "composable-api", "styling", "api", "examples", "migrating-from-v3"]
+ },
+ {
+ "type": "category",
+ "label": "MCP",
+ "items": ["mcp/overview", "mcp/installation", "mcp/usage"]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Ask AI",
+ "items": [
+ "v4/askai",
+ "v4/askai-api",
+ "v4/askai-prompts",
+ "v4/askai-whitelisted-domains",
+ "v4/askai-models",
+ "v4/askai-markdown-indexing",
+ "v4/askai-errors",
+ {
+ "type": "link",
+ "label": "Full Documentation",
+ "href": "https://www.algolia.com/doc/guides/algolia-ai/askai"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Sidepanel",
+ "items": [
+ "sidepanel/getting-started",
+ "sidepanel/advanced-use-cases",
+ "sidepanel/hybrid",
+ "sidepanel/api-reference"
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Crawler",
+ "items": ["create-crawler", "record-extractor", "templates", "crawler-configuration-visual", "manage-your-crawls"]
+ },
+ {
+ "type": "category",
+ "label": "Requirements, tips, FAQ",
+ "items": [
+ {
+ "type": "category",
+ "label": "FAQ",
+ "items": ["crawler", "docsearch-program"]
+ },
+ {
+ "type": "doc",
+ "id": "tips"
+ },
+ {
+ "type": "doc",
+ "id": "integrations"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Under the hood",
+ "items": ["how-does-it-work", "required-configuration"]
+ },
+ {
+ "type": "category",
+ "label": "Miscellaneous",
+ "items": ["migrating-from-legacy"]
+ }
+ ]
+}
diff --git a/packages/website/versions.json b/packages/website/versions.json
index dbac805d..9b27128c 100644
--- a/packages/website/versions.json
+++ b/packages/website/versions.json
@@ -1 +1 @@
-["v3", "legacy"]
+["v4", "v3", "legacy"]
` through `` headings or equivalent selectors to build `hierarchy.lvl0` through `hierarchy.lvl6`.
-Documentation starts by explaining generic concepts first and then goes deeper into specifics. This is represented in your HTML markup by the hierarchy of headings you're using. For example, concepts discussed under a `` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+Documentation usually introduces general concepts before covering details. Represent this structure with an ordered heading hierarchy. For example, content under an `` is more specific than content under an `` on the same page. Content that appears earlier on the page ranks higher.
-DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+DocSearch uses this structure to improve relevance. V5 also uses the populated hierarchy levels to render result breadcrumbs. Keep headings in order and avoid skipping levels where possible so each result retains its page context.
-Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+Choose a documentation depth that gives each result enough context. For large pages, use four levels, from `lvl0` to `lvl3`. Use at least three levels.
-_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+You can use classes, such as ``, instead of `` elements.
## Set a unique class to the element holding the content
DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
-Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+A unique identifier makes your configuration more robust and limits indexing to relevant content. Use it to exclude unrelated headers, sidebars, and footers.
## Add anchors to headings
-When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+Add a custom anchor to each heading. Define anchors with an `id` or `name` HTML attribute so browsers can scroll directly to the corresponding position. Links can target an anchor with `#` followed by its value.
-DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+DocSearch uses these anchors to send users to the location of the selected result.
-## Marking the active page(s) in the navigation
+## Mark active pages in the navigation
-If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+If you use multi-level navigation, mark each active level with a custom CSS class. The crawler can use this class to determine where the current page fits in the website hierarchy.
For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
-The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+Use any valid CSS class name that can be part of a CSS selector.
## Consistency of your content
-Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+Use the same heading structure across documentation pages. Make each page topic and outline clear, and avoid selectors that create records without enough context, such as standalone introductions or asides.
-The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+Write selectors that match documentation pages but exclude landing pages, tables of contents, and other unrelated content. Add a dedicated class, such as `.DocSearch-content`, to the main documentation container.
-Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+Use consistent terms for the same concepts. You can also configure [synonyms][5] for terms your users search interchangeably.
-Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+## Avoid duplicate content
-## Avoid duplicates by promoting unicity
+Split broad topics into focused pages. Avoid catch-all pages that make it difficult to identify the relevant result.
-The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+Duplicate content adds noise and can mislead users. Don't repeat all documentation content on a landing or summary page. If you need duplicate records for separate datasets, such as different versions, use [facets][3] to distinguish them.
-Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+## Index metadata for v5
+
+Add each attribute used by the v5 `facets` option to `attributesForFaceting`. DocSearch supports up to five facet controls. For a result badge, index a short value such as `version`, include it in `attributesToRetrieve`, and pass its property path to `resultBadgeKey`. See the [v5 JavaScript API reference][4].
## Conciseness
-What is clearly thought out is clearly and concisely expressed.
+Keep content focused on one task or concept, and use short headings and paragraphs.
-We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+For more guidance, read [How to build a helpful search for technical documentation][2].
[1]: https://www.sitemaps.org/index.html
[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
[3]: https://www.algolia.com/doc/guides/searching/faceting/
+[4]: /docs/packages/js/api-reference#facets
+[5]: https://www.algolia.com/doc/guides/managing-results/must-do/searchable-attributes/#synonyms
diff --git a/packages/website/docs/v5-breaking-changes.mdx b/packages/website/docs/v5-breaking-changes.mdx
new file mode 100644
index 00000000..f3ec2ef5
--- /dev/null
+++ b/packages/website/docs/v5-breaking-changes.mdx
@@ -0,0 +1,236 @@
+---
+title: v5 breaking changes
+description: Complete user-facing breaking changes and compatibility notes for DocSearch v5.
+---
+
+This page lists the user-facing changes between the v4.6.0 package source and `5.0.0-beta.0`. Use it with the [v4 migration guide](./migrating-from-v4).
+
+## JavaScript entry points
+
+### The root export is AI-capable
+
+In v4, the root `@docsearch/js` export rendered the combined component and allowed Ask AI to be omitted. In v5, it renders `DocSearchAI`, and its `DocSearchProps` type requires `askAi`.
+
+Use the root entry when you configure Agent Studio:
+
+```js title="app.js"
+import docsearch from '@docsearch/js';
+```
+
+### Keyword-only search moved to `/docsearch`
+
+Use the new subpath when you don't need Ask AI:
+
+```js title="app.js"
+import docsearch from '@docsearch/js/docsearch';
+```
+
+This entry excludes Ask AI code.
+
+### The UMD bundle is split
+
+- `dist/umd/index.js` includes keyword search and Ask AI.
+- `dist/umd/docsearch.js` includes keyword search only.
+- Both bundles expose `window.docsearch`.
+- Loading both bundles causes the later script to replace the same global.
+
+### An exports map restricts JavaScript imports
+
+`@docsearch/js` now exports only `.` and `./docsearch`. Replace imports of internal distribution files with one of these public entry points. Direct CDN URLs to the two documented UMD files remain supported by the package layout.
+
+## React components
+
+### `DocSearch` is keyword-only
+
+V4's `DocSearch` accepted `askAi` and `interceptAskAiEvent`. V5's `DocSearch` contains keyword search only and no longer declares those props.
+
+### `DocSearchAI` owns the AI experience
+
+Use `DocSearchAI` for keyword search and Ask AI:
+
+```jsx title="Search.jsx"
+import { DocSearchAI } from '@docsearch/react';
+```
+
+`DocSearchAIProps` extends `DocSearchProps`, requires `askAi`, and adds `interceptAskAiEvent`.
+
+The package also adds `@docsearch/react/docsearchAi` and `@docsearch/react/askaiModal` subpaths.
+
+### The Ask AI modal is separate
+
+`DocSearchModal` is keyword-only. `DocSearchAskAiModal` contains the combined keyword and AI modal. Composable integrations that rendered `DocSearchModal` with `askAi` must switch to `DocSearchAskAiModal` and its required provider callbacks. Review the [Composable API](/docs/composable-api) instead of constructing these props without the provider.
+
+`@docsearch/modal` exports the AI modal from its root and from `@docsearch/modal/askai`.
+
+## Ask AI and Agent Studio
+
+### The legacy transport is removed
+
+V5 no longer requests a legacy Ask AI token or sends chat requests to the v4 Ask AI endpoint. All Ask AI conversations use the Agent Studio completions endpoint.
+
+Create and configure an assistant in [Agent Studio](/docs/agent-studio/getting-started) before upgrading.
+
+### `askAi.agentStudio` is removed
+
+The backend switch is no longer needed because Agent Studio is the only backend. Remove both `agentStudio: true` and `agentStudio: false`.
+
+### `askAi.useStagingEnv` is removed
+
+The staging endpoint switch isn't part of `DocSearchAskAi` in v5.
+
+### Flat Ask AI search parameters are removed
+
+`DocSearchAskAi.searchParameters` now always uses `AgentStudioSearchParameters`: an object keyed by index name.
+
+```js title="app.js"
+searchParameters: {
+ docs: {
+ filters: 'language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ distinct: true,
+ },
+}
+```
+
+Each value supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`. The Agent Studio type omits `facetFilters`.
+
+### Agent Studio credentials are sent directly
+
+Ask AI requests use the configured application ID and API key in `x-algolia-application-id` and `x-algolia-api-key` headers. Memory authentication adds `x-algolia-secure-user-token`. Check the permissions and domain restrictions of keys that were issued for the legacy transport.
+
+### Feedback uses Agent Studio
+
+Feedback now posts to Agent Studio and supports negative-feedback reason tags and notes. Stored conversation messages can contain `feedbackTags` and `feedbackNotes` in addition to the like or dislike value.
+
+### Agent Studio configuration is nested under `askAi`
+
+Dynamic `indices`, custom `tools`, `memory`, and keyword `promptSuggestions` belong inside the `askAi` object. `interceptAskAiEvent` remains a top-level integration callback.
+
+### Suggested questions have two sources
+
+- `askAi.suggestedQuestions` determines whether DocSearch loads published questions for the assistant from `algolia_ask_ai_suggested_questions` on the new-conversation screen.
+- `askAi.promptSuggestions` searches a configured index containing a `prompt` attribute and displays those prompts with keyword results.
+
+These options aren't interchangeable.
+
+## Search configuration
+
+### The Docusaurus adapter configuration changed
+
+The v5 adapter reads `themeConfig.docsearch` and rejects the former `themeConfig.algolia` key. It also requires `indices` and rejects `indexName` and root `searchParameters`.
+
+Replace `searchPagePath` with `searchPage`. Move `askAi.sidePanel` to the root `sidePanel` option. Remove legacy Ask AI credentials and the `askAi.agentStudio` switch. Follow [Migrate the Docusaurus adapter from v4](/docs/packages/docusaurus-adapter/migrating-from-v4) for before-and-after configurations.
+
+### At least one index is required at runtime
+
+Pass `indices` or `indexName`. V5 throws this error when neither produces an index:
+
+```text
+Must supply either `indexName` or `indices` for DocSearch to work
+```
+
+### `indexName` remains deprecated
+
+`indexName` still works; it isn't removed in v5. If present, DocSearch places it before all `indices` entries. Passing the same index through both options sends duplicate requests.
+
+### Root `searchParameters` remains deprecated
+
+The root option applies only to `indexName`. Move search parameters to each `DocSearchIndex` in `indices`.
+
+### Multiple indices share one result flow
+
+V5 creates one source for each index response and combines hit totals across responses. Result order follows the normalized index order. Review code that assumes one index or source identifier.
+
+## New keyword search behavior
+
+### Facets add requests and filters
+
+The new `facets` option fetches facet values with a zero-hit query for every configured index. DocSearch merges and sorts values, supports at most five keys after trimmed, lowercase duplicate checks, and displays only facets with values.
+
+A selected value is appended to that index's existing `facetFilters`. Account for the additional facet-value request in analytics, rate estimates, and search-client mocks.
+
+### Result badges require retrieved attributes
+
+The new `resultBadgeKey` reads a property path from each hit. The default `attributesToRetrieve` list doesn't include custom badge properties. Add them to each relevant index's `searchParameters.attributesToRetrieve`.
+
+### Result markup and grouping changed
+
+V5 refreshes the modal and result markup, renders breadcrumbs, introduces source panels, and adds facet and badge elements. CSS selectors, DOM tests, snapshots, and custom overrides that target v4 internals can break.
+
+Use public component props for behavior and review [Styling](/docs/packages/css/styling) for visual changes.
+
+## Styles and builds
+
+### Ask AI styles have a separate source bundle
+
+The complete `@docsearch/css` stylesheet still imports button, modal, and Ask AI rules. React also exposes split style entries:
+
+- `@docsearch/react/style/variables`
+- `@docsearch/react/style/button`
+- `@docsearch/react/style/modal`
+- `@docsearch/react/style/askai`
+- `@docsearch/react/style/sidepanel`
+
+If you assemble styles by component, add `style/askai` for `DocSearchAI` or `DocSearchAskAiModal`.
+
+### Generated React file names changed
+
+The documented package subpaths remain stable, but their targets changed from names such as `dist/esm/DocSearchModal.js` to generated entry files such as `dist/esm/modal.js`. Imports that bypassed the package exports can break.
+
+### The React `main` field now points to ESM
+
+`@docsearch/react` changes `main` from `dist/umd/index.js` to `dist/esm/index.js`. Consumers that resolve `main` instead of the package exports need an ESM-compatible build pipeline. The explicit `unpkg` and `jsdelivr` fields continue to point to `dist/umd/index.js`.
+
+### The browser target is ES2017
+
+V5's tsdown builds target ES2017. Provide transpilation or polyfills if your browser support policy extends below that target.
+
+## Public controls
+
+### JavaScript instances don't expose Sidepanel state
+
+`DocSearchInstance` exposes `open`, `close`, `openAskAi`, `destroy`, `isReady`, and `isOpen`. It doesn't expose `openSidepanel`, `isSidepanelOpen`, or `isSidepanelSupported`.
+
+### React refs include Sidepanel controls
+
+`DocSearchRef` exposes the JavaScript-style modal controls plus `openSidepanel`, `isSidepanelOpen`, and `isSidepanelSupported`. `openSidepanel` does nothing until a Sidepanel view registers. On mobile, `openAskAi` and standard Ask AI actions fall back to the modal.
+
+See [hybrid mode](/docs/hybrid-mode) for the supported integration.
+
+### Deprecated keyboard hook fields remain
+
+`UseDocSearchKeyboardEventsProps.onInput` and `searchButtonRef` are accepted for compatibility but are deprecated and aren't used by the v5 React hook implementation.
+
+## Compatibility
+
+### React peer range
+
+`@docsearch/react`, `@docsearch/core`, `@docsearch/modal`, and `@docsearch/sidepanel` declare these optional peers:
+
+- `react`: `>=16.8.0 <20.0.0`
+- `react-dom`: `>=16.8.0 <20.0.0`
+- `@types/react`: `>=16.8.0 <20.0.0`
+
+`@docsearch/react` also accepts optional `search-insights` versions `>=1 <3`.
+
+### Package versions must match
+
+The `5.0.0-beta.0` packages depend on matching beta versions of the other DocSearch packages. Don't mix v4 and v5 packages in a Composable API or Sidepanel tree.
+
+### CSS remains a separate install for top-level integrations
+
+Install `@docsearch/css@^5.0.0-beta`, then import `@docsearch/css`. For a CDN integration, load `dist/style.css` from the same caret beta range.
+
+## Additive v5 APIs
+
+These additions aren't breaking by themselves, but they replace common v4 custom implementations:
+
+- `facets` and `DocSearchFacet` for keyword filters.
+- `resultBadgeKey` for hit metadata.
+- `DocSearchAI` and `DocSearchAskAiModal` for AI-capable React views.
+- `AgentStudioIndices` and `AgentStudioSearchControls` for dynamic search tools.
+- `ToolCalls` and `ToolDefinition` for custom Agent Studio tools.
+- `Memory` for user-scoped Agent Studio memory.
+- `PromptSuggestions` for keyword-query prompt suggestions.
+- Ask AI feedback tags and notes.
+- Split JavaScript, React, and style entries for smaller keyword-only builds.
diff --git a/packages/website/docs/what-is-docsearch.md b/packages/website/docs/what-is-docsearch.md
index 5b9cc3c9..cd0ecc17 100644
--- a/packages/website/docs/what-is-docsearch.md
+++ b/packages/website/docs/what-is-docsearch.md
@@ -1,24 +1,27 @@
---
title: What is DocSearch?
+description: Understand how DocSearch provides search for technical documentation.
sidebar_label: What is DocSearch?
---
## Why?
-We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+We created DocSearch because developers spend a lot of time reading documentation, and finding relevant information in large documentation sites can be difficult. Building good search is a challenge.
-It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+Algolia has extensive experience building search interfaces. We use that experience to extract content from technical documentation and make it searchable from the first keystroke.
-## Quick description
+## Overview
-We split DocSearch into a crawler and a frontend library.
+DocSearch has two independent parts: indexing and the frontend search experience.
-- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
-- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+- The [Algolia Crawler][4] extracts your documentation into an Algolia index. Use the [Crawler interface][5] to edit the crawler configuration, monitor crawls, and trigger new crawls.
+- The [DocSearch v5 packages][7] query that index and render keyword search or Ask AI in your frontend. They are built on [Algolia Autocomplete][6].
+
+Crawler configuration and record schema versions don't select the installed DocSearch frontend package version. You can update the frontend package without changing how the crawler is scheduled.
## How to feature DocSearch?
-DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+DocSearch is free for eligible documentation sites. Read [the eligibility requirements][2] and apply. After approval and indexing, add a [DocSearch v5 package][7] or a supported framework integration to your website. Keep the "Search by Algolia" link displayed.
DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
@@ -30,3 +33,4 @@ You can now [apply to the program][3]
[4]: https://www.algolia.com/products/search-and-discovery/crawler/
[5]: https://dashboard.algolia.com/crawler
[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[7]: /docs/packages/overview
diff --git a/packages/website/docs/who-can-apply.md b/packages/website/docs/who-can-apply.md
index 320814d0..317b2249 100644
--- a/packages/website/docs/who-can-apply.md
+++ b/packages/website/docs/who-can-apply.md
@@ -1,30 +1,32 @@
---
title: Who can apply?
+description: Check whether your documentation project is eligible for DocSearch.
---
-**Open for all developer documentation and technical blogs.**
+**Open to developer documentation and technical blogs.**
-We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all online technical documentations and technical blogs.
+We built DocSearch to improve search on large technical documentation sites. We offer the free DocSearch program to public technical documentation and technical blogs.
We usually turn down applications when they are not production ready or have non-technical content on the website.
## Application process
-To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+To [apply][1] to the DocSearch program, follow the onboarding process in the Algolia dashboard. Submit your domain for validation against the program requirements. If your domain meets the criteria, you can create your DocSearch crawler.
-- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+- Use one of our [supported integrations][3] or a [DocSearch v5 package][5] after your content is indexed.
-- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+- Verify your domain ownership within 7 days of approval to continue using the crawler.
-- β
Please review [DocSearch Plan Terms and Conditions][2].
+- Review the [DocSearch Plan Terms and Conditions][2].
## Process duration
-DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+The application process includes automated validation. If we can't determine your eligibility automatically, we'll conduct a manual review that may take one to two business days.
-Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+Once approved, continue the onboarding process to create your DocSearch crawler. After the crawler indexes your data, choose the frontend package or framework integration separately. Updating the frontend doesn't change your crawler or index format.
[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
[3]: integrations.md
[4]: https://alg.li/discord
+[5]: /docs/packages/overview
diff --git a/packages/website/docusaurus.config.mjs b/packages/website/docusaurus.config.mjs
index f1605941..8c70af8f 100644
--- a/packages/website/docusaurus.config.mjs
+++ b/packages/website/docusaurus.config.mjs
@@ -50,7 +50,10 @@ export default {
'https://github.com/algolia/docsearch/edit/main/packages/website/',
versions: {
current: {
- label: 'Latest (v4.x)',
+ label: 'Beta (v5.0.0-beta.x)',
+ },
+ v4: {
+ label: 'Stable (v4.x)',
},
v3: {
label: 'Legacy (v3.x)',
@@ -138,9 +141,9 @@ export default {
],
},
announcementBar: {
- id: 'announcement-bar',
+ id: 'docsearch-v5-beta',
content:
- 'π Get Ask AI now! Turn your docs site search into an AI-powered assistant β faster answers, fewer tickets, better self-serve. Get Started Now',
+ 'DocSearch 5.0.0-beta is available. Migrate from v4 or choose a package.',
},
colorMode: {
defaultMode: 'light',
@@ -165,8 +168,12 @@ export default {
to: 'docs/v3/docsearch',
},
{
- label: 'DocSearch v4 - Beta',
- to: 'docs/docsearch',
+ label: 'DocSearch v4',
+ to: 'docs/v4/docsearch',
+ },
+ {
+ label: 'DocSearch v5 beta',
+ to: 'docs/packages/overview',
},
],
},
diff --git a/packages/website/sidebars.js b/packages/website/sidebars.js
index cc5d370b..c4fbae84 100644
--- a/packages/website/sidebars.js
+++ b/packages/website/sidebars.js
@@ -13,19 +13,87 @@ export default {
{
type: 'category',
label: 'Introduction',
- items: ['what-is-docsearch', 'who-can-apply'],
+ items: [
+ 'what-is-docsearch',
+ 'who-can-apply',
+ 'migrating-from-v4',
+ 'v5-breaking-changes',
+ ],
},
{
type: 'category',
- label: 'DocSearch v4',
+ label: 'Packages',
items: [
- 'docsearch',
- 'docusaurus-adapter',
+ 'packages/overview',
+ {
+ type: 'category',
+ label: '@docsearch/js',
+ items: ['packages/js/getting-started', 'packages/js/api-reference'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/react',
+ items: [
+ 'packages/react/getting-started',
+ 'packages/react/api-reference',
+ 'packages/react/examples',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/modal',
+ items: ['packages/modal/overview', 'packages/modal/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel',
+ items: [
+ 'packages/sidepanel/getting-started',
+ 'packages/sidepanel/advanced-use-cases',
+ 'packages/sidepanel/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel-js',
+ items: [
+ 'packages/sidepanel-js/getting-started',
+ 'packages/sidepanel-js/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/css',
+ items: ['packages/css/styling', 'packages/css/bundle-exports'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/core',
+ items: ['packages/core/overview', 'packages/core/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/docusaurus-adapter',
+ items: [
+ 'packages/docusaurus-adapter/getting-started',
+ 'packages/docusaurus-adapter/configuration-reference',
+ 'packages/docusaurus-adapter/migrating-from-v4',
+ ],
+ },
'composable-api',
- 'styling',
- 'api',
- 'examples',
- 'migrating-from-v3',
+ 'hybrid-mode',
+ ],
+ },
+ {
+ type: 'category',
+ label: 'Agent Studio',
+ items: [
+ 'agent-studio/getting-started',
+ 'agent-studio/dynamic-indices',
+ 'agent-studio/tools',
+ 'agent-studio/memory',
+ 'agent-studio/prompt-suggestions',
+ 'agent-studio/feedback',
],
},
{
@@ -33,34 +101,6 @@ export default {
label: 'MCP',
items: ['mcp/overview', 'mcp/installation', 'mcp/usage'],
},
- {
- type: 'category',
- label: 'Algolia Ask AI',
- items: [
- 'v4/askai',
- 'v4/askai-api',
- 'v4/askai-prompts',
- 'v4/askai-whitelisted-domains',
- 'v4/askai-models',
- 'v4/askai-markdown-indexing',
- 'v4/askai-errors',
- {
- type: 'link',
- label: 'Full Documentation',
- href: 'https://www.algolia.com/doc/guides/algolia-ai/askai',
- },
- ],
- },
- {
- type: 'category',
- label: 'Sidepanel',
- items: [
- 'sidepanel/getting-started',
- 'sidepanel/advanced-use-cases',
- 'sidepanel/hybrid',
- 'sidepanel/api-reference',
- ],
- },
{
type: 'category',
label: 'Algolia Crawler',
diff --git a/packages/website/src/components/Home.js b/packages/website/src/components/Home.js
index a8a4ea86..ee5dbb91 100644
--- a/packages/website/src/components/Home.js
+++ b/packages/website/src/components/Home.js
@@ -116,9 +116,9 @@ function Home() {
+ eyebrow="Interactive demo"
+ title="See DocSearch in action"
+ />
diff --git a/packages/website/versioned_docs/version-v4/api.mdx b/packages/website/versioned_docs/version-v4/api.mdx
new file mode 100644
index 00000000..ecf87ebb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/api.mdx
@@ -0,0 +1,935 @@
+---
+title: API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+
+
+
+## `container`
+
+> `type: string | HTMLElement` | **required**
+
+The container for the DocSearch search box. You can either pass a [CSS selector][5] or an [Element][6]. If there are several containers matching the selector, DocSearch picks up the first one.
+
+## `environment`
+
+> `type: typeof window` | `default: window` | **optional**
+
+The environment in which your application is running.
+
+This is useful if youβre using DocSearch in a different context than `window`.
+
+
+
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `indices`
+
+> `type: Array`
+
+The list of indices and their _optional_ `searchParameters` to be used for keyword search.
+
+[Algolia Search Parameters][7]
+
+:::tip
+
+The ordering matters in the list, as results are ordered based on `indices` order.
+
+:::
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+
+
+
+```js
+docsearch({
+ // ...
+ indices: ['YOUR_ALGOLIA_INDEX'],
+ // ...
+});
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```js
+docsearch({
+ // ...
+ indices: [
+ {
+ name: 'YOUR_ALGOLIA_INDEX',
+ searchParameters: {
+ facetFilters: ['language:en'],
+ // ...
+ },
+ },
+ ],
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```jsx
+
+```
+
+
+
+
+## `indexName`
+
+> `type: string` | **deprecated**
+
+:::warning[Deprecation warning]
+
+`indexName` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+Your Algolia index name.
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+## `placeholder`
+
+> `type: string` | `default: "Search docs"` | **optional**
+
+The placeholder of the input of the DocSearch pop-up modal. Note: If you add a placeholder, it will replace the dynamic placeholder based on `askAi`. It would be better to edit [translations](#translations) instead.
+
+## `askAi`
+
+> `type: AskAiObject` | `string` | **optional**
+
+Your Algolia Assistant ID.
+
+
+
+
+```js
+docsearch({
+ // ...
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ // ...
+});
+```
+
+or if you want to use different credentials for `askAi` and add search parameters
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ indexName: 'ANOTHER_INDEX_NAME',
+ apiKey: 'ANOTHER_SEARCH_API_KEY',
+ appId: 'ANOTHER_APP_ID',
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ // Filtering parameters
+ facetFilters: ['language:en', 'version:latest'],
+ filters: 'type:content AND language:en',
+
+ // Content control parameters
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+
+ // Deduplication
+ distinct: true,
+ },
+
+ // Enables/disables showing suggested questions on Ask AI's new conversation screen
+ // NOTE: Only available with version >= 4.3
+ suggestedQuestions: true,
+ },
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use different credentials for `askAi`
+
+```jsx
+= 4.3
+ suggestedQuestions: true,
+ }}
+/>
+```
+
+
+
+
+:::tip[Ask AI supports these essential search parameters for optimal performance:]
+
+- **Filtering**: `facetFilters: ['type:content']` - Filter by language, version, or content type
+- **Complex filtering**: `filters: 'type:content AND language:en'` - Apply complex filtering rules
+- **Content control**: `attributesToRetrieve: ['title', 'content', 'url']` - Control which attributes are retrieved
+- **Search scope**: `restrictSearchableAttributes: ['title', 'content']` - Limit search to specific fields
+- **Deduplication**: `distinct: true` - Remove duplicate results (`boolean | number | string`)
+
+These parameters provide the essential functionality for Ask AI while keeping the API simple and focused.
+
+:::
+
+### `askAi.agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`askAi.agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `askAi.agentStudio` is `true`, the Ask AI chat will use Algolia's [Agent Studio][12] as the chat backend instead of the Ask AI backend. Learn more on [Algolia Agent Studio Docs][13].
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+::::info[Search parameter shapes]
+
+- Standard Ask AI (`agentStudio` omitted or `false`): `searchParameters` is a flat object and supports `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- Agent Studio (`agentStudio: true`): `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+::::
+
+## `searchParameters`
+
+> `type: SearchParameters` | **optional** | **deprecated**
+
+:::warning[Deprecation warning]
+
+`searchParameters` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+The [Algolia Search Parameters][7].
+
+## `transformItems`
+
+> `type: function` | `default: items => items` | **optional**
+
+Receives the items from the search response, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them.
+
+
+
+
+```js
+docsearch({
+ // ...
+ transformItems(items) {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ }}
+/>
+```
+
+
+
+
+## `hitComponent`
+
+> `type: ({ hit, children }, { html }) => JSX.Element | string | Function` | `default: Hit` | **optional**
+
+The component to display each item. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ hit, children }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ hit, children }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the `hit` object which contains all the data for the search result, and `children` which is the default rendered content.
+
+See the [default implementation][8].
+
+
+
+
+```js
+docsearch({
+ // ...
+ hitComponent({ hit, children }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+
+ ${children}
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ π
+ {children}
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `transformSearchClient`
+
+> `type: function` | `default: DocSearchTransformClient => DocSearchTransformClient` | **optional**
+
+Useful for transforming the [Algolia Search Client][10], for example to [debounce search queries][9]
+
+## `disableUserPersonalization`
+
+> `type: boolean` | `default: false` | **optional**
+
+Disable saving recent searches and favorites to the local storage.
+
+## `initialQuery`
+
+> `type: string` | **optional**
+
+The search input initial query.
+
+## `navigator`
+
+> `type: Navigator` | **optional**
+
+An implementation of [Algolia Autocomplete][1]βs Navigator API to redirect the user when opening a link.
+
+Learn more on the [Navigator API][11] documentation.
+
+## `translations`
+
+> `type: Partial` | `default: docSearchTranslations` | **optional**
+
+Allow translations of any raw text and aria-labels present in the DocSearch button or modal components.
+
+
+docSearchTranslations
+
+
+```ts
+const translations: DocSearchTranslations = {
+ button: {
+ buttonText: 'Search',
+ buttonAriaLabel: 'Search',
+ },
+ modal: {
+ searchBox: {
+ clearButtonTitle: 'Clear',
+ clearButtonAriaLabel: 'Clear the query',
+ closeButtonText: 'Close',
+ closeButtonAriaLabel: 'Close',
+ placeholderText: undefined, // fallback: 'Search docs' or 'Search docs or ask AI a question'
+ placeholderTextAskAi: undefined, // fallback: 'Ask another question...'
+ placeholderTextAskAiStreaming: 'Answering...',
+ // can only be one of the following
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/enterkeyhint#value
+ enterKeyHint: 'search',
+ enterKeyHintAskAi: 'enter',
+ searchInputLabel: 'Search',
+ backToKeywordSearchButtonText: 'Back to keyword search',
+ backToKeywordSearchButtonAriaLabel: 'Back to keyword search',
+ newConversationPlaceholder: 'Ask a question',
+ conversationHistoryTitle: 'My conversation history',
+ startNewConversationText: 'Start a new conversation',
+ viewConversationHistoryText: 'Conversation history'
+ },
+ startScreen: {
+ recentSearchesTitle: 'Recent',
+ noRecentSearchesText: 'No recent searches',
+ saveRecentSearchButtonTitle: 'Save this search',
+ removeRecentSearchButtonTitle: 'Remove this search from history',
+ favoriteSearchesTitle: 'Favorite',
+ removeFavoriteSearchButtonTitle: 'Remove this search from favorites',
+ recentConversationsTitle: 'Recent conversations',
+ removeRecentConversationButtonTitle:
+ 'Remove this conversation from history',
+ },
+ errorScreen: {
+ titleText: 'Unable to fetch results',
+ helpText: 'You might want to check your network connection.',
+ },
+ noResultsScreen: {
+ noResultsText: 'No results found for',
+ suggestedQueryText: 'Try searching for',
+ reportMissingResultsText: 'Believe this query should return results?',
+ reportMissingResultsLinkText: 'Let us know.',
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'Ask AI: ',
+ noResultsAskAiPlaceholder: 'Didn't find it in the docs? Ask AI to help: ',
+ },
+ askAiScreen: {
+ disclaimerText:
+ 'Answers are generated with AI which can make mistakes. Verify responses.',
+ relatedSourcesText: 'Related sources',
+ thinkingText: 'Thinking...',
+ copyButtonText: 'Copy',
+ copyButtonCopiedText: 'Copied!',
+ copyButtonTitle: 'Copy',
+ likeButtonTitle: 'Like',
+ dislikeButtonTitle: 'Dislike',
+ thanksForFeedbackText: 'Thanks for your feedback!',
+ preToolCallText: 'Searching...',
+ duringToolCallText: 'Searching for ',
+ afterToolCallText: 'Searched for',
+ // If provided, these override the default rendering of aggregated tool calls:
+ aggregatedToolCallNode: undefined, // (queries: string[], onSearchQueryClick: (query: string) => void) => React.ReactNode
+ aggregatedToolCallText: undefined, // (queries: string[]) => { before?: string; separator?: string; lastSeparator?: string; after?: string }
+ // Text to show when user has stopped streaming a message
+ stoppedStreamingText: 'You stopped this response',
+ },
+ footer: {
+ selectText: 'Select',
+ submitQuestionText: 'Submit question',
+ selectKeyAriaLabel: 'Enter key',
+ navigateText: 'Navigate',
+ navigateUpKeyAriaLabel: 'Arrow up',
+ navigateDownKeyAriaLabel: 'Arrow down',
+ closeText: 'Close',
+ backToSearchText: 'Back to search',
+ closeKeyAriaLabel: 'Escape key',
+ poweredByText: 'Powered by',
+ },
+ newConversation: {
+ newConversationTitle: 'How can I help you today?',
+ newConversationDescription: 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.'
+ }
+ },
+};
+```
+
+
+
+
+## `getMissingResultsUrl`
+
+> `type: ({ query: string }) => string` | **optional**
+
+Function to return the URL of your documentation repository.
+
+
+
+
+```js
+docsearch({
+ // ...
+ getMissingResultsUrl({ query }) {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ }}
+/>
+```
+
+
+
+
+When provided, an informative message wrapped with your link will be displayed on no results searches. The default text can be changed using the [translations](#translations) property.
+
+
+
+
+
+## `keyboardShortcuts`
+
+> `type: KeyboardShortcuts` | **optional**
+
+Configuration for keyboard shortcuts that trigger the search modal.
+
+### Default behavior:
+
+- `Ctrl/Cmd+K` - Opens and closes the search modal
+- `/` - Opens the search modal (doesn't close)
+
+### Interface:
+
+```typescript
+interface KeyboardShortcuts {
+ 'Ctrl/Cmd+K'?: boolean; // default: true
+ '/'?: boolean; // default: true
+}
+```
+
+
+
+
+```js
+// Default - all shortcuts enabled
+docsearch({
+ // ...
+});
+
+// Disable slash shortcut
+docsearch({
+ // ...
+ keyboardShortcuts: { '/': false },
+});
+
+// Disable Ctrl/Cmd+K shortcut (also hides button hint)
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false },
+});
+
+// Disable all keyboard shortcuts
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false, '/': false },
+});
+```
+
+
+
+
+
+```jsx
+{
+ /* Default - all shortcuts enabled */
+}
+ ;
+
+{
+ /* Disable slash shortcut */
+}
+ ;
+
+{
+ /* Disable Ctrl/Cmd+K shortcut (also hides button hint) */
+}
+ ;
+
+{
+ /* Disable all keyboard shortcuts */
+}
+ ;
+```
+
+
+
+
+:::info[Keyboard Shortcut Behavior]
+
+- **Ctrl/Cmd+K**: Toggle shortcut that both opens and closes the modal
+- **/**: Character shortcut that only opens the modal (prevents interference with search typing)
+- **Escape**: Always works to close the modal regardless of Configuration
+
+:::
+
+## `resultsFooterComponent`
+
+> `type: ({ state }, { html }) => JSX.Element | string | Function` | **optional**
+
+The component to display below the search results. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ state }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ state }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the [current state](https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/types/AutocompleteState.ts) which allows you to retrieve the number of hits returned, the query etc.
+
+
+
+
+```js
+docsearch({
+ // ...
+ resultsFooterComponent({ state }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `maxResultsPerGroup`
+
+> `type: number` | **optional**
+
+The maximum number of results to display per search group. Default is 5.
+
+[You can find a working example without JSX in this sandbox](https://codesandbox.io/s/docsearch-v3-maxresultspergroup-without-jsx-ct9m22?file=/src/index.js)
+
+
+
+
+```js
+docsearch({
+ // ...
+ maxResultsPerGroup: 7,
+});
+```
+
+
+
+
+
+## `recentSearchesLimit`
+
+> `type: number` | `default: 7` | **optional**
+
+The maximum number of recent searches that are stored for the user. Default is 7.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesLimit: 12,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `recentSearchesWithFavoritesLimit`
+
+> `type: number` | `default: 4` | **optional**
+
+The maximum number of recent searches that are stored when the user has favorited searches. Default is 4.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesWithFavoritesLimit: 5,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `portalContainer` (React-only)
+
+> `type: Element | DocumentFragment` | `default: document.body` | **optional**
+
+The element where the DocSearch modal will be portaled. Use this when you need the overlay to render in a custom DOM nodeβfor example when working inside a shadow root, a specific layout container, or a modal manager. When omitted, the modal portals to `document.body`.
+
+:::warning
+
+This prop only exists in `@docsearch/react`. If you are using **`@docsearch/js`**, use the [`container`](#container) option insteadβthe value you pass there is both the **mount point** of the search button _and_ the portal target for the modal.
+
+:::
+
+
+
+
+```jsx
+// assume you have a dedicated modal root in your html
+;
+
+const portalEl = document.getElementById('modal-root');
+
+ ;
+```
+
+
+
+
+
+```js
+docsearch({
+ // the element that will **contain the button** and **host the modal portal**
+ container: '#modal-root',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+});
+```
+
+
+
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[6]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[7]: https://www.algolia.com/doc/api-reference/search-api-parameters/
+[8]: https://github.com/algolia/docsearch/blob/main/packages/docsearch-react/src/Hit.tsx
+[9]: https://codesandbox.io/s/docsearch-v3-debounced-search-gnx87
+[10]: https://www.algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/?client=javascript
+[11]: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/keyboard-navigation/
+[12]: https://www.algolia.com/products/ai/agent-studio
+[13]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/composable-api.mdx b/packages/website/versioned_docs/version-v4/composable-api.mdx
new file mode 100644
index 00000000..314b6e1b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/composable-api.mdx
@@ -0,0 +1,315 @@
+---
+title: Composable API
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+The Composable API is available from version `>= 4.3`
+:::
+
+DocSearch has a new Composable API for rendering the DocSearch button and modal. This API was
+introduced to help with more explicit control over where and how the components are rendered within a page.
+
+## Introduction
+
+The Composable API was introduced to help give more flexibility on how you render and use DocSearch on your website. With it,
+you have more control of where, when and how you want to bundle the components and render them.
+
+With Composable API comes two new NPM packages:
+
+- `@docsearch/core` - Shared core logic for managing different states of DocSearch
+- `@docsearch/modal` - The actual components used for the DocSearch Modal
+
+:::warning
+Because of the nature of composability, this API is only available within React, and not within the `@docsearch/js` package.
+:::
+
+## Getting Started
+
+In order to start using the Composable API, you will need to install the following three packages:
+
+
+
+
+```bash
+npm install @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+The most simple implementation would be as follows:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+:::info
+The actual components MUST be rendered within the `` Provider in order for them to communicate with the global state.
+:::
+
+This setup is slightly more involved with now rendering three different components:
+
+- `` is the parent element which controls and shares all state with the child components
+- ` ` is the actual button element that is rendered and triggers the DocSearch Modal to open
+- ` ` is the main modal containing the search form, search results, and Ask AI
+
+
+### Ask AI
+
+Using Ask AI with the Composable API is quite similar to the normal way of using DocSearch. All that is needed is the `askAi` configuration:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+You can find more information on Ask AI, and its setup in its [dedicated docs][2].
+
+### Advanced
+
+```tsx
+export default function AdvancedSearch(): JSX.Element {
+ return (
+
+
+
+
+ );
+}
+```
+
+### Bundle saving exports
+
+To help aid in trimming initial bundle size, the `@docsearch/modal` package exposes explicit file exports as well:
+
+```ts
+import { DocSearchButton } from '@docsearch/modal/button';
+import { DocSearchModal } from '@docsearch/modal/modal';
+```
+
+Here is a basic example of delaying the loading of the `DocSearchModal` code until the search button is clicked:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton } from '@docsearch/modal/button';
+import type { DocSearchModal as DocSearchModalType } from '@docsearch/modal/modal';
+import { useState } from 'react';
+
+let DocSearchModal: typeof DocSearchModalType | null = null;
+
+async function importDocSearchModalIfNeeded() {
+ if (DocSearchModal) {
+ return;
+ }
+
+ const { DocSearchModal: Modal } = await import('@docsearch/modal/modal');
+
+ DocSearchModal = Modal;
+}
+
+export default function DynamicModal() {
+ const [modalLoaded, setModalLoaded] = useState(false);
+
+ const loadModal = () => {
+ importDocSearchModalIfNeeded().then(() => {
+ setModalLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {modalLoaded && DocSearchModal && (
+
+ )}
+
+ );
+}
+```
+
+## Components
+
+### ` `
+
+The ` ` component from the `@docsearch/core` package is the main state handler for all of DocSearch.
+It utilizes [React Context][1] to enable sharing its state across nested components.
+
+#### Props
+
+```ts
+interface DocSearchProps {
+ // React children to be rendered within the DocSearch Provider
+ children: Array | JSX.Element | React.ReactNode | null;
+ // Theme to be set enabling style changes for `light` or `dark` themes
+ theme?: 'light' | 'dark';
+ // Initial starting query for keyword search
+ initialQuery?: string;
+ // Manage supported keyboard shortcuts for opening/closing the DocSearch Modal
+ keyboardShortcuts?: {
+ 'Ctrl/Cmd+K': boolean,
+ '/': boolean,
+ };
+}
+```
+
+### ` `
+
+The main DocSearch search button to trigger the DocSearch Modal.
+
+#### Props
+
+```ts
+interface DocSearchButtonProps {
+ // Optional callback for when the button is clicked. The original click event is passed.
+ onClick?: (event: React.MouseEvent) => void;
+ // Translation strings specific to the button.
+ translations: {
+ buttonText?: string;
+ buttonAriaLabel?: string;
+ };
+}
+```
+
+### ` `
+
+The main keyword search Modal used to search your documentation.
+
+#### Props
+
+```ts
+interface DocSearchModalProps {
+ /**
+ * Algolia application id used by the search client.
+ */
+ appId: string;
+ /**
+ * Public api key with search permissions for the index.
+ */
+ apiKey: string;
+ /**
+ * Name of the algolia index to query.
+ *
+ * @deprecated `indexName` will be removed in a future version. Please use `indices` property going forward.
+ */
+ indexName?: string;
+ /**
+ * List of indices and _optional_ searchParameters to be used for search.
+ *
+ * @see {@link https://docsearch.algolia.com/docs/api#indices}
+ */
+ indices?: Array;
+ /**
+ * Configuration or assistant id to enable ask ai mode. Pass a string assistant id or a full config object.
+ */
+ askAi?: DocSearchAskAi | string;
+ // ...
+}
+```
+
+More property documentation can be found in the [DocSearch API Reference][3] page.
+
+[1]: https://react.dev/reference/react/createContext
+[2]: /docs/v4/v4/askai
+[3]: /docs/api
diff --git a/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
new file mode 100644
index 00000000..cc913ea4
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
@@ -0,0 +1,96 @@
+---
+title: New Crawler UI/UX
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+The Algolia Crawler Visual UI provides an updated, user-friendly way to manage your crawl settings and monitor your indexing process. This guide covers the main features of the new interface.
+
+## DocSearch Tab
+
+The Crawler UI now includes a dedicated **DocSearch** tab. This tab provides everything you need to implement DocSearch on your site, including:
+
+- **Implementation code**: Copy-paste ready code snippets for integrating DocSearch into your frontend.
+- **API keys**: Your unique Application ID and Search API Key for connecting to your Algolia index.
+- **Quick links**: Access to review your records, explore documentation, and join the support Discord.
+
+
+
+
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `Monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+You can update your crawler configuration in two ways:
+
+**Visual Configuration UI:**
+Quickly edit common options without writing code using the new Visual Configuration interface.
+
+
+
+
+
+**Code Editor:**
+For advanced configuration, use the live code editor to directly modify your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to debug selectors or see how the crawler interprets your site.
+
+
+
+
+
+## Suggestions
+
+The **Suggestions** section in the Crawler UI provides actionable feedback to help you improve your crawl and data extraction. After each crawl, you'll see recommendations for:
+
+- Fixing redirect or domain issues
+- Addressing ignored or failed URLs
+- Adding missing sitemaps
+
+Each suggestion includes a description, a solution, and quick links to relevant documentation or monitoring tools, so you can resolve issues efficiently and optimize your search experience.
+
+
+
+
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/crawler.mdx b/packages/website/versioned_docs/version-v4/crawler.mdx
new file mode 100644
index 00000000..f2e4b3f9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler.mdx
@@ -0,0 +1,120 @@
+---
+title: DocSearch x Algolia Crawler
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][3] team know.
+
+You can also read our [Crawler FAQ](https://www.algolia.com/doc/tools/crawler/troubleshooting/crawl-status/), to understand how it behaves:
+
+- [One of my pages wasn't crawled](https://www.algolia.com/doc/tools/crawler/troubleshooting/extraction-issues/#a-page-wasnt-crawled)
+- [Why are my pages skipped?](https://www.algolia.com/doc/tools/crawler/troubleshooting/fetching-issues/)
+
+For questions related to the DocSearch program, please see our [DocSearch program FAQ](/docs/docsearch-program).
+
+## How often will you crawl my website?
+
+Crawls are scheduled at a random time once a week. You can [configure this schedule from the config file](https://www.algolia.com/doc/tools/crawler/apis/configuration/schedule/) or trigger one manually from [the Crawler interface][2].
+
+## Why do I have duplicate content in my results?
+
+This can happen when you have more than one URL pointing to the same content, for example with `./docs`, `./docs/` and `./docs/index.html`.
+
+We recommend configuring canonical URLs on your website, you can read more on the ["Consolidate duplicate URLs" guide by Google](https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls).
+
+Ultimately, it is possible to set the [`exclusionPatterns`](https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/) to all the patterns you want to exclude.
+
+## Are the [`docsearch-scraper`](https://github.com/algolia/docsearch-scraper) and [`docsearch-configs`](https://github.com/algolia/docsearch-configs) repository still maintained?
+
+We've deprecated our legacy infrastructure, but you can still use it to [run your own instance](/docs/legacy/run-your-own) and plug it to [DocSearch v3](/docs/v3/docsearch)!
+
+## How to migrate
+
+> Every owner should have received a migration email from Algolia with the details. If you were not part of the previous `index` owners, or the maintainer has changed, you can request access via [our support page](https://www.algolia.com/support/).
+
+All the steps are detailed in the email you've received, but in order to use the new infrastructure you need to:
+
+- Join the Algolia application with the invite included in the email
+- Update your frontend integration with the credentials received in the email.
+
+
+
+
+```js app.js
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_NEW_ALGOLIA_APP_ID',
+ apiKey: 'YOUR_NEW_ALGOLIA_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME', // it does not change
+});
+```
+
+
+
+
+
+```jsx App.js
+
+```
+
+
+
+
+
+## What should I do with my legacy config and credentials?
+
+You can forget about them, we will do the cleaning once all of our users have migrated to the new infrastructure!
+
+You should use [the dedicated web interface][2] to make any changes to your index.
+
+## Why do I see two Algolia apps in my dashboard?
+
+We did not remove access to the legacy DocSearch application (`BH4D9OD16A`) to give you the time to get familiar with our new infrastructure. `BH4D9OD16A` will remain available until the migration has been completed for all the DocSearch users.
+
+## Search yields no results
+
+If your search does not yield any results, but there is no error in [your browser developer tools](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), there might be an issue with your index.
+
+Make sure that:
+
+1. [Your Crawler config](/docs/record-extractor) matches your website structure
+
+We provide [config templates](/docs/templates) for many website generators, but you can also use them as a base. To debug your selectors, we recommend using [the URL tester](/docs/manage-your-crawls/#url-tester).
+
+2. Your index settings are up to date (you'll see a banner in [the search preview](/docs/manage-your-crawls/#search-preview) if not)
+
+The Crawler only applies `index settings` at index creation time, to keep the Algolia dashboard as the source of truth. If you have drastically changed your config, or moved to a website generator, we recommend you to delete your index from the Algolia dashboard before starting a new crawl.
+
+## Can I delete my crawler?
+
+No. Well, you can but once you do things will not work correctly. We automatically create a default crawler that is associated with your DocSearch application and deleting it with the intention of creating a new one will not work as expected.
+
+## What if I delete my DocSearch Crawler?
+
+The fastest way will be to connect with us on our [Discord](https://alg.li/discord). Alternatively, email us at the address below and we will get to it as soon as we can.
+
+## Can I use the Crawler on password protected sites?
+
+The Crawler as used with DocSearch applications cannot be used for password protected sites that require a login. If you need this functionality, you need to utilize a regular Algolia plan https://www.algolia.com/pricing and add a crawler to it. Note that while it is free to add a pay-as-you-go crawler, the free tier does have limitations.
+
+## Links related to the migration
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+[1]: https://alg.li/discord
+[2]: https://dashboard.algolia.com/crawler
+[3]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/create-crawler.mdx b/packages/website/versioned_docs/version-v4/create-crawler.mdx
new file mode 100644
index 00000000..5e7c5124
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/create-crawler.mdx
@@ -0,0 +1,78 @@
+---
+title: Create a New Crawler
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+# Create a New Crawler
+
+:::info
+New DocSearch apps created after **July 2nd, 2024** can now use the Algolia Crawler UI to set up and manage their crawls. This guide walks you through the process of adding your domain, verifying ownership, creating a crawler, and running your first test crawl. You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+
+If you signed up before July 2nd, 2024, you can still use the Crawler UI, but creating and managing a Crawler is more streamlined for users who joined after that date.
+
+Learn more about the [New Crawler UI/UX features](./crawler-configuration-visual).
+:::
+
+## Add domains
+
+1. Sign in to the [Algolia dashboard](https://dashboard.algolia.com/crawler).
+2. In the left sidebar, select **Data sources**.
+3. Select **Crawler**:
+ - Click **Add your domain** and enter the domains or subdomains you want to crawl (e.g., `example.com`, `www.example.com`).
+ - If youβve already added a domain, click the **Domains** tab.
+4. Click **Add domain**.
+
+
+
+
+
+> **Note:** You must verify your domain within a 7-day grace period after adding it. Additionally, your domain must be approved for use by the DocSearch team before you can proceed with crawling.
+
+## Verify your domain
+
+You must verify ownership of each domain you want to crawl. The default method is email verification, but you can also use a meta tag, HTML file, robots.txt, or DNS record.
+
+### Meta tag
+1. In the **Meta tag** tab, click **Copy** to copy the verification tag.
+2. Add the tag to your site's `` section.
+3. Publish your site and click **Verify now** in the Crawler dashboard.
+
+### HTML file
+1. In the **HTML file** tab, click **Copy** to copy the verification file content.
+2. Save it as a new HTML file and upload it to your web server.
+3. Add the fileβs URL in the dashboard and click **Verify now**.
+
+### robots.txt
+1. In the **Robots.txt** tab, click **Copy** to copy the verification code.
+2. Paste it into your site's `robots.txt` file.
+3. Publish and click **Verify now**.
+
+### DNS
+1. In the **DNS** tab, copy the provided DNS TXT record.
+2. Add it to your DNS providerβs settings.
+3. Click **Verify now** after the record propagates (may take up to 72 hours).
+
+## Create a new crawler
+
+Once your domain is verified and approved by our DocSearch team:
+1. Go to the **Crawler** page in the dashboard.
+2. Click **New Crawler** and fill in:
+ - **Crawler name** (descriptive)
+ - **App ID** (your Algolia application ID)
+ - **Start URL** (usually your home page)
+ - **Crawler template** (choose a template or default)
+3. Click **Create** to finish and run a test crawl.
+
+## Run the test crawl
+
+The initial crawl will visit up to 100 URLs to test access and extraction. You can monitor progress in the **Overview** page. After completion, review the extracted records in the Algolia dashboard.
+
+## Next steps
+
+- Edit your crawler configuration for scheduled crawls, inclusion/exclusion rules, and extraction settings.
+- Use the Crawlerβs suggestions for further optimization.
+- For more details, see the [official Algolia documentation](https://www.algolia.com/doc/tools/crawler/getting-started/create-crawler/).
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/docsearch-program.md b/packages/website/versioned_docs/version-v4/docsearch-program.md
new file mode 100644
index 00000000..29d65ae2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch-program.md
@@ -0,0 +1,131 @@
+---
+title: DocSearch program
+---
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][4] team know.
+
+For questions related to the DocSearch x Algolia Crawler, please see our [Crawler FAQ](/docs/crawler).
+
+## What do I need to install on my side?
+
+You just need to [implement DocSearch in your frontend](/docs/docsearch) with the credentials received by email when your application has been deployed.
+
+DocSearch leverages the [Algolia Crawler](https://www.algolia.com/products/search-and-discovery/crawler/), which offers a web [interface](https://dashboard.algolia.com/crawler) to create, monitor, edit, start your Crawlers. If you have any questions regarding it, please see our [Crawler FAQ](/docs/crawler).
+
+## How much does it cost?
+
+It's free!
+
+We know that paying for search infrastructure is a cost not all open source projects can afford. That's why we decided to keep DocSearch free for everyone. All we ask in exchange is that you keep the "Search by [Algolia][2]" logo displayed next to the search results.
+
+If this is not possible for you, you're free to [open your own Algolia account](https://www.algolia.com/pricing) and run [DocSearch on your own][3] without this limitation. In that case, though, depending on the size of your documentation, you might need a paid account (free accounts can hold as much as 10k records).
+
+## What data are you collecting?
+
+We save the data we extract from your website markup, which we put in a custom JSON format instead of HTML. This is the data we put in the Algolia DocSearch index. The selectors in your config define what data to scrape.
+
+As the website owner, we also give you access to your own Algolia application. This will let you see how your website is indexed in Algolia, detailed analytics about the anonymized searches in your website, team managements, and more!
+
+## Where is my data hosted?
+
+We host the DocSearch data on Algolia's servers, with replications around the globe. You can find more details about the actual [server specs here](https://www.algolia.com/doc/guides/infrastructure/servers/), and more complete information in our [privacy policy](https://www.algolia.com/policies/privacy).
+
+## How do I upgrade my DocSearch app?
+
+Depending on what you are looking for you have a few options!
+
+### Upgrade #1: I want a specific feature, like Rules, added to my existing DocSearch application
+
+[Reach out to us](https://algolia.com/support) and we may be able to help!
+
+### Upgrade #2: I want to remove the Algolia logo
+
+This would disqualify you from the free DocSearch program. We do offer an open-source
+[legacy version](https://docsearch.algolia.com/docs/legacy/run-your-own) of the DocSearch Crawler that you can use and
+host yourself or you can use our [API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript) but you will need to use a new Algolia application and pay for its usage.
+
+### Upgrade #3: Algolia is awesome, I want to use it for my whole site
+
+That's awesome! Please reach out to our [sales team](https://www.algolia.com/contactus/)
+who can help you figure out the right plan for you. Once you have your new application
+created you can simply copy and paste [your Crawler config](https://docsearch.algolia.com/docs/templates) into your new application's
+Crawler.
+
+## Can I use DocSearch on non-doc pages?
+
+The free DocSearch we provide will **only** crawl open-source projects documentation pages or technical blogs. To use it on other parts of your website, you'll need to create your own Algolia account and either:
+
+- Run the [DocSearch crawler][3] on your own
+- Use one of our other [framework integrations or API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript)
+
+## Can you index code samples?
+
+Yes, but we do not recommend it.
+
+Code samples are a great way for humans to understand how people use a specific method. It often requires boilerplate code though, repeated across examples, which adds noise to the results.
+
+## A documentation website I like does not use DocSearch. What can I do?
+
+We'd love to help!
+
+If one of your favorite tool documentation websites is missing DocSearch, we encourage you to file an issue in their repository explaining how DocSearch could help. Feel free to [let us know on Discord][1] as well and we'll provide all the help we can.
+
+## How did we build this website?
+
+We build this website with [Docusaurus v2](https://docusaurus.io/). We were helped by a great man who inspired us a lot, Endi. We want [to pay a tribute to this exceptional human being that will be always part of the DocSearch project](https://docusaurus.io/blog/2020/01/07/tribute-to-endi). Rest in peace mate!
+
+## Can I share the `apiKey` in my repo?
+
+The `apiKey` the DocSearch team provides is [a search-only key](https://www.algolia.com/doc/guides/security/api-keys/#search-only-api-key) and can be safely shared publicly. You can track it in your version control system (e.g. git). If you are running the scraper on your own, please make sure to create a search-only key and [do not share your Admin key](https://www.algolia.com/doc/guides/security/api-keys/#admin-api-key).
+
+## Why is the email API key different in the dashboard?
+
+Every Algolia app comes with a default "Search API Key" which can be seen in the dashboard. That key allow you to list indices, settings, and search on **every** index owned by your application. In the case of a DocSearch application, in your acceptance email we provide a search **ONLY** API key scoped to only your DocSearch index. If for any reason you need to recover the API key sent in the email, just connect with our [support](https://algolia.com/support) team.
+
+## How do I rotate my API keys?
+
+Please reach out to our [support](https://algolia.com/support) team.
+
+## Can I have multiple projects under the same Algolia application?
+
+We recommend having a single Algolia application per project. Please [apply](https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply) if you'd like to use DocSearch in an other project of yours.
+
+### Why?
+
+The information of the initially applied project is used everywhere when we deploy your app:
+
+- The scope of your API keys
+- The name of your Algolia application/Crawler
+- The indices we generate
+- The allowed domains of your Crawler
+
+This allows us to easily scope issues when reaching out for support.
+
+## Support
+
+:::caution
+
+Please make sure to **first read the documentation before reaching out**.
+
+Here are some links to help you:
+
+- [The Algolia Crawler documentation](https://www.algolia.com/doc/tools/crawler/getting-started/overview/)
+- [The Algolia Crawler FAQ](/docs/crawler)
+- [The DocSearch FAQ](/docs/docsearch-program)
+- [The Algolia documentation](https://www.algolia.com/doc/)
+
+You can also take a look at [the Algolia academy](https://academy.algolia.com/trainings) to understand more about Algolia.
+
+:::
+
+Please be informed that while Algolia does not provide support for DocSearch itself, we can support requests for the following products:
+
+- The Algolia Crawler, reach out [via the support page](https://algolia.com/support).
+- The Algolia Dashboard, reach out [via the support page](https://algolia.com/support).
+
+For any issue related to [the DocSearch UI library](https://github.com/algolia/docsearch), please open a [GitHub issue](https://github.com/algolia/docsearch/issues).
+
+[1]: https://alg.li/discord
+[2]: https://www.algolia.com/
+[3]: /docs/legacy/run-your-own
+[4]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/docsearch.mdx b/packages/website/versioned_docs/version-v4/docsearch.mdx
new file mode 100644
index 00000000..9c17704f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch.mdx
@@ -0,0 +1,418 @@
+---
+title: Getting Started with v4
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+DocSearch v4 provides a significant upgrade over previous versions, offering enhanced accessibility, responsiveness, and an improved search experience for your documentation. Built on [Algolia Autocomplete][1], DocSearch v4 ensures a seamless integration trusted by leading documentation sites worldwide.
+
+## Installation
+
+> Looking for the Composable API documentation? You can find it [here][17].
+
+DocSearch packages are available on the [npm registry][10].
+
+### Docusaurus users
+
+If your docs site is powered by Docusaurus, use [`@docsearch/docusaurus-adapter`](/docs/docusaurus-adapter) for the latest DocSearch features (including new Ask AI capabilities such as sidepanel support), while keeping `@docusaurus/preset-classic`.
+
+
+
+
+```bash
+yarn add @docsearch/js@4
+# or with npm
+npm install @docsearch/js@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+```bash
+yarn add @docsearch/react@4
+# or
+npm install @docsearch/react@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``:
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+
+### Optimize first query performance
+
+Enhance your users' first search experience by using `preconnect`, see [Performance optimization](#preconnect) below
+
+## Implementation
+
+
+
+
+DocSearch requires a dedicated container in your HTML
+
+```html
+
+```
+
+Initialize DocSearch by passing your container:
+
+```js app.js
+import docsearch from '@docsearch/js';
+
+import '@docsearch/css';
+
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+});
+```
+
+DocSearch generates an accessible, fully-functional search input for you automatically.
+
+
+
+
+
+Integrating DocSearch into your React app is straightforward:
+
+```jsx App.js
+import { DocSearch } from '@docsearch/react';
+
+import '@docsearch/css';
+
+function App() {
+ return (
+
+ );
+}
+
+export default App;
+```
+
+DocSearch generates a fully accessible search input out-of-the-box.
+
+
+
+
+
+### Quick Testing (without credentials)
+
+If you'd like to test DocSearch immediately without your own credentials, use our demo configuration:
+
+
+
+
+```js
+docsearch({
+ appId: 'PMZUYBQDAK',
+ apiKey: '24b09689d5b4223813d9b8e48563c8f6',
+ indexName: 'docsearch',
+ askAi: 'askAIDemo',
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+Or use our new dedicated [DocSearch Playground](https://community.algolia.com/docsearch-playground/)
+
+### Using DocSearch with Ask AI
+
+DocSearch v4 introduces support for Ask AI, Algolia's advanced, AI-powered search capability. Ask AI enhances the user experience by providing contextually relevant and intelligent responses directly from your documentation. You can also use the same `askAi` configuration object to route chat through Agent Studio.
+
+To enable Ask AI, you can add your Algolia Assistant ID as a string, or use an object for more advanced configuration (such as specifying a different index, credentials, search parameters, or enabling Agent Studio):
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+});
+```
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ indexName: 'YOUR_MARKDOWN_INDEX', // Optional: use a different index for Ask AI
+ apiKey: 'YOUR_SEARCH_API_KEY', // Optional: use a different API key for Ask AI
+ appId: 'YOUR_APP_ID', // Optional: use a different App ID for Ask AI
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'], // Optional: filter Ask AI context
+ },
+ suggestedQuestions: true // Optional: enable loading suggested questions on the Ask AI new conversation screen
+ },
+});
+```
+
+
+
+
+- Use the string form for a simple setup.
+- Use the object form to customize which index, credentials, or filters Ask AI uses.
+- The suggested questions feature is controlled on the [Dashboard](https://dashboard.algolia.com) in the Ask AI section.
+
+### Using Agent Studio with DocSearch
+
+To use [Algolia Agent Studio](https://www.algolia.com/doc/guides/algolia-ai/agent-studio) as the chat backend, set `agentStudio: true` inside the `askAi` object.
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+- `agentStudio` is configured inside `askAi`, not as a top-level DocSearch prop.
+- When `agentStudio: true`, `searchParameters` must be keyed by index name.
+- Agent Studio search parameters support `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+### Filtering search results
+
+#### Keyword search
+
+If your website uses [DocSearch meta tags][13] or if you've added [custom variables to your config][14], you'll be able to use the [`facetFilters`][16] option to scope your search results to a [`facet`][15]
+
+This is useful to limit the scope of the search to one language or one version.
+
+
+
+
+```js
+docsearch({
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+#### Ask AI
+
+Filtering also applies when using Ask AI. This is useful to limit the scope of the LLM's search to only relevant results.
+
+:::info
+We recommend using the `facetFilters` option when using Ask AI with multiple languages or any multi-faceted index.
+:::
+
+
+
+```js
+docsearch({
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+ },
+});
+```
+
+
+
+```jsx
+
+```
+
+
+
+
+:::tip
+You can use `facetFilters: ['type:content']` to ensure Ask AI only uses records where the `type` attribute is `content` (i.e., only records that actually have content). This is useful if your index contains records for navigation, metadata, or other non-content types.
+:::
+
+### Sending events
+
+You can send search events to your DocSearch index by passing in the `insights` parameter when creating your DocSearch instance.
+
+
+
+
+```diff
+docsearch({
+ // other options
++ insights: true,
+});
+```
+
+
+
+
+
+```diff
+
+```
+
+
+
+
+
+## Performance optimization
+
+### Preconnect
+
+Improve the loading speed of your initial search request by adding this snippet into your website's `` section:
+
+```html
+
+```
+
+This helps the browser establish a quick connection with Algolia, enhancing user experience, especially on mobile devices.
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/integrations
+[6]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[7]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[8]: https://codesandbox.io/s/docsearch-js-v3-playground-z9oxj
+[9]: https://codesandbox.io/s/docsearch-react-v3-playground-619yg
+[10]: https://www.npmjs.com/
+[11]: /docs/api#container
+[12]: /docs/api
+[13]: /docs/required-configuration#introduce-global-information-as-meta-tags
+[14]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: https://www.algolia.com/doc/guides/managing-results/refine-results/filtering/#facetfilters
+[17]: /docs/composable-api
diff --git a/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
new file mode 100644
index 00000000..4ae81493
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
@@ -0,0 +1,61 @@
+---
+title: Docusaurus Adapter (Recommended)
+---
+
+If you use Docusaurus, install and configure `@docsearch/docusaurus-adapter` to get the latest DocSearch features on your current Docusaurus version.
+
+## Why this adapter exists
+
+Docusaurus ships an excellent built-in Algolia integration (`@docusaurus/theme-search-algolia`), but Docusaurus (Meta-maintained) and DocSearch don't always release on the same cadence.
+
+The DocSearch adapter lets us ship new DocSearch features (including Ask AI sidepanel support) without forcing users to wait for a Docusaurus integration update.
+
+In practice, this means:
+
+- Faster access to new DocSearch capabilities.
+- Better compatibility for Ask AI + sidepanel features.
+- A dedicated search integration path maintained in the DocSearch project.
+
+## Install
+
+```bash
+yarn add @docsearch/docusaurus-adapter
+# or
+npm install @docsearch/docusaurus-adapter
+```
+
+## Configuration
+
+Keep `@docusaurus/preset-classic`, add the adapter plugin, and configure search under `themeConfig.docsearch` (preferred):
+
+```js title="docusaurus.config.mjs"
+export default {
+ plugins: ['@docsearch/docusaurus-adapter'],
+ themeConfig: {
+ docsearch: {
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+ askAi: {
+ assistantId: 'YOUR_ASSISTANT_ID',
+ sidePanel: true,
+ },
+ contextualSearch: true,
+ },
+ },
+};
+```
+
+## `docsearch` vs `algolia` keys
+
+- `themeConfig.docsearch` is the canonical key.
+- `themeConfig.algolia` is supported as a backward-compatible alias.
+- Do not define both keys at the same time.
+
+Using `themeConfig.docsearch` helps avoid built-in Docusaurus search-theme validation conflicts when you want newer DocSearch options like `askAi.sidePanel`.
+
+## Customizing Search UI (SearchBar/SearchPage)
+
+If you want to customize search behavior or UI, customize the adapter theme components (`@theme/SearchBar` and `@theme/SearchPage`) from the adapter integration path.
+
+This keeps your customization aligned with DocSearch feature updates and avoids coupling to the built-in Docusaurus Algolia theme implementation.
diff --git a/packages/website/versioned_docs/version-v4/examples.mdx b/packages/website/versioned_docs/version-v4/examples.mdx
new file mode 100644
index 00000000..6241cd50
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/examples.mdx
@@ -0,0 +1,428 @@
+---
+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.
diff --git a/packages/website/versioned_docs/version-v4/how-does-it-work.mdx b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
new file mode 100644
index 00000000..3cc42427
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
@@ -0,0 +1,51 @@
+---
+title: How does it work?
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+Getting up and ready with DocSearch is a straightforward process that requires three steps: you apply, we configure the crawler and the Algolia app for you, and you integrate our UI in your frontend. You only need to copy and paste a JavaScript snippet.
+
+
+
+## You apply
+
+The first thing you'll need to do is to apply for DocSearch by [filling out the form on this page][1] (double check first that [you qualify][2]). We are receiving a lot of requests, so this form makes sure we won't be forgetting anyone.
+
+We guarantee that we will answer every request, but as we receive a lot of applications, please give us a couple of days to get back to you :)
+
+## We create your Algolia application and a dedicated crawler
+
+Once we receive [your application][1], we'll have a look at your website, create an Algolia application and a dedicated [crawler][5] for it. Your crawler comes with [a configuration file][6] which defines which URLs we should crawl or ignore, as well as the specific CSS selectors to use for selecting headers, subheaders, etc.
+
+This step still requires some manual work and human brain, but thanks to the +4,000 configs we already created, we're able to automate most of it. Once this creation finishes, we'll run a first indexing of your website and have it run automatically at a random time of the week.
+
+**With the Crawler, comes [a dedicated interface][8] for you to:**
+
+- Start, schedule and monitor your crawls
+- Edit and test your config file directly with [DocSearch v3][7]
+
+**With the Algolia application comes access to the dashboard for you to:**
+
+- Browse your index and see how your content is indexed
+- Various analytics to understand how your search performs and ensure that your users are able to find what theyβre searching for
+- Trials for other Algolia features
+- Team management
+
+## You update your website
+
+We'll then get back to you with the JavaScript snippet you'll need to add to your website. This will bind your [DocSearch component][7] to display results from your Algolia index on each keystroke in a pop-up modal.
+
+Now that DocSearch is set, you don't have anything else to do. We'll keep crawling your website and update your search results automatically. All we ask is that you keep the "Search by Algolia" logo next to your search results.
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: /docs/who-can-apply
+[3]: https://github.com/algolia/docsearch-configs/tree/master/configs
+[4]: /docs/styling
+[5]: https://www.algolia.com/products/search-and-discovery/crawler/
+[6]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[7]: /docs/v3/docsearch
+[8]: https://crawler.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/integrations.md b/packages/website/versioned_docs/version-v4/integrations.md
new file mode 100644
index 00000000..59806313
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/integrations.md
@@ -0,0 +1,45 @@
+---
+title: Supported Integrations
+---
+
+We worked with **documentation website generators** to have DocSearch directly embedded as a first class citizen in the websites they produce.
+
+## Our great integrations
+
+So, if you're using one of the following tools, check out their documentation to see how to enable DocSearch on your website:
+
+- [Docusaurus v1][1] - [How to enable search][2]
+- [Docusaurus v2 & v3][3] - [DocSearch adapter (recommended)][23] / [Using Algolia DocSearch][4]
+- [VuePress][5] - [Algolia Search][6]
+- [VitePress][21] - [Search][22]
+- [Starlight][7] - [Algolia Search][8]
+- [LaRecipe][9] - [Algolia Search][10]
+- [Orchid][11] - [Algolia Search][12]
+- [Smooth DOC][13] - [DocSearch][14]
+- [Docsy][15] - [Configure Algolia DocSearch][16]
+- [Lotus Docs][19] - [Enabling the DocSearch Plugin][20]
+- [Sphinx](https://www.sphinx-doc.org/en/master/) - [Algolia DocSearch for Sphinx](https://sphinx-docsearch.readthedocs.io/)
+
+If you're maintaining a similar tool and want us to add you to the list, [feel free to make a pull request](https://github.com/algolia/docsearch/edit/main/packages/website/docs/integrations.md) and [contribute to Code Exchange](https://www.algolia.com/developers/code-exchange/contribute/). We're happy to help.
+
+[1]: https://v1.docusaurus.io/
+[2]: https://v1.docusaurus.io/docs/en/search
+[3]: https://docusaurus.io/
+[4]: https://docusaurus.io/docs/search#using-algolia-docsearch
+[5]: https://vuepress.vuejs.org/
+[6]: https://vuepress.vuejs.org/theme/default-theme-config.html#algolia-search
+[7]: https://starlight.astro.build/
+[8]: https://starlight.astro.build/guides/site-search/#algolia-docsearch
+[9]: https://larecipe.saleem.dev/docs/2.2/overview
+[10]: https://larecipe.saleem.dev/docs/2.2/search#available-engines
+[11]: https://orchid.run
+[12]: https://orchid.run/plugins/orchidsearch#algolia-docsearch
+[13]: https://next-smooth-doc.vercel.app/
+[14]: https://next-smooth-doc.vercel.app/docs/docsearch/
+[15]: https://www.docsy.dev/
+[16]: https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch
+[19]: https://lotusdocs.dev/docs/
+[20]: https://lotusdocs.dev/docs/guides/features/docsearch/#enabling-the-docsearch-plugin
+[21]: https://vitepress.dev/
+[22]: https://vitepress.dev/reference/default-theme-search#algolia-search
+[23]: /docs/docusaurus-adapter
diff --git a/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
new file mode 100644
index 00000000..3dbf5caa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
@@ -0,0 +1,67 @@
+---
+title: "[Pre-v4] Manage your crawls"
+---
+
+:::caution
+This UI is deprecated and no longer maintained. For the latest instructions, please use the new documentation: [Crawler Configuration Visual UI](./crawler-configuration-visual). You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+:::
+
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+DocSearch comes with the [Algolia Crawler web interface](https://crawler.algolia.com/) that allows you to configure how and when your Algolia index will be populated.
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+The live editor allows you to update your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## Search preview
+
+From the [`editor`](#update-your-config), you have access to a `Search preview` tab to browse search results with [`DocSearch v3`](/docs/v3/docsearch).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to [debug selectors](https://www.algolia.com/doc/tools/crawler/getting-started/crawler-configuration/#debugging-selectors) or how we crawl your website.
+
+
+
+
diff --git a/packages/website/versioned_docs/version-v4/mcp/installation.mdx b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
new file mode 100644
index 00000000..300b20c2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
@@ -0,0 +1,32 @@
+---
+title: Install DocSearch MCP
+sidebar_label: Installation
+---
+
+import MCPInstall from '@site/src/components/mcp/MCPInstall';
+
+DocSearch MCP is a remote MCP server. Point any MCP-compatible client at this endpoint β no authentication required:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+The fastest path is the **DocSearch CLI** β one command that configures your client for you. Prefer to set things up yourself? Install it as a **plugin** (ships the MCP server plus client guidance like rules, skills, and commands) or **manually** (just the MCP server config). Pick your client below.
+
+
+
+## Verify the install
+
+Ask your MCP client a public documentation question, for example:
+
+```text
+Use DocSearch MCP to find the current Next.js middleware matcher docs.
+```
+
+The client should call the DocSearch tools and answer with content from the matching documentation, ideally with source links.
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/overview.mdx b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
new file mode 100644
index 00000000..1d3aeae5
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: DocSearch MCP
+sidebar_label: Overview
+---
+
+DocSearch MCP lets AI clients search current public developer documentation from the DocSearch corpus.
+
+Use it when you want an assistant to answer questions from public docs instead of relying only on model training data. The public endpoint does not require authentication:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+## What it does
+
+DocSearch MCP exposes documentation search through the [Model Context Protocol](https://modelcontextprotocol.io/). MCP-compatible clients connect to the endpoint and call DocSearch tools while answering your questions.
+
+The endpoint is focused on public developer documentation. You do not need an Algolia application ID, search API key, or DocSearch application to use it.
+
+## How it works
+
+Most lookups are a single call: name the product and ask your question, and DocSearch finds the right documentation set and returns the matching content together.
+
+When a question spans several products, or you want to inspect and hand-pick documentation sets first, there is a two-step flow: resolve the documentation sets, then query the ones you choose.
+
+## Available tools
+
+### `algolia_docsearch_search_docs`
+
+The one-shot tool, and the right default for most lookups. Give it a `library` (the product, SDK, or platform) and a `query` (your question); it resolves the best matching documentation set and returns ranked content in a single call. If the library is ambiguous, it returns candidate documentation sets to choose from instead.
+
+### `algolia_docsearch_resolve_docset`
+
+Step 1 of the manual flow. Finds the documentation sets that best match a product, library, or platform and returns candidates β each with a `docset_id`, title, description, and ranking signals to help pick the best match.
+
+### `algolia_docsearch_query_docs`
+
+Step 2 of the manual flow. Retrieves documentation content for one or more `docset_id`s returned by `algolia_docsearch_resolve_docset`. Pass several at once when a question spans multiple products.
+
+## Next steps
+
+- [Install DocSearch MCP](/docs/mcp/installation)
+- [Use DocSearch MCP](/docs/mcp/usage)
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/usage.mdx b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
new file mode 100644
index 00000000..fb7b8a9b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
@@ -0,0 +1,113 @@
+---
+title: Use DocSearch MCP
+sidebar_label: Usage
+---
+
+DocSearch MCP works best when your client knows to search public documentation before answering library, framework, API, or SDK questions.
+
+## Ask documentation questions
+
+After installation, ask your client about public developer docs in natural language:
+
+```text
+How do I configure middleware matchers in Next.js?
+```
+
+```text
+Show me the current Stripe webhook signature verification docs.
+```
+
+```text
+What is the current setup for Algolia InstantSearch React?
+```
+
+If your client does not automatically use MCP tools, mention DocSearch MCP explicitly:
+
+```text
+Use DocSearch MCP to look up React Server Components data fetching.
+```
+
+## Use the Claude Code command
+
+The Claude Code plugin includes a manual command:
+
+```text
+/algolia-docsearch:docs [topic]
+```
+
+Examples:
+
+```text
+/algolia-docsearch:docs Next.js middleware matcher
+/algolia-docsearch:docs Stripe webhook signature verification
+/algolia-docsearch:docs Algolia InstantSearch React configure search client
+```
+
+## Tool flow
+
+DocSearch MCP exposes three tools. Most of the time the client only needs the one-shot tool; the two-step flow is for multi-product questions or when you want to hand-pick documentation sets.
+
+You can ask in natural language β full sentences and questions work well. For the one-shot tool, keep `library` to the product name and put the actual question in `query`.
+
+### One-shot: `algolia_docsearch_search_docs`
+
+The client names the product and asks the question in a single call:
+
+```json
+{
+ "library": "Next.js",
+ "query": "how do middleware matchers work"
+}
+```
+
+It returns ranked documentation content for the best matching set. If the library is ambiguous, it returns candidate documentation sets instead so the client can pick one and fall back to `algolia_docsearch_query_docs`.
+
+### Two-step: resolve, then query
+
+For questions that span several products, or when the client wants to choose documentation sets explicitly:
+
+1. `algolia_docsearch_resolve_docset` finds documentation sets:
+
+```json
+{
+ "query": "Next.js app router"
+}
+```
+
+It returns candidates, each with a `docset_id`.
+
+2. `algolia_docsearch_query_docs` retrieves content for the chosen `docset_id`(s):
+
+```json
+{
+ "query": "middleware matcher config",
+ "docsetIds": ["nextjs"]
+}
+```
+
+Pass multiple `docsetIds` when a question spans more than one product.
+
+## Tips
+
+- Be specific about the product and topic you want.
+- Include a version when it matters.
+- Ask for source URLs if you want the client to show where the answer came from.
+- If the first result is too broad, ask for a narrower topic.
+
+## Troubleshooting
+
+### The client does not call DocSearch MCP
+
+Make sure the MCP server is enabled in your client and named `algolia-docsearch`. If you installed the plugin, check that the plugin is enabled too.
+
+### The result is about the wrong product
+
+Ask again with the official product name. For the one-shot tool, set `library` to the vendor's product name (for example, `Algolia InstantSearch` rather than `search`).
+
+### The client cannot connect
+
+Confirm that your client supports remote HTTP MCP servers and that the configured URL is:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
diff --git a/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
new file mode 100644
index 00000000..e8edf61e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
@@ -0,0 +1,87 @@
+---
+title: Migrating from the legacy scraper
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+With the new version of the [DocSearch UI][1], we wanted to go further and provide better tooling for you to create and maintain your config file, and some extra Algolia features that you all have been requesting for a long time!
+
+## What's new?
+
+### Scraper
+
+The DocSearch infrastructure now leverages the [Algolia Crawler][2]. We've teamed up with our friends and created a new [DocSearch helper][4], that extracts records as we were previously doing with our beloved [DocSearch scraper][3]!
+
+The best part is that you no longer need to install any tooling on your side if you want to maintain or update your index!
+
+We now provide a web interface **[legacy][7]** or **[new](https://dashboard.algolia.com/crawler)** that will allow you to:
+
+- Start, schedule and monitor your crawls
+- Edit your config file from our live editor
+- Test your results directly with [DocSearch v3][1] or [DocSearch v4][32]
+
+### Algolia application and credentials
+
+We've received a lot of requests asking for:
+
+- A way to manage team members
+- Browse and see how Algolia records are indexed
+- See and subscribe to other Algolia features
+
+They are now all available, in **your own Algolia application**, for free :D
+
+## FAQ
+
+You can find answers related to the DocSearch migration in our [Crawler FAQ page](/docs/crawler).
+
+### Useful links
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+## Config file key mapping
+
+Below are the keys that can be found in the [`legacy` DocSearch configs][14] and their translation to an [Algolia Crawler config][16]. For more detailed information on the Algolia Crawler, see [the official documentation][15].
+
+| `legacy` | `current` | description |
+| --- | --- | --- |
+| `start_urls` | [`startUrls`][20] | Now accepts URLs only, see [`helpers.docsearch`][30] to handle custom variables |
+| `page_rank` | [`pageRank`][31] | Can be added to the `recordProps` in [`helpers.docsearch`][30], should be passed as a **string** |
+| `js_render` | [`renderJavaScript`][21] | Unchanged |
+| `js_wait` | [`renderJavascript.waitTime`][22] | See documentation of [`renderJavaScript`][21] |
+| `index_name` | **removed**, see [`actions`][23] | Handled directly in the [`actions`][23] |
+| `sitemap_urls` | [`sitemaps`][24] | Unchanged |
+| `stop_urls` | [`exclusionPatterns`][25] | Supports [`micromatch`][27] |
+| `selectors_exclude` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `custom_settings` | [`initialIndexSettings`][26] | Unchanged |
+| `scrape_start_urls` | **removed** | Can be handled with [`exclusionPatterns`][25] |
+| `strip_chars` | **removed** | `#` are removed automatically from anchor links, edge cases should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `conversation_id` | **removed** | Not needed anymore |
+| `nb_hits` | **removed** | Not needed anymore |
+| `sitemap_alternate_links` | **removed** | Not needed anymore |
+| `stop_content` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+
+[1]: /docs/v3/docsearch
+[2]: https://www.algolia.com/products/search-and-discovery/crawler/
+[3]: /docs/legacy/run-your-own
+[4]: /docs/record-extractor
+[7]: https://crawler.algolia.com/
+[14]: /docs/legacy/config-file
+[15]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[16]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[20]: https://www.algolia.com/doc/tools/crawler/apis/configuration/start-urls/
+[21]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[22]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/#parameter-param-waittime
+[23]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-indexname
+[24]: https://www.algolia.com/doc/tools/crawler/apis/configuration/sitemaps/
+[25]: https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/
+[26]: https://www.algolia.com/doc/tools/crawler/apis/configuration/initial-index-settings/
+[27]: https://github.com/micromatch/micromatch
+[28]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[29]: /docs/record-extractor
+[30]: /docs/record-extractor#introduction
+[31]: /docs/record-extractor#pagerank
+[32]: /docs/docsearch
diff --git a/packages/website/docs/migrating-from-v3.md b/packages/website/versioned_docs/version-v4/migrating-from-v3.md
similarity index 100%
rename from packages/website/docs/migrating-from-v3.md
rename to packages/website/versioned_docs/version-v4/migrating-from-v3.md
diff --git a/packages/website/versioned_docs/version-v4/record-extractor.md b/packages/website/versioned_docs/version-v4/record-extractor.md
new file mode 100644
index 00000000..64c34ca7
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/record-extractor.md
@@ -0,0 +1,345 @@
+---
+title: Record Extractor
+---
+
+## Introduction
+
+:::info
+
+This documentation will only contain information regarding the **helpers.docsearch** method, see **[Algolia Crawler Documentation][7]** for more information on the **[Algolia Crawler][8]**.
+
+:::
+
+Pages are extracted by a [`recordExtractor`][9]. These extractors are assigned to [`actions`][12] via the [`recordExtractor`][9] parameter. This parameter links to a function that returns the data you want to index, organized in an array of JSON objects.
+
+_The helpers are a collection of functions to help you extract content and generate Algolia records._
+
+### Useful links
+
+- [Extracting records with the Algolia Crawler][11]
+- [`recordExtractor` parameters][10]
+
+## Usage
+
+The most common way to use the DocSearch helper, is to return its result to the [`recordExtractor`][9] function.
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Manipulate the DOM with Cheerio
+
+The [`Cheerio instance ($)`](https://cheerio.js.org/) allows you to manipulate the DOM:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ $(".my-warning-message").remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Provide fallback selectors
+
+Fallback selectors can be useful when retrieving content that might not exist in some pages:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ // `.exists h1` will be selected if `.exists-probably h1` does not exists.
+ lvl0: {
+ selectors: [".exists-probably h1", ".exists h1"],
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ // `.exists p, .exists li` will be selected.
+ content: [
+ ".does-not-exists p, .does-not-exists li",
+ ".exists p, .exists li",
+ ],
+ },
+ });
+},
+```
+
+### Provide raw text (`defaultValue`)
+
+_Only the `lvl0` and [custom variables][13] selectors support this option_
+
+You might want to structure your search results differently than your website, or provide a `defaultValue` to a potentially non-existent selector:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably h1",
+ defaultValue: "myRawTextIfDoesNotExists",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably .language",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ },
+ });
+},
+```
+
+### Indexing content for faceting
+
+_These selectors also support [`defaultValue`](#provide-raw-text-defaultvalue) and [fallback selectors](#provide-fallback-selectors)_
+
+You might want to index content that will be used as filters in your frontend (e.g. `version` or `lang`), you can define any custom variable to the `recordProps` object to add them to your Algolia records:
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ foo: ".bar",
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".does-not-exists",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ version: {
+ // You can send raw values without `selectors`
+ defaultValue: ["latest", "stable"],
+ },
+ },
+ });
+},
+```
+
+The following `version`, `lang` and `foo` attributes will be available in your records:
+
+```json
+foo: "valueFromBarSelector",
+language: ["en", "en-US"],
+version: ["latest", "stable"]
+```
+
+You can now use them to [filter your search in the frontend][16]
+
+### Boost search results with `pageRank`
+
+This parameter allows you to boost records using a custom ranking attribute built from the current `pathsToMatch`. Pages with highest [`pageRank`](#pagerank) will be returned before pages with a lower [`pageRank`](#pagerank). The default value is 0 and you can pass any numeric value **as a string**, including negative values.
+
+Search results are sorted by weight (desc), so you can have both boosted and non boosted results. The weight of each result will be computed for a given query based on multiple factors: match level, position, etc. and the pageRank value will be added to this final weight. The pageRank on its own may not be enough to influence the results of your query depending on how your [overall ranking is set up](https://www.algolia.com/doc/guides/managing-results/relevance-overview/in-depth/ranking-criteria/). If changing the pageRank value doesn't influence your search results enough, even with large values, move weight.pageRank higher in the Ranking and Sorting page for your index.
+
+You can view the computed weight directly from the Algolia dashboard (dashboard.algolia.com->search->perform a search->mouse hover over the "ranking criteria" icon bottom right of each record). That will give you an idea of what pageRank value is acceptable for your case.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers, url }) => {
+ const isDocPage = /\/[\w-]+\/docs\//.test(url.pathname);
+ const isBlogPage = /\/[\w-]+\/blog\//.test(url.pathname);
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ pageRank: isDocPage ? "-2000" : isBlogPage ? "-1000" : "0",
+ },
+ });
+ },
+},
+```
+
+### Reduce the number of records
+
+If you encounter the `Extractors returned too many records` error when your page outputs more than 750 records, the [`aggregateContent`](#aggregatecontent) option helps you reduce the number of records at the `content` level of the extractor.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ aggregateContent: true,
+ });
+ },
+},
+```
+
+### Reduce the record size
+
+If you encounter the `Records extracted are too big` error when crawling your website, it is usually because there is too much information in your records, or because your page is too large. The [`recordVersion`](#recordversion) option helps you reduce the records size by removing informations that are only used with [DocSearch v2](/docs/legacy/dropdown).
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ recordVersion: "v3",
+ });
+ },
+},
+```
+
+## `recordProps` API Reference
+
+### `lvl0`
+
+> `type: Lvl0` | **required**
+
+```ts
+type Lvl0 = {
+ selectors: string | string[];
+ defaultValue?: string;
+};
+```
+
+### `lvl1`, `content`
+
+> `type: string | string[]` | **required**
+
+### `lvl2`, `lvl3`, `lvl4`, `lvl5`, `lvl6`
+
+> `type: string | string[]` | **optional**
+
+### `pageRank`
+
+> `type: number` | **optional**
+
+See the [live example](#boost-search-results-with-pagerank)
+
+### Custom variables
+
+> `type: string | string[] | CustomVariable` | **optional**
+
+```ts
+type CustomVariable =
+ | {
+ defaultValue: string | string[];
+ }
+ | {
+ selectors: string | string[];
+ defaultValue?: string | string[];
+ };
+```
+
+Custom variables are used to [`filter your search`](/docs/v3/docsearch#filtering-your-search), you can define them in the [`recordProps`](#indexing-content-for-faceting)
+
+## `helpers.docsearch` API Reference
+
+### `aggregateContent`
+
+> `type: boolean` | default: `true` | **optional**
+
+[This option](#reduce-the-number-of-records) groups the Algolia records created at the `content` level of the selector into a single record for its matching heading.
+
+### `recordVersion`
+
+> `type: 'v3' | 'v2'` | default: `v2` | **optional**
+
+This option removes content from the Algolia records that are only used for [DocSearch v2](/docs/legacy/dropdown). If you are using [the latest version of DocSearch](/docs/v3/docsearch), you can [set it to `v3`](#reduce-the-record-size).
+
+### `indexHeadings`
+
+> `type: boolean | { from: number, to: number }` | default: `true` | **optional**
+
+This option tells the crawler if the `headings` (`lvlX`) should be indexed.
+
+- When `false`, only records for the `content` level will be created.
+- When `from, to` is provided, only records for the `lvlX` to `lvlY` will be created.
+
+[1]: /docs/v3/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/migrating-from-legacy
+[6]: /docs/legacy/run-your-own
+[7]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[8]: https://www.algolia.com/products/search-and-discovery/crawler/
+[9]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[10]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor-2
+[11]: https://www.algolia.com/doc/tools/crawler/guides/extracting-data/#extracting-records
+[12]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/
+[13]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: /docs/v3/docsearch/#filtering-your-search
diff --git a/packages/website/versioned_docs/version-v4/required-configuration.mdx b/packages/website/versioned_docs/version-v4/required-configuration.mdx
new file mode 100644
index 00000000..9b33aed2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/required-configuration.mdx
@@ -0,0 +1,189 @@
+---
+title: Required configuration
+---
+
+This section gives you the best practices to optimize our crawl. Adopting the following specification is required to let our crawler build the best experience from your website. You will need to update your website and follow these rules.
+
+:::info
+
+If your website is generated, thanks to one of [our supported tools][1], you do not need to change your website as it is already compliant with our requirements.
+
+:::
+
+## The generic configuration example
+
+You can find the default DocSearch config template below and tweak it with some examples from our [`complex extractors` section][12].
+
+If you are using one of [our integrations][13], please see [the templates page][11].
+
+
+docsearch-default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ startUrls: ['https://YOUR_START_URL.io/'],
+ sitemaps: ['https://YOUR_START_URL.io/sitemap.xml'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_START_URL.io/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+### Overview of a clear layout
+
+A website implementing these best practices will look simple and clear, as shown below:
+
+
+
+The main blue element will be your `.DocSearch-content` container. More details in the following guidelines.
+
+### Use the right classes as [`recordProps`][2]
+
+You can add some specific static classes to help us find your content role. These classes can not involve any style changes. These dedicated classes will help us to create a great learn-as-you-type experience from your documentation.
+
+- Add a static class `DocSearch-content` to the main container of your textual content. Most of the time, this tag is a `` or an `` HTML element.
+
+- Every searchable `lvl` element outside this main documentation container (for instance in a sidebar) must be a `global` selector. They will be globally picked up and injected to every record built from your page. Be careful, the level value matters and every matching element must have an increasing level along the HTML flow. A level `X` (for `lvlX`) should appear after a level `Y` while `X > Y`.
+
+- `lvlX` selectors should use the standard title tags like `h1`, `h2`, `h3`, etc. You can also use static classes. Set a unique `id` or `name` attribute to these elements as detailed below.
+
+- Every DOM element matching the `lvlX` selectors must have a unique `id` or `name` attribute. This will help the redirection to directly scroll down to the exact place of the matching elements. These attributes define the right anchor to use.
+
+- Every textual element (recordProps `content`) must be wrapped in a `` or `
` tag. This content must be atomic and split into small entities. Be careful to never nest one matching element into another one as it will create duplicates.
+
+- Stay consistent and do not forget that we need to have some consistency along the HTML flow.
+
+## Introduce global information as meta tags
+
+Our crawler automatically extracts information from our DocSearch specific meta tags:
+
+```html
+
+
+```
+
+The crawl adds the `content` value of these `meta` tags to all records extracted from the page. The meta tags `name` must follow the `docsearch:$NAME` pattern. `$NAME` is the name of the attribute set to all records.
+
+The `docsearch:version` meta tag can be a set [of comma-separated tokens][5], each of which is a version relevant to the page. These tokens must be compliant with [the SemVer specification][6] or only contain alphanumeric characters (e.g. `latest`, `next`, etc.). As facet filters, these version tokens are case-insensitive.
+
+For example, all records extracted from a page with the following meta tag:
+
+```html
+
+```
+
+The `version` attribute of these records will be :
+
+```json
+version:["2.0.0-alpha.62", "latest"]
+```
+
+You can then [transform these attributes as `facetFilters`][3] to [filter over them from the UI][10].
+
+## Nice to have
+
+- Your website should have [an updated sitemap][7]. This is key to let our crawler know what should be updated. Do not worry, we will still crawl your website and discover embedded hyperlinks to find your great content.
+
+- Every page needs to have their full context available. Using global elements might help (see above).
+
+- Make sure your documentation content is also available without JavaScript rendering on the client-side. If you absolutely need JavaScript turned on, you need to [set `renderJavaScript: true` in your configuration][8].
+
+Any questions? Connect with us on [Discord][14] or [support][9].
+
+[1]: /docs/integrations
+[2]: record-extractor#recordprops-api-reference
+[3]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[5]: https://html.spec.whatwg.org/dev/common-microsyntaxes.html#comma-separated-tokens
+[6]: https://semver.org/
+[7]: https://www.sitemaps.org/
+[8]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[9]: https://support.algolia.com/
+[10]: /docs/v3/docsearch#filtering-your-search
+[11]: /docs/templates
+[12]: /docs/record-extractor#introduction
+[13]: /docs/integrations
+[14]: https://alg.li/discord
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
new file mode 100644
index 00000000..b22ca01f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
@@ -0,0 +1,144 @@
+---
+title: Advanced use cases
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+This guide will cover some advanced implementations/use cases for the Sidepanel. The examples below assume you're using the Sidepanel React package,
+available from `@docsearch/sidepanel`. The `@docsearch/sidepanel` package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Complex implementation
+
+Below is an example of a more complex implementation with `searchParameters`, a different `variant`, and some translations.
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+function App() {
+ return (
+
+
+
+
+ );
+}
+```
+
+## Dynamic importing
+
+Sidepanel is built in a way that allows for dynamic importing of its components to help reduce bundle size. Below is a brief example of how to do so:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton } from '@docsearch/sidepanel/button';
+import type { Sidepanel as SidepanelType } from '@docsearch/sidepanel/sidepanel';
+import { useState } from 'react';
+
+let Sidepanel: typeof SidepanelType | null = null;
+
+async function importSidepanelIfNeeded() {
+ if (Sidepanel) {
+ return;
+ }
+
+ const { Sidepanel: Panel } = await import('@docsearch/sidepanel/sidepanel');
+
+ Sidepanel = Panel;
+}
+
+export default function DynamicSidepanel() {
+ const [sidepanelLoaded, setSidepanelLoaded] = useState(false);
+
+ const loadSidepanel = () => {
+ importSidepanelIfNeeded().then(() => {
+ setSidepanelLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {sidepanelLoaded && Sidepanel && (
+
+ )}
+
+ );
+}
+```
+
+## Hybrid Mode
+
+Hybrid Mode allows you to combine the Sidepanel and the original DocSearch Modal in one integrated experience.
+
+You can trigger the Modal for search and the Sidepanel for AI-powered assistance.
+
+Learn more in the [Hybrid Mode guide][1].
+
+[1]: /docs/sidepanel/hybrid
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
new file mode 100644
index 00000000..6e3a1b5e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
@@ -0,0 +1,186 @@
+---
+title: Sidepanel API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `assistantId`
+
+> `type: string` | **required**
+
+The ID for which Ask AI assistant to use.
+
+## `indexName`
+
+> `type: string` | **required**
+
+The name of the index to be used with the Ask AI service.
+
+## `agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `agentStudio` is true, the Ask AI chat will use Algolia's [Agent Studio][2] as the chat backend instead of the Ask AI backend. More can be learned about setting up Agent Studio on their dedicated [documentation page][3].
+
+## `searchParameters`
+
+> `type: AskAiSearchParameters | Record>` | **optional**
+
+Additional search parameters used to scope Ask AI or Agent Studio retrieval.
+
+- When `agentStudio` is omitted or `false`, pass a flat object such as `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- When `agentStudio` is `true`, `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+```tsx
+
+```
+
+```tsx
+
+```
+
+## `variant`
+
+> `type: 'floating' | 'inline'` | default: `'floating'` | **optional**
+
+Variant of the Sidepanel positioning.
+
+- `inline` pushes page content when opened.
+- `floating` is positioned above all other content on the page.
+
+## `side`
+
+> `type: 'right' | 'left'` | default: `'right'` | **optional**
+
+The side of the page which the panel will originate from.
+
+## `width`
+
+> `type: number | string` | default: `'360px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its default state.
+
+## `expandedWidth`
+
+> `type: number | string` | default: `'580px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its expanded state.
+
+## `suggestedQuestions`
+
+> `type: boolean` | default: `false` | **optional**
+
+Enables displaying suggested questions on new conversation screen.
+
+More information on setting up Suggested Questions can be found on [Algolia Docs][1]
+
+## `keyboardShortcuts`
+
+> `type: { 'Ctrl/Cmd+I': boolean }` | **optional**
+
+Configuration for keyboard shortcuts. Allows enabling/disabling specific shortcuts.
+
+### Default behavior
+
+- `Ctrl/Cmd+I` - Opens and closes the Sidepanel
+
+### Interface
+
+```ts
+interface SidepanelShortcuts {
+ 'Ctrl/Cmd+I'?: boolean; // default: true
+}
+```
+
+## `theme`
+
+> `type: 'light' | 'dark'` | default: `'light'` | **optional**
+
+## `portalContainer` (React only)
+
+> `type: Element | DocumentFragment` | default: `document.body` | **optional**
+
+The container element where the panel should be portaled to. Use this when you need the Sidepanel to render in a custom DOM node.
+
+:::warning
+This prop only exists in the React based versions of Sidepanel. If you are using the `@docsearch/sidepanel-js` package, use the `container` option instead.
+:::
+
+
+
+ ```tsx
+ // assume you have a dedicated DOM node in your HTML
+
+
+ const portalEl = document.getElementById('sidepanel-root');
+
+
+ ```
+
+
+
+ ```js
+ sidepanel({
+ // The element that will contain the Sidepanel Button and Sidepanel
+ container: '#sidepanel-root',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+ })
+ ```
+
+
+
+[1]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/suggested-questions
+[2]: https://www.algolia.com/products/ai/agent-studio
+[3]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
new file mode 100644
index 00000000..13d31f95
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
@@ -0,0 +1,136 @@
+---
+title: Get started with Sidepanel
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Sidepanel is available from version `>= 4.4`
+:::
+
+## Introduction
+
+DocSearch Sidepanel is a new experience separate from the DocSearch Modal experience. Sidepanel is built entirely for usage with Ask AI and can be used completely standalone or in [Hybrid mode][1] with the Modal.
+
+## Installation
+
+To get started with Sidepanel, first you will need to install the needed packages:
+
+
+
+
+```bash
+npm install @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+npm install @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+yarn add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+pnpm add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+bun add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+### Without package manager
+
+```html
+
+
+
+
+```
+
+## Implementation
+
+The simplest implementation of Sidepanel would be as follows:
+
+
+
+```tsx
+import { DocSearchSidepanel } from '@docsearch/react/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function App() {
+ return (
+
+ );
+}
+```
+
+
+
+You will need a `container` DOM node to render the Sidepanel into:
+
+```html
+
+```
+
+```js
+import sidepanel from '@docsearch/sidepanel-js';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+sidepanel({
+ container: '#docsearch-sidepanel',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+});
+```
+
+
+
+This is just the most basic form of implementation. To learn about other implementation methods, you can read our [Advanced use cases][2].
+
+To learn more about the different configuration options for Sidepanel, you can read our [Sidepanel API References][3].
+
+[1]: /docs/sidepanel/hybrid
+[2]: /docs/sidepanel/advanced-use-cases
+[3]: /docs/sidepanel/api-reference
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
new file mode 100644
index 00000000..0be6f2cb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
@@ -0,0 +1,100 @@
+---
+title: Hybrid Mode
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Currently Hybrid Mode is only available when using the React usage approach. Hybrid Mode is not available in the JavaScript-only (vanilla) integration.
+:::
+
+## Introduction
+
+Sidepanel can run alongside the DocSearch Modal through what we call "Hybrid Mode." When a user initiates an Ask AI action from within
+the DocSearch Modal, such as submitting a prompt or selecting an AI-related suggestion, the interface automatically transitions into the Sidepanel for
+the continuation of the conversation.
+
+## Set up
+
+To set up the Hybrid Mode experience, you will need the following:
+
+- [DocSearch Modal][1] packages installed
+- Sidepanel Component package installed
+
+The Sidepanel Component package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+Once everything is installed, you can set up Hybrid Mode as such:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function HybridMode() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+There is no manual opt-in for Hybrid Mode to work. When both the Modal and Sidepanel are rendered inside the same `` context, Hybrid Mode is enabled automatically. No additional configuration is required.
+
+[1]: /docs/docsearch#installation
diff --git a/packages/website/versioned_docs/version-v4/styling.md b/packages/website/versioned_docs/version-v4/styling.md
new file mode 100644
index 00000000..554fe0c0
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/styling.md
@@ -0,0 +1,48 @@
+---
+title: Styling
+---
+
+:::info
+
+The following content is for **[DocSearch v4][2]**. If you are using **[DocSearch v3][3]**, see the **[legacy][4]** documentation.
+
+:::
+
+## Introduction
+
+DocSearch v4 comes with a theme package called `@docsearch/css`, which offers a sleek out of the box theme!
+
+:::note
+
+This package is a dependency of [`@docsearch/js`][1] and [`@docsearch/react`][1], you don't need to install it if you are using a package manager!
+
+:::
+
+## Installation
+
+```bash
+yarn add @docsearch/css@4
+# or
+npm install @docsearch/css@4
+```
+
+If you donβt want to use a package manager, you can use a standalone endpoint:
+
+```html
+
+```
+
+## Files
+
+```
+@docsearch/css
+βββ dist/style.css # all styles
+βββ dist/_variables.css # CSS variables
+βββ dist/button.css # CSS for the button
+βββ dist/modal.css # CSS for the modal
+```
+
+[1]: /docs/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/v3/docsearch
diff --git a/packages/website/versioned_docs/version-v4/templates.mdx b/packages/website/versioned_docs/version-v4/templates.mdx
new file mode 100644
index 00000000..b14126d9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/templates.mdx
@@ -0,0 +1,1069 @@
+---
+title: Config Templates
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+To help you create the best search experience for your users, we provide out-of-the-box crawler config templates for multiple websites generators. If you'd like to add a new template to our list, or believe we should update an existing one, please [let us know on Discord][1] or [open a pull request][2].
+
+> If you want to better understand the default parameters of the configs below, take a look at the [Crawler documentation](https://www.algolia.com/doc/tools/crawler/apis/configuration/).
+
+## Getting Started
+
+Once approved for DocSearch, we will automatically create a Crawler on your behalf, include your URL, and the Algolia credentials for your appId, apiKey, and indexName. If we detect that you are using any of the predefined generators, we'll attempt to automatically assign the proper template that matches your generator. However, this is not guaranteed. If no specific generator is detected, we will apply the default template seen below.
+
+## Updating the Template
+
+You can manually update the crawler template by going to dashboard.algolia.com, click "Data sources", select your crawler, and go to the editor page. From there you can edit the JavaScript directly. Note that you can make draft changes without saving, test the changes using the "URL Tester", and then "Save" once you're happy with your changes.
+
+## Default Template
+
+
+default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ indexPrefix: 'crawler_',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL'],
+ renderJavaScript: false,
+ sitemaps: [],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v1 Template
+
+
+docusaurus-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/docs/',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/blog/',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/docs/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Docs',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['docs'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/blog/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Blog',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['blog'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang', 'language', 'version', 'tags'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v2 & v3 Template
+
+
+docusaurus-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // priority order: deepest active sub list header -> navbar active item -> 'Documentation'
+ // Extracting the breadcrumb titles for better accessibility.
+ const navbarTitle = $(".navbar__item.navbar__link--active").text();
+ const pageBreadcrumbTitles = $(".breadcrumbs__link")
+ .toArray()
+ .map((item) => $(item).text().trim())
+ .filter(Boolean);
+ const lvl0 =
+ [navbarTitle, ...pageBreadcrumbTitles].join(" / ") || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: lvl0,
+ },
+ lvl1: ['header h1', 'article h1'],
+ lvl2: 'article h2',
+ lvl3: 'article h3',
+ lvl4: 'article h4',
+ lvl5: 'article h5, article td:first-child',
+ lvl6: 'article h6',
+ content: 'article p, article li, article td:last-child',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ 'language',
+ 'version',
+ 'docusaurus_tag',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+## Astro Starlight Template
+
+
+starlight.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Get the top level menu item
+ const lvl0 =
+ $('details:has(a[aria-current="page"])')
+ .find("summary")
+ .find("span")
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: "main h1",
+ lvl2: "main h2",
+ lvl3: "main h3",
+ lvl4: "main h4",
+ lvl5: "main h5",
+ lvl6: "main h6",
+ content: "main p, main li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v1 Template
+
+
+vuepress-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: 'p.sidebar-heading.open',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content__default h1',
+ lvl2: '.content__default h2',
+ lvl3: '.content__default h3',
+ lvl4: '.content__default h4',
+ lvl5: '.content__default h5',
+ content: '.content__default p, .content__default li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v2 Template
+
+
+vuepress-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vitepress Template
+
+
+vitepress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content h1',
+ lvl2: '.content h2',
+ lvl3: '.content h3',
+ lvl4: '.content h4',
+ lvl5: '.content h5',
+ content: '.content p, .content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Rspress Template
+
+
+rspress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ const lvl0 =
+ $(".rspress-nav-menu-item.rspress-nav-menu-item-active")
+ .first()
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: ".rspress-doc h1",
+ lvl2: ".rspress-doc h2",
+ lvl3: ".rspress-doc h3",
+ lvl4: ".rspress-doc h4",
+ lvl5: ".rspress-doc h5",
+ lvl6: ".rspress-doc pre > code", // if you want to search code blocks, add this line
+ content: ".rspress-doc p, .rspress-doc li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: "v3",
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## pkgdown Template
+
+
+pkgdown.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/index.html',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/reference',
+ 'https://YOUR_WEBSITE_URL/articles',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ exclusionPatterns: [
+ '**/reference/',
+ '**/reference/index.html',
+ '**/articles/',
+ '**/articles/index.html',
+ ],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/index.html**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ defaultValue: 'YOUR_INDEX_NAME Home page',
+ },
+ lvl1: '.contents h2',
+ lvl2: '.contents h3',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li, .contents .pre',
+ tags: {
+ defaultValue: ['homepage'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/reference**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.ref-arguments th',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['reference'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/articles**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.contents h2, .contents h3',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['articles'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+[1]: https://alg.li/discord
+[2]: https://github.com/algolia/docsearch
diff --git a/packages/website/versioned_docs/version-v4/tips.md b/packages/website/versioned_docs/version-v4/tips.md
new file mode 100644
index 00000000..57d1c4fa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/tips.md
@@ -0,0 +1,71 @@
+---
+title: Tips for a good search
+---
+
+DocSearch can work with almost any website, but we've found that some site structures yield more relevant results or faster indexing time. On this page we'll share some tips on how to make the most out of DocSearch.
+
+## Use a `sitemap.xml`
+
+If you provide a sitemap in your configuration, DocSearch will use it to directly browse the pages to index. Pages are still crawled which means we extract every compliant link.
+
+We highly recommend you add a `sitemap.xml` to your website if you don't have one already. This will not only make the indexing faster, but also provide you more control over which pages to index.
+
+Sitemaps are also considered good practice for other aspects, including SEO ([more information on sitemaps][1]).
+
+## Structure the hierarchy of information
+
+DocSearch works better on structured documentation. Relevance of results is based on the structural hierarchy of content. In simpler terms, it means that we read the ``, ..., `` headings of your page to guess the hierarchy of information. This hierarchy brings contextual information to your records.
+
+Documentation starts by explaining generic concepts first and then goes deeper into specifics. This is represented in your HTML markup by the hierarchy of headings you're using. For example, concepts discussed under a `` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+
+DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+
+Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+
+_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+
+## Set a unique class to the element holding the content
+
+DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
+
+Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+
+## Add anchors to headings
+
+When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+
+DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+
+## Marking the active page(s) in the navigation
+
+If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+
+For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
+
+The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+
+## Consistency of your content
+
+Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+
+The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+
+Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+
+Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+
+## Avoid duplicates by promoting unicity
+
+The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+
+Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+
+## Conciseness
+
+What is clearly thought out is clearly and concisely expressed.
+
+We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+
+[1]: https://www.sitemaps.org/index.html
+[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
+[3]: https://www.algolia.com/doc/guides/searching/faceting/
diff --git a/packages/website/docs/v4/askai-api.mdx b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
similarity index 97%
rename from packages/website/docs/v4/askai-api.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-api.mdx
index a01ff9e1..3edf58b2 100644
--- a/packages/website/docs/v4/askai-api.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
@@ -23,4 +23,4 @@ The official documentation includes:
- Integration examples with Next.js and Vercel AI SDK
- Error handling and best practices
-For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/askai).
+For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/v4/askai).
diff --git a/packages/website/docs/v4/askai-errors.mdx b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-errors.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
index 60b6d10b..53eb6f47 100644
--- a/packages/website/docs/v4/askai-errors.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
@@ -161,5 +161,5 @@ The request exceeded the model's maximum context length. This happens when the c
[1]: /docs/api#askai
[2]: https://sitesearch.algolia.com/docs/experiences/search-askai#configuration
[3]: https://www.algolia.com/doc/guides/algolia-ai/askai/reference/api
-[4]: /docs/v4/askai-whitelisted-domains
+[4]: /docs/v4/v4/askai-whitelisted-domains
[5]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/models
diff --git a/packages/website/docs/v4/askai-markdown-indexing.mdx b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-markdown-indexing.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
index 4160f9ef..4900f1b9 100644
--- a/packages/website/docs/v4/askai-markdown-indexing.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
@@ -39,7 +39,7 @@ The easiest way to set up markdown indexing is through the Crawler UI, which aut
- **Content Tag**: Specify the HTML content selector (typically `main`)
- **Template**: Choose the template that matches your documentation framework:
- **Docusaurus** - For Docusaurus sites
- - **VitePress** - For VitePress sites
+ - **VitePress** - For VitePress sites
- **Astro/Starlight** - For Astro/Starlight sites
- **Non-DocSearch (Generic)** - For custom sites or other frameworks
@@ -245,7 +245,7 @@ class CustomAskAI {
async sendMessage(conversationId, messages, searchParameters = {}) {
const token = await this.getToken();
-
+
const response = await fetch(`${this.baseUrl}/chat`, {
method: 'POST',
headers: {
@@ -270,14 +270,14 @@ class CustomAskAI {
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
-
+
return {
async *[Symbol.asyncIterator]() {
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
-
+
const chunk = decoder.decode(value, { stream: true });
if (chunk.trim()) {
yield chunk;
@@ -323,7 +323,7 @@ for await (const chunk of stream) {
- Integration with existing chat systems
- Custom analytics and monitoring
-> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/askai-api).
+> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/v4/askai-api).
**Using Facet Filters with Your Markdown Index:**
diff --git a/packages/website/docs/v4/askai-models.mdx b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
similarity index 71%
rename from packages/website/docs/v4/askai-models.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-models.mdx
index fff60ff5..63f10810 100644
--- a/packages/website/docs/v4/askai-models.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
@@ -2,7 +2,7 @@
title: Bring Your Own LLM
---
-import { ProvidersTable } from '../../src/components/ProvidersTable'
+import { ProvidersTable } from '@site/src/components/ProvidersTable';
Ask AI currently supports a Bring Your Own LLM (BYOLLM) model selection, allowing you to connect your preferred provider.
diff --git a/packages/website/docs/v4/askai-prompts.mdx b/packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-prompts.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
diff --git a/packages/website/docs/v4/askai-whitelisted-domains.mdx b/packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-whitelisted-domains.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
diff --git a/packages/website/docs/v4/askai.mdx b/packages/website/versioned_docs/version-v4/v4/askai.mdx
similarity index 98%
rename from packages/website/docs/v4/askai.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai.mdx
index 0cc29de5..9a561f57 100644
--- a/packages/website/docs/v4/askai.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai.mdx
@@ -118,5 +118,5 @@ This view gives you a centralized place to organize, reuse, and fine-tune your a
## Next steps
-- [Prompting with Ask AI](/docs/v4/askai-prompts)
-- [Ask AI Whitelisted Domains](/docs/v4/askai-whitelisted-domains)
+- [Prompting with Ask AI](/docs/v4/v4/askai-prompts)
+- [Ask AI Whitelisted Domains](/docs/v4/v4/askai-whitelisted-domains)
diff --git a/packages/website/versioned_docs/version-v4/what-is-docsearch.md b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
new file mode 100644
index 00000000..c371ae12
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
@@ -0,0 +1,32 @@
+---
+title: What is DocSearch?
+sidebar_label: What is DocSearch?
+---
+
+## Why?
+
+We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+
+It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+
+## Quick description
+
+We split DocSearch into a crawler and a frontend library.
+
+- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
+- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+
+## How to feature DocSearch?
+
+DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+
+DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
+
+You can now [apply to the program][3].
+
+[1]: https://opencollective.com/algolia
+[2]: /docs/who-can-apply
+[3]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[4]: https://www.algolia.com/products/search-and-discovery/crawler/
+[5]: https://dashboard.algolia.com/crawler
+[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
diff --git a/packages/website/versioned_docs/version-v4/who-can-apply.md b/packages/website/versioned_docs/version-v4/who-can-apply.md
new file mode 100644
index 00000000..cec7c5ae
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/who-can-apply.md
@@ -0,0 +1,30 @@
+---
+title: Who can apply?
+---
+
+**Open for all developer documentation and technical blogs.**
+
+We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all public online technical documentations and technical blogs.
+
+We usually turn down applications when they are not production ready or have non-technical content on the website.
+
+## Application process
+
+To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+
+- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+
+- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+
+- β
Please review [DocSearch Plan Terms and Conditions][2].
+
+## Process duration
+
+DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+
+Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
+[3]: integrations.md
+[4]: https://alg.li/discord
diff --git a/packages/website/versioned_sidebars/version-v4-sidebars.json b/packages/website/versioned_sidebars/version-v4-sidebars.json
new file mode 100644
index 00000000..74276efe
--- /dev/null
+++ b/packages/website/versioned_sidebars/version-v4-sidebars.json
@@ -0,0 +1,81 @@
+{
+ "docs": [
+ {
+ "type": "category",
+ "label": "Introduction",
+ "items": ["what-is-docsearch", "who-can-apply"]
+ },
+ {
+ "type": "category",
+ "label": "DocSearch v4",
+ "items": ["docsearch", "docusaurus-adapter", "composable-api", "styling", "api", "examples", "migrating-from-v3"]
+ },
+ {
+ "type": "category",
+ "label": "MCP",
+ "items": ["mcp/overview", "mcp/installation", "mcp/usage"]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Ask AI",
+ "items": [
+ "v4/askai",
+ "v4/askai-api",
+ "v4/askai-prompts",
+ "v4/askai-whitelisted-domains",
+ "v4/askai-models",
+ "v4/askai-markdown-indexing",
+ "v4/askai-errors",
+ {
+ "type": "link",
+ "label": "Full Documentation",
+ "href": "https://www.algolia.com/doc/guides/algolia-ai/askai"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Sidepanel",
+ "items": [
+ "sidepanel/getting-started",
+ "sidepanel/advanced-use-cases",
+ "sidepanel/hybrid",
+ "sidepanel/api-reference"
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Crawler",
+ "items": ["create-crawler", "record-extractor", "templates", "crawler-configuration-visual", "manage-your-crawls"]
+ },
+ {
+ "type": "category",
+ "label": "Requirements, tips, FAQ",
+ "items": [
+ {
+ "type": "category",
+ "label": "FAQ",
+ "items": ["crawler", "docsearch-program"]
+ },
+ {
+ "type": "doc",
+ "id": "tips"
+ },
+ {
+ "type": "doc",
+ "id": "integrations"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Under the hood",
+ "items": ["how-does-it-work", "required-configuration"]
+ },
+ {
+ "type": "category",
+ "label": "Miscellaneous",
+ "items": ["migrating-from-legacy"]
+ }
+ ]
+}
diff --git a/packages/website/versions.json b/packages/website/versions.json
index dbac805d..9b27128c 100644
--- a/packages/website/versions.json
+++ b/packages/website/versions.json
@@ -1 +1 @@
-["v3", "legacy"]
+["v4", "v3", "legacy"]
` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+Documentation usually introduces general concepts before covering details. Represent this structure with an ordered heading hierarchy. For example, content under an `` is more specific than content under an `` on the same page. Content that appears earlier on the page ranks higher.
-DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+DocSearch uses this structure to improve relevance. V5 also uses the populated hierarchy levels to render result breadcrumbs. Keep headings in order and avoid skipping levels where possible so each result retains its page context.
-Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+Choose a documentation depth that gives each result enough context. For large pages, use four levels, from `lvl0` to `lvl3`. Use at least three levels.
-_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+You can use classes, such as ``, instead of `` elements.
## Set a unique class to the element holding the content
DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
-Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+A unique identifier makes your configuration more robust and limits indexing to relevant content. Use it to exclude unrelated headers, sidebars, and footers.
## Add anchors to headings
-When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+Add a custom anchor to each heading. Define anchors with an `id` or `name` HTML attribute so browsers can scroll directly to the corresponding position. Links can target an anchor with `#` followed by its value.
-DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+DocSearch uses these anchors to send users to the location of the selected result.
-## Marking the active page(s) in the navigation
+## Mark active pages in the navigation
-If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+If you use multi-level navigation, mark each active level with a custom CSS class. The crawler can use this class to determine where the current page fits in the website hierarchy.
For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
-The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+Use any valid CSS class name that can be part of a CSS selector.
## Consistency of your content
-Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+Use the same heading structure across documentation pages. Make each page topic and outline clear, and avoid selectors that create records without enough context, such as standalone introductions or asides.
-The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+Write selectors that match documentation pages but exclude landing pages, tables of contents, and other unrelated content. Add a dedicated class, such as `.DocSearch-content`, to the main documentation container.
-Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+Use consistent terms for the same concepts. You can also configure [synonyms][5] for terms your users search interchangeably.
-Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+## Avoid duplicate content
-## Avoid duplicates by promoting unicity
+Split broad topics into focused pages. Avoid catch-all pages that make it difficult to identify the relevant result.
-The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+Duplicate content adds noise and can mislead users. Don't repeat all documentation content on a landing or summary page. If you need duplicate records for separate datasets, such as different versions, use [facets][3] to distinguish them.
-Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+## Index metadata for v5
+
+Add each attribute used by the v5 `facets` option to `attributesForFaceting`. DocSearch supports up to five facet controls. For a result badge, index a short value such as `version`, include it in `attributesToRetrieve`, and pass its property path to `resultBadgeKey`. See the [v5 JavaScript API reference][4].
## Conciseness
-What is clearly thought out is clearly and concisely expressed.
+Keep content focused on one task or concept, and use short headings and paragraphs.
-We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+For more guidance, read [How to build a helpful search for technical documentation][2].
[1]: https://www.sitemaps.org/index.html
[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
[3]: https://www.algolia.com/doc/guides/searching/faceting/
+[4]: /docs/packages/js/api-reference#facets
+[5]: https://www.algolia.com/doc/guides/managing-results/must-do/searchable-attributes/#synonyms
diff --git a/packages/website/docs/v5-breaking-changes.mdx b/packages/website/docs/v5-breaking-changes.mdx
new file mode 100644
index 00000000..f3ec2ef5
--- /dev/null
+++ b/packages/website/docs/v5-breaking-changes.mdx
@@ -0,0 +1,236 @@
+---
+title: v5 breaking changes
+description: Complete user-facing breaking changes and compatibility notes for DocSearch v5.
+---
+
+This page lists the user-facing changes between the v4.6.0 package source and `5.0.0-beta.0`. Use it with the [v4 migration guide](./migrating-from-v4).
+
+## JavaScript entry points
+
+### The root export is AI-capable
+
+In v4, the root `@docsearch/js` export rendered the combined component and allowed Ask AI to be omitted. In v5, it renders `DocSearchAI`, and its `DocSearchProps` type requires `askAi`.
+
+Use the root entry when you configure Agent Studio:
+
+```js title="app.js"
+import docsearch from '@docsearch/js';
+```
+
+### Keyword-only search moved to `/docsearch`
+
+Use the new subpath when you don't need Ask AI:
+
+```js title="app.js"
+import docsearch from '@docsearch/js/docsearch';
+```
+
+This entry excludes Ask AI code.
+
+### The UMD bundle is split
+
+- `dist/umd/index.js` includes keyword search and Ask AI.
+- `dist/umd/docsearch.js` includes keyword search only.
+- Both bundles expose `window.docsearch`.
+- Loading both bundles causes the later script to replace the same global.
+
+### An exports map restricts JavaScript imports
+
+`@docsearch/js` now exports only `.` and `./docsearch`. Replace imports of internal distribution files with one of these public entry points. Direct CDN URLs to the two documented UMD files remain supported by the package layout.
+
+## React components
+
+### `DocSearch` is keyword-only
+
+V4's `DocSearch` accepted `askAi` and `interceptAskAiEvent`. V5's `DocSearch` contains keyword search only and no longer declares those props.
+
+### `DocSearchAI` owns the AI experience
+
+Use `DocSearchAI` for keyword search and Ask AI:
+
+```jsx title="Search.jsx"
+import { DocSearchAI } from '@docsearch/react';
+```
+
+`DocSearchAIProps` extends `DocSearchProps`, requires `askAi`, and adds `interceptAskAiEvent`.
+
+The package also adds `@docsearch/react/docsearchAi` and `@docsearch/react/askaiModal` subpaths.
+
+### The Ask AI modal is separate
+
+`DocSearchModal` is keyword-only. `DocSearchAskAiModal` contains the combined keyword and AI modal. Composable integrations that rendered `DocSearchModal` with `askAi` must switch to `DocSearchAskAiModal` and its required provider callbacks. Review the [Composable API](/docs/composable-api) instead of constructing these props without the provider.
+
+`@docsearch/modal` exports the AI modal from its root and from `@docsearch/modal/askai`.
+
+## Ask AI and Agent Studio
+
+### The legacy transport is removed
+
+V5 no longer requests a legacy Ask AI token or sends chat requests to the v4 Ask AI endpoint. All Ask AI conversations use the Agent Studio completions endpoint.
+
+Create and configure an assistant in [Agent Studio](/docs/agent-studio/getting-started) before upgrading.
+
+### `askAi.agentStudio` is removed
+
+The backend switch is no longer needed because Agent Studio is the only backend. Remove both `agentStudio: true` and `agentStudio: false`.
+
+### `askAi.useStagingEnv` is removed
+
+The staging endpoint switch isn't part of `DocSearchAskAi` in v5.
+
+### Flat Ask AI search parameters are removed
+
+`DocSearchAskAi.searchParameters` now always uses `AgentStudioSearchParameters`: an object keyed by index name.
+
+```js title="app.js"
+searchParameters: {
+ docs: {
+ filters: 'language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ distinct: true,
+ },
+}
+```
+
+Each value supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`. The Agent Studio type omits `facetFilters`.
+
+### Agent Studio credentials are sent directly
+
+Ask AI requests use the configured application ID and API key in `x-algolia-application-id` and `x-algolia-api-key` headers. Memory authentication adds `x-algolia-secure-user-token`. Check the permissions and domain restrictions of keys that were issued for the legacy transport.
+
+### Feedback uses Agent Studio
+
+Feedback now posts to Agent Studio and supports negative-feedback reason tags and notes. Stored conversation messages can contain `feedbackTags` and `feedbackNotes` in addition to the like or dislike value.
+
+### Agent Studio configuration is nested under `askAi`
+
+Dynamic `indices`, custom `tools`, `memory`, and keyword `promptSuggestions` belong inside the `askAi` object. `interceptAskAiEvent` remains a top-level integration callback.
+
+### Suggested questions have two sources
+
+- `askAi.suggestedQuestions` determines whether DocSearch loads published questions for the assistant from `algolia_ask_ai_suggested_questions` on the new-conversation screen.
+- `askAi.promptSuggestions` searches a configured index containing a `prompt` attribute and displays those prompts with keyword results.
+
+These options aren't interchangeable.
+
+## Search configuration
+
+### The Docusaurus adapter configuration changed
+
+The v5 adapter reads `themeConfig.docsearch` and rejects the former `themeConfig.algolia` key. It also requires `indices` and rejects `indexName` and root `searchParameters`.
+
+Replace `searchPagePath` with `searchPage`. Move `askAi.sidePanel` to the root `sidePanel` option. Remove legacy Ask AI credentials and the `askAi.agentStudio` switch. Follow [Migrate the Docusaurus adapter from v4](/docs/packages/docusaurus-adapter/migrating-from-v4) for before-and-after configurations.
+
+### At least one index is required at runtime
+
+Pass `indices` or `indexName`. V5 throws this error when neither produces an index:
+
+```text
+Must supply either `indexName` or `indices` for DocSearch to work
+```
+
+### `indexName` remains deprecated
+
+`indexName` still works; it isn't removed in v5. If present, DocSearch places it before all `indices` entries. Passing the same index through both options sends duplicate requests.
+
+### Root `searchParameters` remains deprecated
+
+The root option applies only to `indexName`. Move search parameters to each `DocSearchIndex` in `indices`.
+
+### Multiple indices share one result flow
+
+V5 creates one source for each index response and combines hit totals across responses. Result order follows the normalized index order. Review code that assumes one index or source identifier.
+
+## New keyword search behavior
+
+### Facets add requests and filters
+
+The new `facets` option fetches facet values with a zero-hit query for every configured index. DocSearch merges and sorts values, supports at most five keys after trimmed, lowercase duplicate checks, and displays only facets with values.
+
+A selected value is appended to that index's existing `facetFilters`. Account for the additional facet-value request in analytics, rate estimates, and search-client mocks.
+
+### Result badges require retrieved attributes
+
+The new `resultBadgeKey` reads a property path from each hit. The default `attributesToRetrieve` list doesn't include custom badge properties. Add them to each relevant index's `searchParameters.attributesToRetrieve`.
+
+### Result markup and grouping changed
+
+V5 refreshes the modal and result markup, renders breadcrumbs, introduces source panels, and adds facet and badge elements. CSS selectors, DOM tests, snapshots, and custom overrides that target v4 internals can break.
+
+Use public component props for behavior and review [Styling](/docs/packages/css/styling) for visual changes.
+
+## Styles and builds
+
+### Ask AI styles have a separate source bundle
+
+The complete `@docsearch/css` stylesheet still imports button, modal, and Ask AI rules. React also exposes split style entries:
+
+- `@docsearch/react/style/variables`
+- `@docsearch/react/style/button`
+- `@docsearch/react/style/modal`
+- `@docsearch/react/style/askai`
+- `@docsearch/react/style/sidepanel`
+
+If you assemble styles by component, add `style/askai` for `DocSearchAI` or `DocSearchAskAiModal`.
+
+### Generated React file names changed
+
+The documented package subpaths remain stable, but their targets changed from names such as `dist/esm/DocSearchModal.js` to generated entry files such as `dist/esm/modal.js`. Imports that bypassed the package exports can break.
+
+### The React `main` field now points to ESM
+
+`@docsearch/react` changes `main` from `dist/umd/index.js` to `dist/esm/index.js`. Consumers that resolve `main` instead of the package exports need an ESM-compatible build pipeline. The explicit `unpkg` and `jsdelivr` fields continue to point to `dist/umd/index.js`.
+
+### The browser target is ES2017
+
+V5's tsdown builds target ES2017. Provide transpilation or polyfills if your browser support policy extends below that target.
+
+## Public controls
+
+### JavaScript instances don't expose Sidepanel state
+
+`DocSearchInstance` exposes `open`, `close`, `openAskAi`, `destroy`, `isReady`, and `isOpen`. It doesn't expose `openSidepanel`, `isSidepanelOpen`, or `isSidepanelSupported`.
+
+### React refs include Sidepanel controls
+
+`DocSearchRef` exposes the JavaScript-style modal controls plus `openSidepanel`, `isSidepanelOpen`, and `isSidepanelSupported`. `openSidepanel` does nothing until a Sidepanel view registers. On mobile, `openAskAi` and standard Ask AI actions fall back to the modal.
+
+See [hybrid mode](/docs/hybrid-mode) for the supported integration.
+
+### Deprecated keyboard hook fields remain
+
+`UseDocSearchKeyboardEventsProps.onInput` and `searchButtonRef` are accepted for compatibility but are deprecated and aren't used by the v5 React hook implementation.
+
+## Compatibility
+
+### React peer range
+
+`@docsearch/react`, `@docsearch/core`, `@docsearch/modal`, and `@docsearch/sidepanel` declare these optional peers:
+
+- `react`: `>=16.8.0 <20.0.0`
+- `react-dom`: `>=16.8.0 <20.0.0`
+- `@types/react`: `>=16.8.0 <20.0.0`
+
+`@docsearch/react` also accepts optional `search-insights` versions `>=1 <3`.
+
+### Package versions must match
+
+The `5.0.0-beta.0` packages depend on matching beta versions of the other DocSearch packages. Don't mix v4 and v5 packages in a Composable API or Sidepanel tree.
+
+### CSS remains a separate install for top-level integrations
+
+Install `@docsearch/css@^5.0.0-beta`, then import `@docsearch/css`. For a CDN integration, load `dist/style.css` from the same caret beta range.
+
+## Additive v5 APIs
+
+These additions aren't breaking by themselves, but they replace common v4 custom implementations:
+
+- `facets` and `DocSearchFacet` for keyword filters.
+- `resultBadgeKey` for hit metadata.
+- `DocSearchAI` and `DocSearchAskAiModal` for AI-capable React views.
+- `AgentStudioIndices` and `AgentStudioSearchControls` for dynamic search tools.
+- `ToolCalls` and `ToolDefinition` for custom Agent Studio tools.
+- `Memory` for user-scoped Agent Studio memory.
+- `PromptSuggestions` for keyword-query prompt suggestions.
+- Ask AI feedback tags and notes.
+- Split JavaScript, React, and style entries for smaller keyword-only builds.
diff --git a/packages/website/docs/what-is-docsearch.md b/packages/website/docs/what-is-docsearch.md
index 5b9cc3c9..cd0ecc17 100644
--- a/packages/website/docs/what-is-docsearch.md
+++ b/packages/website/docs/what-is-docsearch.md
@@ -1,24 +1,27 @@
---
title: What is DocSearch?
+description: Understand how DocSearch provides search for technical documentation.
sidebar_label: What is DocSearch?
---
## Why?
-We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+We created DocSearch because developers spend a lot of time reading documentation, and finding relevant information in large documentation sites can be difficult. Building good search is a challenge.
-It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+Algolia has extensive experience building search interfaces. We use that experience to extract content from technical documentation and make it searchable from the first keystroke.
-## Quick description
+## Overview
-We split DocSearch into a crawler and a frontend library.
+DocSearch has two independent parts: indexing and the frontend search experience.
-- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
-- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+- The [Algolia Crawler][4] extracts your documentation into an Algolia index. Use the [Crawler interface][5] to edit the crawler configuration, monitor crawls, and trigger new crawls.
+- The [DocSearch v5 packages][7] query that index and render keyword search or Ask AI in your frontend. They are built on [Algolia Autocomplete][6].
+
+Crawler configuration and record schema versions don't select the installed DocSearch frontend package version. You can update the frontend package without changing how the crawler is scheduled.
## How to feature DocSearch?
-DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+DocSearch is free for eligible documentation sites. Read [the eligibility requirements][2] and apply. After approval and indexing, add a [DocSearch v5 package][7] or a supported framework integration to your website. Keep the "Search by Algolia" link displayed.
DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
@@ -30,3 +33,4 @@ You can now [apply to the program][3]
[4]: https://www.algolia.com/products/search-and-discovery/crawler/
[5]: https://dashboard.algolia.com/crawler
[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[7]: /docs/packages/overview
diff --git a/packages/website/docs/who-can-apply.md b/packages/website/docs/who-can-apply.md
index 320814d0..317b2249 100644
--- a/packages/website/docs/who-can-apply.md
+++ b/packages/website/docs/who-can-apply.md
@@ -1,30 +1,32 @@
---
title: Who can apply?
+description: Check whether your documentation project is eligible for DocSearch.
---
-**Open for all developer documentation and technical blogs.**
+**Open to developer documentation and technical blogs.**
-We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all online technical documentations and technical blogs.
+We built DocSearch to improve search on large technical documentation sites. We offer the free DocSearch program to public technical documentation and technical blogs.
We usually turn down applications when they are not production ready or have non-technical content on the website.
## Application process
-To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+To [apply][1] to the DocSearch program, follow the onboarding process in the Algolia dashboard. Submit your domain for validation against the program requirements. If your domain meets the criteria, you can create your DocSearch crawler.
-- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+- Use one of our [supported integrations][3] or a [DocSearch v5 package][5] after your content is indexed.
-- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+- Verify your domain ownership within 7 days of approval to continue using the crawler.
-- β
Please review [DocSearch Plan Terms and Conditions][2].
+- Review the [DocSearch Plan Terms and Conditions][2].
## Process duration
-DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+The application process includes automated validation. If we can't determine your eligibility automatically, we'll conduct a manual review that may take one to two business days.
-Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+Once approved, continue the onboarding process to create your DocSearch crawler. After the crawler indexes your data, choose the frontend package or framework integration separately. Updating the frontend doesn't change your crawler or index format.
[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
[3]: integrations.md
[4]: https://alg.li/discord
+[5]: /docs/packages/overview
diff --git a/packages/website/docusaurus.config.mjs b/packages/website/docusaurus.config.mjs
index f1605941..8c70af8f 100644
--- a/packages/website/docusaurus.config.mjs
+++ b/packages/website/docusaurus.config.mjs
@@ -50,7 +50,10 @@ export default {
'https://github.com/algolia/docsearch/edit/main/packages/website/',
versions: {
current: {
- label: 'Latest (v4.x)',
+ label: 'Beta (v5.0.0-beta.x)',
+ },
+ v4: {
+ label: 'Stable (v4.x)',
},
v3: {
label: 'Legacy (v3.x)',
@@ -138,9 +141,9 @@ export default {
],
},
announcementBar: {
- id: 'announcement-bar',
+ id: 'docsearch-v5-beta',
content:
- 'π Get Ask AI now! Turn your docs site search into an AI-powered assistant β faster answers, fewer tickets, better self-serve. Get Started Now',
+ 'DocSearch 5.0.0-beta is available. Migrate from v4 or choose a package.',
},
colorMode: {
defaultMode: 'light',
@@ -165,8 +168,12 @@ export default {
to: 'docs/v3/docsearch',
},
{
- label: 'DocSearch v4 - Beta',
- to: 'docs/docsearch',
+ label: 'DocSearch v4',
+ to: 'docs/v4/docsearch',
+ },
+ {
+ label: 'DocSearch v5 beta',
+ to: 'docs/packages/overview',
},
],
},
diff --git a/packages/website/sidebars.js b/packages/website/sidebars.js
index cc5d370b..c4fbae84 100644
--- a/packages/website/sidebars.js
+++ b/packages/website/sidebars.js
@@ -13,19 +13,87 @@ export default {
{
type: 'category',
label: 'Introduction',
- items: ['what-is-docsearch', 'who-can-apply'],
+ items: [
+ 'what-is-docsearch',
+ 'who-can-apply',
+ 'migrating-from-v4',
+ 'v5-breaking-changes',
+ ],
},
{
type: 'category',
- label: 'DocSearch v4',
+ label: 'Packages',
items: [
- 'docsearch',
- 'docusaurus-adapter',
+ 'packages/overview',
+ {
+ type: 'category',
+ label: '@docsearch/js',
+ items: ['packages/js/getting-started', 'packages/js/api-reference'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/react',
+ items: [
+ 'packages/react/getting-started',
+ 'packages/react/api-reference',
+ 'packages/react/examples',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/modal',
+ items: ['packages/modal/overview', 'packages/modal/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel',
+ items: [
+ 'packages/sidepanel/getting-started',
+ 'packages/sidepanel/advanced-use-cases',
+ 'packages/sidepanel/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel-js',
+ items: [
+ 'packages/sidepanel-js/getting-started',
+ 'packages/sidepanel-js/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/css',
+ items: ['packages/css/styling', 'packages/css/bundle-exports'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/core',
+ items: ['packages/core/overview', 'packages/core/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/docusaurus-adapter',
+ items: [
+ 'packages/docusaurus-adapter/getting-started',
+ 'packages/docusaurus-adapter/configuration-reference',
+ 'packages/docusaurus-adapter/migrating-from-v4',
+ ],
+ },
'composable-api',
- 'styling',
- 'api',
- 'examples',
- 'migrating-from-v3',
+ 'hybrid-mode',
+ ],
+ },
+ {
+ type: 'category',
+ label: 'Agent Studio',
+ items: [
+ 'agent-studio/getting-started',
+ 'agent-studio/dynamic-indices',
+ 'agent-studio/tools',
+ 'agent-studio/memory',
+ 'agent-studio/prompt-suggestions',
+ 'agent-studio/feedback',
],
},
{
@@ -33,34 +101,6 @@ export default {
label: 'MCP',
items: ['mcp/overview', 'mcp/installation', 'mcp/usage'],
},
- {
- type: 'category',
- label: 'Algolia Ask AI',
- items: [
- 'v4/askai',
- 'v4/askai-api',
- 'v4/askai-prompts',
- 'v4/askai-whitelisted-domains',
- 'v4/askai-models',
- 'v4/askai-markdown-indexing',
- 'v4/askai-errors',
- {
- type: 'link',
- label: 'Full Documentation',
- href: 'https://www.algolia.com/doc/guides/algolia-ai/askai',
- },
- ],
- },
- {
- type: 'category',
- label: 'Sidepanel',
- items: [
- 'sidepanel/getting-started',
- 'sidepanel/advanced-use-cases',
- 'sidepanel/hybrid',
- 'sidepanel/api-reference',
- ],
- },
{
type: 'category',
label: 'Algolia Crawler',
diff --git a/packages/website/src/components/Home.js b/packages/website/src/components/Home.js
index a8a4ea86..ee5dbb91 100644
--- a/packages/website/src/components/Home.js
+++ b/packages/website/src/components/Home.js
@@ -116,9 +116,9 @@ function Home() {
+ eyebrow="Interactive demo"
+ title="See DocSearch in action"
+ />
diff --git a/packages/website/versioned_docs/version-v4/api.mdx b/packages/website/versioned_docs/version-v4/api.mdx
new file mode 100644
index 00000000..ecf87ebb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/api.mdx
@@ -0,0 +1,935 @@
+---
+title: API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+
+
+
+## `container`
+
+> `type: string | HTMLElement` | **required**
+
+The container for the DocSearch search box. You can either pass a [CSS selector][5] or an [Element][6]. If there are several containers matching the selector, DocSearch picks up the first one.
+
+## `environment`
+
+> `type: typeof window` | `default: window` | **optional**
+
+The environment in which your application is running.
+
+This is useful if youβre using DocSearch in a different context than `window`.
+
+
+
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `indices`
+
+> `type: Array`
+
+The list of indices and their _optional_ `searchParameters` to be used for keyword search.
+
+[Algolia Search Parameters][7]
+
+:::tip
+
+The ordering matters in the list, as results are ordered based on `indices` order.
+
+:::
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+
+
+
+```js
+docsearch({
+ // ...
+ indices: ['YOUR_ALGOLIA_INDEX'],
+ // ...
+});
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```js
+docsearch({
+ // ...
+ indices: [
+ {
+ name: 'YOUR_ALGOLIA_INDEX',
+ searchParameters: {
+ facetFilters: ['language:en'],
+ // ...
+ },
+ },
+ ],
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```jsx
+
+```
+
+
+
+
+## `indexName`
+
+> `type: string` | **deprecated**
+
+:::warning[Deprecation warning]
+
+`indexName` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+Your Algolia index name.
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+## `placeholder`
+
+> `type: string` | `default: "Search docs"` | **optional**
+
+The placeholder of the input of the DocSearch pop-up modal. Note: If you add a placeholder, it will replace the dynamic placeholder based on `askAi`. It would be better to edit [translations](#translations) instead.
+
+## `askAi`
+
+> `type: AskAiObject` | `string` | **optional**
+
+Your Algolia Assistant ID.
+
+
+
+
+```js
+docsearch({
+ // ...
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ // ...
+});
+```
+
+or if you want to use different credentials for `askAi` and add search parameters
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ indexName: 'ANOTHER_INDEX_NAME',
+ apiKey: 'ANOTHER_SEARCH_API_KEY',
+ appId: 'ANOTHER_APP_ID',
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ // Filtering parameters
+ facetFilters: ['language:en', 'version:latest'],
+ filters: 'type:content AND language:en',
+
+ // Content control parameters
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+
+ // Deduplication
+ distinct: true,
+ },
+
+ // Enables/disables showing suggested questions on Ask AI's new conversation screen
+ // NOTE: Only available with version >= 4.3
+ suggestedQuestions: true,
+ },
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use different credentials for `askAi`
+
+```jsx
+= 4.3
+ suggestedQuestions: true,
+ }}
+/>
+```
+
+
+
+
+:::tip[Ask AI supports these essential search parameters for optimal performance:]
+
+- **Filtering**: `facetFilters: ['type:content']` - Filter by language, version, or content type
+- **Complex filtering**: `filters: 'type:content AND language:en'` - Apply complex filtering rules
+- **Content control**: `attributesToRetrieve: ['title', 'content', 'url']` - Control which attributes are retrieved
+- **Search scope**: `restrictSearchableAttributes: ['title', 'content']` - Limit search to specific fields
+- **Deduplication**: `distinct: true` - Remove duplicate results (`boolean | number | string`)
+
+These parameters provide the essential functionality for Ask AI while keeping the API simple and focused.
+
+:::
+
+### `askAi.agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`askAi.agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `askAi.agentStudio` is `true`, the Ask AI chat will use Algolia's [Agent Studio][12] as the chat backend instead of the Ask AI backend. Learn more on [Algolia Agent Studio Docs][13].
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+::::info[Search parameter shapes]
+
+- Standard Ask AI (`agentStudio` omitted or `false`): `searchParameters` is a flat object and supports `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- Agent Studio (`agentStudio: true`): `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+::::
+
+## `searchParameters`
+
+> `type: SearchParameters` | **optional** | **deprecated**
+
+:::warning[Deprecation warning]
+
+`searchParameters` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+The [Algolia Search Parameters][7].
+
+## `transformItems`
+
+> `type: function` | `default: items => items` | **optional**
+
+Receives the items from the search response, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them.
+
+
+
+
+```js
+docsearch({
+ // ...
+ transformItems(items) {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ }}
+/>
+```
+
+
+
+
+## `hitComponent`
+
+> `type: ({ hit, children }, { html }) => JSX.Element | string | Function` | `default: Hit` | **optional**
+
+The component to display each item. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ hit, children }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ hit, children }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the `hit` object which contains all the data for the search result, and `children` which is the default rendered content.
+
+See the [default implementation][8].
+
+
+
+
+```js
+docsearch({
+ // ...
+ hitComponent({ hit, children }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+
+ ${children}
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ π
+ {children}
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `transformSearchClient`
+
+> `type: function` | `default: DocSearchTransformClient => DocSearchTransformClient` | **optional**
+
+Useful for transforming the [Algolia Search Client][10], for example to [debounce search queries][9]
+
+## `disableUserPersonalization`
+
+> `type: boolean` | `default: false` | **optional**
+
+Disable saving recent searches and favorites to the local storage.
+
+## `initialQuery`
+
+> `type: string` | **optional**
+
+The search input initial query.
+
+## `navigator`
+
+> `type: Navigator` | **optional**
+
+An implementation of [Algolia Autocomplete][1]βs Navigator API to redirect the user when opening a link.
+
+Learn more on the [Navigator API][11] documentation.
+
+## `translations`
+
+> `type: Partial` | `default: docSearchTranslations` | **optional**
+
+Allow translations of any raw text and aria-labels present in the DocSearch button or modal components.
+
+
+docSearchTranslations
+
+
+```ts
+const translations: DocSearchTranslations = {
+ button: {
+ buttonText: 'Search',
+ buttonAriaLabel: 'Search',
+ },
+ modal: {
+ searchBox: {
+ clearButtonTitle: 'Clear',
+ clearButtonAriaLabel: 'Clear the query',
+ closeButtonText: 'Close',
+ closeButtonAriaLabel: 'Close',
+ placeholderText: undefined, // fallback: 'Search docs' or 'Search docs or ask AI a question'
+ placeholderTextAskAi: undefined, // fallback: 'Ask another question...'
+ placeholderTextAskAiStreaming: 'Answering...',
+ // can only be one of the following
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/enterkeyhint#value
+ enterKeyHint: 'search',
+ enterKeyHintAskAi: 'enter',
+ searchInputLabel: 'Search',
+ backToKeywordSearchButtonText: 'Back to keyword search',
+ backToKeywordSearchButtonAriaLabel: 'Back to keyword search',
+ newConversationPlaceholder: 'Ask a question',
+ conversationHistoryTitle: 'My conversation history',
+ startNewConversationText: 'Start a new conversation',
+ viewConversationHistoryText: 'Conversation history'
+ },
+ startScreen: {
+ recentSearchesTitle: 'Recent',
+ noRecentSearchesText: 'No recent searches',
+ saveRecentSearchButtonTitle: 'Save this search',
+ removeRecentSearchButtonTitle: 'Remove this search from history',
+ favoriteSearchesTitle: 'Favorite',
+ removeFavoriteSearchButtonTitle: 'Remove this search from favorites',
+ recentConversationsTitle: 'Recent conversations',
+ removeRecentConversationButtonTitle:
+ 'Remove this conversation from history',
+ },
+ errorScreen: {
+ titleText: 'Unable to fetch results',
+ helpText: 'You might want to check your network connection.',
+ },
+ noResultsScreen: {
+ noResultsText: 'No results found for',
+ suggestedQueryText: 'Try searching for',
+ reportMissingResultsText: 'Believe this query should return results?',
+ reportMissingResultsLinkText: 'Let us know.',
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'Ask AI: ',
+ noResultsAskAiPlaceholder: 'Didn't find it in the docs? Ask AI to help: ',
+ },
+ askAiScreen: {
+ disclaimerText:
+ 'Answers are generated with AI which can make mistakes. Verify responses.',
+ relatedSourcesText: 'Related sources',
+ thinkingText: 'Thinking...',
+ copyButtonText: 'Copy',
+ copyButtonCopiedText: 'Copied!',
+ copyButtonTitle: 'Copy',
+ likeButtonTitle: 'Like',
+ dislikeButtonTitle: 'Dislike',
+ thanksForFeedbackText: 'Thanks for your feedback!',
+ preToolCallText: 'Searching...',
+ duringToolCallText: 'Searching for ',
+ afterToolCallText: 'Searched for',
+ // If provided, these override the default rendering of aggregated tool calls:
+ aggregatedToolCallNode: undefined, // (queries: string[], onSearchQueryClick: (query: string) => void) => React.ReactNode
+ aggregatedToolCallText: undefined, // (queries: string[]) => { before?: string; separator?: string; lastSeparator?: string; after?: string }
+ // Text to show when user has stopped streaming a message
+ stoppedStreamingText: 'You stopped this response',
+ },
+ footer: {
+ selectText: 'Select',
+ submitQuestionText: 'Submit question',
+ selectKeyAriaLabel: 'Enter key',
+ navigateText: 'Navigate',
+ navigateUpKeyAriaLabel: 'Arrow up',
+ navigateDownKeyAriaLabel: 'Arrow down',
+ closeText: 'Close',
+ backToSearchText: 'Back to search',
+ closeKeyAriaLabel: 'Escape key',
+ poweredByText: 'Powered by',
+ },
+ newConversation: {
+ newConversationTitle: 'How can I help you today?',
+ newConversationDescription: 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.'
+ }
+ },
+};
+```
+
+
+
+
+## `getMissingResultsUrl`
+
+> `type: ({ query: string }) => string` | **optional**
+
+Function to return the URL of your documentation repository.
+
+
+
+
+```js
+docsearch({
+ // ...
+ getMissingResultsUrl({ query }) {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ }}
+/>
+```
+
+
+
+
+When provided, an informative message wrapped with your link will be displayed on no results searches. The default text can be changed using the [translations](#translations) property.
+
+
+
+
+
+## `keyboardShortcuts`
+
+> `type: KeyboardShortcuts` | **optional**
+
+Configuration for keyboard shortcuts that trigger the search modal.
+
+### Default behavior:
+
+- `Ctrl/Cmd+K` - Opens and closes the search modal
+- `/` - Opens the search modal (doesn't close)
+
+### Interface:
+
+```typescript
+interface KeyboardShortcuts {
+ 'Ctrl/Cmd+K'?: boolean; // default: true
+ '/'?: boolean; // default: true
+}
+```
+
+
+
+
+```js
+// Default - all shortcuts enabled
+docsearch({
+ // ...
+});
+
+// Disable slash shortcut
+docsearch({
+ // ...
+ keyboardShortcuts: { '/': false },
+});
+
+// Disable Ctrl/Cmd+K shortcut (also hides button hint)
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false },
+});
+
+// Disable all keyboard shortcuts
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false, '/': false },
+});
+```
+
+
+
+
+
+```jsx
+{
+ /* Default - all shortcuts enabled */
+}
+ ;
+
+{
+ /* Disable slash shortcut */
+}
+ ;
+
+{
+ /* Disable Ctrl/Cmd+K shortcut (also hides button hint) */
+}
+ ;
+
+{
+ /* Disable all keyboard shortcuts */
+}
+ ;
+```
+
+
+
+
+:::info[Keyboard Shortcut Behavior]
+
+- **Ctrl/Cmd+K**: Toggle shortcut that both opens and closes the modal
+- **/**: Character shortcut that only opens the modal (prevents interference with search typing)
+- **Escape**: Always works to close the modal regardless of Configuration
+
+:::
+
+## `resultsFooterComponent`
+
+> `type: ({ state }, { html }) => JSX.Element | string | Function` | **optional**
+
+The component to display below the search results. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ state }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ state }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the [current state](https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/types/AutocompleteState.ts) which allows you to retrieve the number of hits returned, the query etc.
+
+
+
+
+```js
+docsearch({
+ // ...
+ resultsFooterComponent({ state }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `maxResultsPerGroup`
+
+> `type: number` | **optional**
+
+The maximum number of results to display per search group. Default is 5.
+
+[You can find a working example without JSX in this sandbox](https://codesandbox.io/s/docsearch-v3-maxresultspergroup-without-jsx-ct9m22?file=/src/index.js)
+
+
+
+
+```js
+docsearch({
+ // ...
+ maxResultsPerGroup: 7,
+});
+```
+
+
+
+
+
+## `recentSearchesLimit`
+
+> `type: number` | `default: 7` | **optional**
+
+The maximum number of recent searches that are stored for the user. Default is 7.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesLimit: 12,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `recentSearchesWithFavoritesLimit`
+
+> `type: number` | `default: 4` | **optional**
+
+The maximum number of recent searches that are stored when the user has favorited searches. Default is 4.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesWithFavoritesLimit: 5,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `portalContainer` (React-only)
+
+> `type: Element | DocumentFragment` | `default: document.body` | **optional**
+
+The element where the DocSearch modal will be portaled. Use this when you need the overlay to render in a custom DOM nodeβfor example when working inside a shadow root, a specific layout container, or a modal manager. When omitted, the modal portals to `document.body`.
+
+:::warning
+
+This prop only exists in `@docsearch/react`. If you are using **`@docsearch/js`**, use the [`container`](#container) option insteadβthe value you pass there is both the **mount point** of the search button _and_ the portal target for the modal.
+
+:::
+
+
+
+
+```jsx
+// assume you have a dedicated modal root in your html
+;
+
+const portalEl = document.getElementById('modal-root');
+
+ ;
+```
+
+
+
+
+
+```js
+docsearch({
+ // the element that will **contain the button** and **host the modal portal**
+ container: '#modal-root',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+});
+```
+
+
+
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[6]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[7]: https://www.algolia.com/doc/api-reference/search-api-parameters/
+[8]: https://github.com/algolia/docsearch/blob/main/packages/docsearch-react/src/Hit.tsx
+[9]: https://codesandbox.io/s/docsearch-v3-debounced-search-gnx87
+[10]: https://www.algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/?client=javascript
+[11]: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/keyboard-navigation/
+[12]: https://www.algolia.com/products/ai/agent-studio
+[13]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/composable-api.mdx b/packages/website/versioned_docs/version-v4/composable-api.mdx
new file mode 100644
index 00000000..314b6e1b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/composable-api.mdx
@@ -0,0 +1,315 @@
+---
+title: Composable API
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+The Composable API is available from version `>= 4.3`
+:::
+
+DocSearch has a new Composable API for rendering the DocSearch button and modal. This API was
+introduced to help with more explicit control over where and how the components are rendered within a page.
+
+## Introduction
+
+The Composable API was introduced to help give more flexibility on how you render and use DocSearch on your website. With it,
+you have more control of where, when and how you want to bundle the components and render them.
+
+With Composable API comes two new NPM packages:
+
+- `@docsearch/core` - Shared core logic for managing different states of DocSearch
+- `@docsearch/modal` - The actual components used for the DocSearch Modal
+
+:::warning
+Because of the nature of composability, this API is only available within React, and not within the `@docsearch/js` package.
+:::
+
+## Getting Started
+
+In order to start using the Composable API, you will need to install the following three packages:
+
+
+
+
+```bash
+npm install @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+The most simple implementation would be as follows:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+:::info
+The actual components MUST be rendered within the `` Provider in order for them to communicate with the global state.
+:::
+
+This setup is slightly more involved with now rendering three different components:
+
+- `` is the parent element which controls and shares all state with the child components
+- ` ` is the actual button element that is rendered and triggers the DocSearch Modal to open
+- ` ` is the main modal containing the search form, search results, and Ask AI
+
+
+### Ask AI
+
+Using Ask AI with the Composable API is quite similar to the normal way of using DocSearch. All that is needed is the `askAi` configuration:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+You can find more information on Ask AI, and its setup in its [dedicated docs][2].
+
+### Advanced
+
+```tsx
+export default function AdvancedSearch(): JSX.Element {
+ return (
+
+
+
+
+ );
+}
+```
+
+### Bundle saving exports
+
+To help aid in trimming initial bundle size, the `@docsearch/modal` package exposes explicit file exports as well:
+
+```ts
+import { DocSearchButton } from '@docsearch/modal/button';
+import { DocSearchModal } from '@docsearch/modal/modal';
+```
+
+Here is a basic example of delaying the loading of the `DocSearchModal` code until the search button is clicked:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton } from '@docsearch/modal/button';
+import type { DocSearchModal as DocSearchModalType } from '@docsearch/modal/modal';
+import { useState } from 'react';
+
+let DocSearchModal: typeof DocSearchModalType | null = null;
+
+async function importDocSearchModalIfNeeded() {
+ if (DocSearchModal) {
+ return;
+ }
+
+ const { DocSearchModal: Modal } = await import('@docsearch/modal/modal');
+
+ DocSearchModal = Modal;
+}
+
+export default function DynamicModal() {
+ const [modalLoaded, setModalLoaded] = useState(false);
+
+ const loadModal = () => {
+ importDocSearchModalIfNeeded().then(() => {
+ setModalLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {modalLoaded && DocSearchModal && (
+
+ )}
+
+ );
+}
+```
+
+## Components
+
+### ` `
+
+The ` ` component from the `@docsearch/core` package is the main state handler for all of DocSearch.
+It utilizes [React Context][1] to enable sharing its state across nested components.
+
+#### Props
+
+```ts
+interface DocSearchProps {
+ // React children to be rendered within the DocSearch Provider
+ children: Array | JSX.Element | React.ReactNode | null;
+ // Theme to be set enabling style changes for `light` or `dark` themes
+ theme?: 'light' | 'dark';
+ // Initial starting query for keyword search
+ initialQuery?: string;
+ // Manage supported keyboard shortcuts for opening/closing the DocSearch Modal
+ keyboardShortcuts?: {
+ 'Ctrl/Cmd+K': boolean,
+ '/': boolean,
+ };
+}
+```
+
+### ` `
+
+The main DocSearch search button to trigger the DocSearch Modal.
+
+#### Props
+
+```ts
+interface DocSearchButtonProps {
+ // Optional callback for when the button is clicked. The original click event is passed.
+ onClick?: (event: React.MouseEvent) => void;
+ // Translation strings specific to the button.
+ translations: {
+ buttonText?: string;
+ buttonAriaLabel?: string;
+ };
+}
+```
+
+### ` `
+
+The main keyword search Modal used to search your documentation.
+
+#### Props
+
+```ts
+interface DocSearchModalProps {
+ /**
+ * Algolia application id used by the search client.
+ */
+ appId: string;
+ /**
+ * Public api key with search permissions for the index.
+ */
+ apiKey: string;
+ /**
+ * Name of the algolia index to query.
+ *
+ * @deprecated `indexName` will be removed in a future version. Please use `indices` property going forward.
+ */
+ indexName?: string;
+ /**
+ * List of indices and _optional_ searchParameters to be used for search.
+ *
+ * @see {@link https://docsearch.algolia.com/docs/api#indices}
+ */
+ indices?: Array;
+ /**
+ * Configuration or assistant id to enable ask ai mode. Pass a string assistant id or a full config object.
+ */
+ askAi?: DocSearchAskAi | string;
+ // ...
+}
+```
+
+More property documentation can be found in the [DocSearch API Reference][3] page.
+
+[1]: https://react.dev/reference/react/createContext
+[2]: /docs/v4/v4/askai
+[3]: /docs/api
diff --git a/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
new file mode 100644
index 00000000..cc913ea4
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
@@ -0,0 +1,96 @@
+---
+title: New Crawler UI/UX
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+The Algolia Crawler Visual UI provides an updated, user-friendly way to manage your crawl settings and monitor your indexing process. This guide covers the main features of the new interface.
+
+## DocSearch Tab
+
+The Crawler UI now includes a dedicated **DocSearch** tab. This tab provides everything you need to implement DocSearch on your site, including:
+
+- **Implementation code**: Copy-paste ready code snippets for integrating DocSearch into your frontend.
+- **API keys**: Your unique Application ID and Search API Key for connecting to your Algolia index.
+- **Quick links**: Access to review your records, explore documentation, and join the support Discord.
+
+
+
+
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `Monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+You can update your crawler configuration in two ways:
+
+**Visual Configuration UI:**
+Quickly edit common options without writing code using the new Visual Configuration interface.
+
+
+
+
+
+**Code Editor:**
+For advanced configuration, use the live code editor to directly modify your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to debug selectors or see how the crawler interprets your site.
+
+
+
+
+
+## Suggestions
+
+The **Suggestions** section in the Crawler UI provides actionable feedback to help you improve your crawl and data extraction. After each crawl, you'll see recommendations for:
+
+- Fixing redirect or domain issues
+- Addressing ignored or failed URLs
+- Adding missing sitemaps
+
+Each suggestion includes a description, a solution, and quick links to relevant documentation or monitoring tools, so you can resolve issues efficiently and optimize your search experience.
+
+
+
+
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/crawler.mdx b/packages/website/versioned_docs/version-v4/crawler.mdx
new file mode 100644
index 00000000..f2e4b3f9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler.mdx
@@ -0,0 +1,120 @@
+---
+title: DocSearch x Algolia Crawler
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][3] team know.
+
+You can also read our [Crawler FAQ](https://www.algolia.com/doc/tools/crawler/troubleshooting/crawl-status/), to understand how it behaves:
+
+- [One of my pages wasn't crawled](https://www.algolia.com/doc/tools/crawler/troubleshooting/extraction-issues/#a-page-wasnt-crawled)
+- [Why are my pages skipped?](https://www.algolia.com/doc/tools/crawler/troubleshooting/fetching-issues/)
+
+For questions related to the DocSearch program, please see our [DocSearch program FAQ](/docs/docsearch-program).
+
+## How often will you crawl my website?
+
+Crawls are scheduled at a random time once a week. You can [configure this schedule from the config file](https://www.algolia.com/doc/tools/crawler/apis/configuration/schedule/) or trigger one manually from [the Crawler interface][2].
+
+## Why do I have duplicate content in my results?
+
+This can happen when you have more than one URL pointing to the same content, for example with `./docs`, `./docs/` and `./docs/index.html`.
+
+We recommend configuring canonical URLs on your website, you can read more on the ["Consolidate duplicate URLs" guide by Google](https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls).
+
+Ultimately, it is possible to set the [`exclusionPatterns`](https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/) to all the patterns you want to exclude.
+
+## Are the [`docsearch-scraper`](https://github.com/algolia/docsearch-scraper) and [`docsearch-configs`](https://github.com/algolia/docsearch-configs) repository still maintained?
+
+We've deprecated our legacy infrastructure, but you can still use it to [run your own instance](/docs/legacy/run-your-own) and plug it to [DocSearch v3](/docs/v3/docsearch)!
+
+## How to migrate
+
+> Every owner should have received a migration email from Algolia with the details. If you were not part of the previous `index` owners, or the maintainer has changed, you can request access via [our support page](https://www.algolia.com/support/).
+
+All the steps are detailed in the email you've received, but in order to use the new infrastructure you need to:
+
+- Join the Algolia application with the invite included in the email
+- Update your frontend integration with the credentials received in the email.
+
+
+
+
+```js app.js
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_NEW_ALGOLIA_APP_ID',
+ apiKey: 'YOUR_NEW_ALGOLIA_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME', // it does not change
+});
+```
+
+
+
+
+
+```jsx App.js
+
+```
+
+
+
+
+
+## What should I do with my legacy config and credentials?
+
+You can forget about them, we will do the cleaning once all of our users have migrated to the new infrastructure!
+
+You should use [the dedicated web interface][2] to make any changes to your index.
+
+## Why do I see two Algolia apps in my dashboard?
+
+We did not remove access to the legacy DocSearch application (`BH4D9OD16A`) to give you the time to get familiar with our new infrastructure. `BH4D9OD16A` will remain available until the migration has been completed for all the DocSearch users.
+
+## Search yields no results
+
+If your search does not yield any results, but there is no error in [your browser developer tools](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), there might be an issue with your index.
+
+Make sure that:
+
+1. [Your Crawler config](/docs/record-extractor) matches your website structure
+
+We provide [config templates](/docs/templates) for many website generators, but you can also use them as a base. To debug your selectors, we recommend using [the URL tester](/docs/manage-your-crawls/#url-tester).
+
+2. Your index settings are up to date (you'll see a banner in [the search preview](/docs/manage-your-crawls/#search-preview) if not)
+
+The Crawler only applies `index settings` at index creation time, to keep the Algolia dashboard as the source of truth. If you have drastically changed your config, or moved to a website generator, we recommend you to delete your index from the Algolia dashboard before starting a new crawl.
+
+## Can I delete my crawler?
+
+No. Well, you can but once you do things will not work correctly. We automatically create a default crawler that is associated with your DocSearch application and deleting it with the intention of creating a new one will not work as expected.
+
+## What if I delete my DocSearch Crawler?
+
+The fastest way will be to connect with us on our [Discord](https://alg.li/discord). Alternatively, email us at the address below and we will get to it as soon as we can.
+
+## Can I use the Crawler on password protected sites?
+
+The Crawler as used with DocSearch applications cannot be used for password protected sites that require a login. If you need this functionality, you need to utilize a regular Algolia plan https://www.algolia.com/pricing and add a crawler to it. Note that while it is free to add a pay-as-you-go crawler, the free tier does have limitations.
+
+## Links related to the migration
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+[1]: https://alg.li/discord
+[2]: https://dashboard.algolia.com/crawler
+[3]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/create-crawler.mdx b/packages/website/versioned_docs/version-v4/create-crawler.mdx
new file mode 100644
index 00000000..5e7c5124
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/create-crawler.mdx
@@ -0,0 +1,78 @@
+---
+title: Create a New Crawler
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+# Create a New Crawler
+
+:::info
+New DocSearch apps created after **July 2nd, 2024** can now use the Algolia Crawler UI to set up and manage their crawls. This guide walks you through the process of adding your domain, verifying ownership, creating a crawler, and running your first test crawl. You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+
+If you signed up before July 2nd, 2024, you can still use the Crawler UI, but creating and managing a Crawler is more streamlined for users who joined after that date.
+
+Learn more about the [New Crawler UI/UX features](./crawler-configuration-visual).
+:::
+
+## Add domains
+
+1. Sign in to the [Algolia dashboard](https://dashboard.algolia.com/crawler).
+2. In the left sidebar, select **Data sources**.
+3. Select **Crawler**:
+ - Click **Add your domain** and enter the domains or subdomains you want to crawl (e.g., `example.com`, `www.example.com`).
+ - If youβve already added a domain, click the **Domains** tab.
+4. Click **Add domain**.
+
+
+
+
+
+> **Note:** You must verify your domain within a 7-day grace period after adding it. Additionally, your domain must be approved for use by the DocSearch team before you can proceed with crawling.
+
+## Verify your domain
+
+You must verify ownership of each domain you want to crawl. The default method is email verification, but you can also use a meta tag, HTML file, robots.txt, or DNS record.
+
+### Meta tag
+1. In the **Meta tag** tab, click **Copy** to copy the verification tag.
+2. Add the tag to your site's `` section.
+3. Publish your site and click **Verify now** in the Crawler dashboard.
+
+### HTML file
+1. In the **HTML file** tab, click **Copy** to copy the verification file content.
+2. Save it as a new HTML file and upload it to your web server.
+3. Add the fileβs URL in the dashboard and click **Verify now**.
+
+### robots.txt
+1. In the **Robots.txt** tab, click **Copy** to copy the verification code.
+2. Paste it into your site's `robots.txt` file.
+3. Publish and click **Verify now**.
+
+### DNS
+1. In the **DNS** tab, copy the provided DNS TXT record.
+2. Add it to your DNS providerβs settings.
+3. Click **Verify now** after the record propagates (may take up to 72 hours).
+
+## Create a new crawler
+
+Once your domain is verified and approved by our DocSearch team:
+1. Go to the **Crawler** page in the dashboard.
+2. Click **New Crawler** and fill in:
+ - **Crawler name** (descriptive)
+ - **App ID** (your Algolia application ID)
+ - **Start URL** (usually your home page)
+ - **Crawler template** (choose a template or default)
+3. Click **Create** to finish and run a test crawl.
+
+## Run the test crawl
+
+The initial crawl will visit up to 100 URLs to test access and extraction. You can monitor progress in the **Overview** page. After completion, review the extracted records in the Algolia dashboard.
+
+## Next steps
+
+- Edit your crawler configuration for scheduled crawls, inclusion/exclusion rules, and extraction settings.
+- Use the Crawlerβs suggestions for further optimization.
+- For more details, see the [official Algolia documentation](https://www.algolia.com/doc/tools/crawler/getting-started/create-crawler/).
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/docsearch-program.md b/packages/website/versioned_docs/version-v4/docsearch-program.md
new file mode 100644
index 00000000..29d65ae2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch-program.md
@@ -0,0 +1,131 @@
+---
+title: DocSearch program
+---
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][4] team know.
+
+For questions related to the DocSearch x Algolia Crawler, please see our [Crawler FAQ](/docs/crawler).
+
+## What do I need to install on my side?
+
+You just need to [implement DocSearch in your frontend](/docs/docsearch) with the credentials received by email when your application has been deployed.
+
+DocSearch leverages the [Algolia Crawler](https://www.algolia.com/products/search-and-discovery/crawler/), which offers a web [interface](https://dashboard.algolia.com/crawler) to create, monitor, edit, start your Crawlers. If you have any questions regarding it, please see our [Crawler FAQ](/docs/crawler).
+
+## How much does it cost?
+
+It's free!
+
+We know that paying for search infrastructure is a cost not all open source projects can afford. That's why we decided to keep DocSearch free for everyone. All we ask in exchange is that you keep the "Search by [Algolia][2]" logo displayed next to the search results.
+
+If this is not possible for you, you're free to [open your own Algolia account](https://www.algolia.com/pricing) and run [DocSearch on your own][3] without this limitation. In that case, though, depending on the size of your documentation, you might need a paid account (free accounts can hold as much as 10k records).
+
+## What data are you collecting?
+
+We save the data we extract from your website markup, which we put in a custom JSON format instead of HTML. This is the data we put in the Algolia DocSearch index. The selectors in your config define what data to scrape.
+
+As the website owner, we also give you access to your own Algolia application. This will let you see how your website is indexed in Algolia, detailed analytics about the anonymized searches in your website, team managements, and more!
+
+## Where is my data hosted?
+
+We host the DocSearch data on Algolia's servers, with replications around the globe. You can find more details about the actual [server specs here](https://www.algolia.com/doc/guides/infrastructure/servers/), and more complete information in our [privacy policy](https://www.algolia.com/policies/privacy).
+
+## How do I upgrade my DocSearch app?
+
+Depending on what you are looking for you have a few options!
+
+### Upgrade #1: I want a specific feature, like Rules, added to my existing DocSearch application
+
+[Reach out to us](https://algolia.com/support) and we may be able to help!
+
+### Upgrade #2: I want to remove the Algolia logo
+
+This would disqualify you from the free DocSearch program. We do offer an open-source
+[legacy version](https://docsearch.algolia.com/docs/legacy/run-your-own) of the DocSearch Crawler that you can use and
+host yourself or you can use our [API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript) but you will need to use a new Algolia application and pay for its usage.
+
+### Upgrade #3: Algolia is awesome, I want to use it for my whole site
+
+That's awesome! Please reach out to our [sales team](https://www.algolia.com/contactus/)
+who can help you figure out the right plan for you. Once you have your new application
+created you can simply copy and paste [your Crawler config](https://docsearch.algolia.com/docs/templates) into your new application's
+Crawler.
+
+## Can I use DocSearch on non-doc pages?
+
+The free DocSearch we provide will **only** crawl open-source projects documentation pages or technical blogs. To use it on other parts of your website, you'll need to create your own Algolia account and either:
+
+- Run the [DocSearch crawler][3] on your own
+- Use one of our other [framework integrations or API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript)
+
+## Can you index code samples?
+
+Yes, but we do not recommend it.
+
+Code samples are a great way for humans to understand how people use a specific method. It often requires boilerplate code though, repeated across examples, which adds noise to the results.
+
+## A documentation website I like does not use DocSearch. What can I do?
+
+We'd love to help!
+
+If one of your favorite tool documentation websites is missing DocSearch, we encourage you to file an issue in their repository explaining how DocSearch could help. Feel free to [let us know on Discord][1] as well and we'll provide all the help we can.
+
+## How did we build this website?
+
+We build this website with [Docusaurus v2](https://docusaurus.io/). We were helped by a great man who inspired us a lot, Endi. We want [to pay a tribute to this exceptional human being that will be always part of the DocSearch project](https://docusaurus.io/blog/2020/01/07/tribute-to-endi). Rest in peace mate!
+
+## Can I share the `apiKey` in my repo?
+
+The `apiKey` the DocSearch team provides is [a search-only key](https://www.algolia.com/doc/guides/security/api-keys/#search-only-api-key) and can be safely shared publicly. You can track it in your version control system (e.g. git). If you are running the scraper on your own, please make sure to create a search-only key and [do not share your Admin key](https://www.algolia.com/doc/guides/security/api-keys/#admin-api-key).
+
+## Why is the email API key different in the dashboard?
+
+Every Algolia app comes with a default "Search API Key" which can be seen in the dashboard. That key allow you to list indices, settings, and search on **every** index owned by your application. In the case of a DocSearch application, in your acceptance email we provide a search **ONLY** API key scoped to only your DocSearch index. If for any reason you need to recover the API key sent in the email, just connect with our [support](https://algolia.com/support) team.
+
+## How do I rotate my API keys?
+
+Please reach out to our [support](https://algolia.com/support) team.
+
+## Can I have multiple projects under the same Algolia application?
+
+We recommend having a single Algolia application per project. Please [apply](https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply) if you'd like to use DocSearch in an other project of yours.
+
+### Why?
+
+The information of the initially applied project is used everywhere when we deploy your app:
+
+- The scope of your API keys
+- The name of your Algolia application/Crawler
+- The indices we generate
+- The allowed domains of your Crawler
+
+This allows us to easily scope issues when reaching out for support.
+
+## Support
+
+:::caution
+
+Please make sure to **first read the documentation before reaching out**.
+
+Here are some links to help you:
+
+- [The Algolia Crawler documentation](https://www.algolia.com/doc/tools/crawler/getting-started/overview/)
+- [The Algolia Crawler FAQ](/docs/crawler)
+- [The DocSearch FAQ](/docs/docsearch-program)
+- [The Algolia documentation](https://www.algolia.com/doc/)
+
+You can also take a look at [the Algolia academy](https://academy.algolia.com/trainings) to understand more about Algolia.
+
+:::
+
+Please be informed that while Algolia does not provide support for DocSearch itself, we can support requests for the following products:
+
+- The Algolia Crawler, reach out [via the support page](https://algolia.com/support).
+- The Algolia Dashboard, reach out [via the support page](https://algolia.com/support).
+
+For any issue related to [the DocSearch UI library](https://github.com/algolia/docsearch), please open a [GitHub issue](https://github.com/algolia/docsearch/issues).
+
+[1]: https://alg.li/discord
+[2]: https://www.algolia.com/
+[3]: /docs/legacy/run-your-own
+[4]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/docsearch.mdx b/packages/website/versioned_docs/version-v4/docsearch.mdx
new file mode 100644
index 00000000..9c17704f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch.mdx
@@ -0,0 +1,418 @@
+---
+title: Getting Started with v4
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+DocSearch v4 provides a significant upgrade over previous versions, offering enhanced accessibility, responsiveness, and an improved search experience for your documentation. Built on [Algolia Autocomplete][1], DocSearch v4 ensures a seamless integration trusted by leading documentation sites worldwide.
+
+## Installation
+
+> Looking for the Composable API documentation? You can find it [here][17].
+
+DocSearch packages are available on the [npm registry][10].
+
+### Docusaurus users
+
+If your docs site is powered by Docusaurus, use [`@docsearch/docusaurus-adapter`](/docs/docusaurus-adapter) for the latest DocSearch features (including new Ask AI capabilities such as sidepanel support), while keeping `@docusaurus/preset-classic`.
+
+
+
+
+```bash
+yarn add @docsearch/js@4
+# or with npm
+npm install @docsearch/js@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+```bash
+yarn add @docsearch/react@4
+# or
+npm install @docsearch/react@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``:
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+
+### Optimize first query performance
+
+Enhance your users' first search experience by using `preconnect`, see [Performance optimization](#preconnect) below
+
+## Implementation
+
+
+
+
+DocSearch requires a dedicated container in your HTML
+
+```html
+
+```
+
+Initialize DocSearch by passing your container:
+
+```js app.js
+import docsearch from '@docsearch/js';
+
+import '@docsearch/css';
+
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+});
+```
+
+DocSearch generates an accessible, fully-functional search input for you automatically.
+
+
+
+
+
+Integrating DocSearch into your React app is straightforward:
+
+```jsx App.js
+import { DocSearch } from '@docsearch/react';
+
+import '@docsearch/css';
+
+function App() {
+ return (
+
+ );
+}
+
+export default App;
+```
+
+DocSearch generates a fully accessible search input out-of-the-box.
+
+
+
+
+
+### Quick Testing (without credentials)
+
+If you'd like to test DocSearch immediately without your own credentials, use our demo configuration:
+
+
+
+
+```js
+docsearch({
+ appId: 'PMZUYBQDAK',
+ apiKey: '24b09689d5b4223813d9b8e48563c8f6',
+ indexName: 'docsearch',
+ askAi: 'askAIDemo',
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+Or use our new dedicated [DocSearch Playground](https://community.algolia.com/docsearch-playground/)
+
+### Using DocSearch with Ask AI
+
+DocSearch v4 introduces support for Ask AI, Algolia's advanced, AI-powered search capability. Ask AI enhances the user experience by providing contextually relevant and intelligent responses directly from your documentation. You can also use the same `askAi` configuration object to route chat through Agent Studio.
+
+To enable Ask AI, you can add your Algolia Assistant ID as a string, or use an object for more advanced configuration (such as specifying a different index, credentials, search parameters, or enabling Agent Studio):
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+});
+```
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ indexName: 'YOUR_MARKDOWN_INDEX', // Optional: use a different index for Ask AI
+ apiKey: 'YOUR_SEARCH_API_KEY', // Optional: use a different API key for Ask AI
+ appId: 'YOUR_APP_ID', // Optional: use a different App ID for Ask AI
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'], // Optional: filter Ask AI context
+ },
+ suggestedQuestions: true // Optional: enable loading suggested questions on the Ask AI new conversation screen
+ },
+});
+```
+
+
+
+
+- Use the string form for a simple setup.
+- Use the object form to customize which index, credentials, or filters Ask AI uses.
+- The suggested questions feature is controlled on the [Dashboard](https://dashboard.algolia.com) in the Ask AI section.
+
+### Using Agent Studio with DocSearch
+
+To use [Algolia Agent Studio](https://www.algolia.com/doc/guides/algolia-ai/agent-studio) as the chat backend, set `agentStudio: true` inside the `askAi` object.
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+- `agentStudio` is configured inside `askAi`, not as a top-level DocSearch prop.
+- When `agentStudio: true`, `searchParameters` must be keyed by index name.
+- Agent Studio search parameters support `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+### Filtering search results
+
+#### Keyword search
+
+If your website uses [DocSearch meta tags][13] or if you've added [custom variables to your config][14], you'll be able to use the [`facetFilters`][16] option to scope your search results to a [`facet`][15]
+
+This is useful to limit the scope of the search to one language or one version.
+
+
+
+
+```js
+docsearch({
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+#### Ask AI
+
+Filtering also applies when using Ask AI. This is useful to limit the scope of the LLM's search to only relevant results.
+
+:::info
+We recommend using the `facetFilters` option when using Ask AI with multiple languages or any multi-faceted index.
+:::
+
+
+
+```js
+docsearch({
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+ },
+});
+```
+
+
+
+```jsx
+
+```
+
+
+
+
+:::tip
+You can use `facetFilters: ['type:content']` to ensure Ask AI only uses records where the `type` attribute is `content` (i.e., only records that actually have content). This is useful if your index contains records for navigation, metadata, or other non-content types.
+:::
+
+### Sending events
+
+You can send search events to your DocSearch index by passing in the `insights` parameter when creating your DocSearch instance.
+
+
+
+
+```diff
+docsearch({
+ // other options
++ insights: true,
+});
+```
+
+
+
+
+
+```diff
+
+```
+
+
+
+
+
+## Performance optimization
+
+### Preconnect
+
+Improve the loading speed of your initial search request by adding this snippet into your website's `` section:
+
+```html
+
+```
+
+This helps the browser establish a quick connection with Algolia, enhancing user experience, especially on mobile devices.
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/integrations
+[6]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[7]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[8]: https://codesandbox.io/s/docsearch-js-v3-playground-z9oxj
+[9]: https://codesandbox.io/s/docsearch-react-v3-playground-619yg
+[10]: https://www.npmjs.com/
+[11]: /docs/api#container
+[12]: /docs/api
+[13]: /docs/required-configuration#introduce-global-information-as-meta-tags
+[14]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: https://www.algolia.com/doc/guides/managing-results/refine-results/filtering/#facetfilters
+[17]: /docs/composable-api
diff --git a/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
new file mode 100644
index 00000000..4ae81493
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
@@ -0,0 +1,61 @@
+---
+title: Docusaurus Adapter (Recommended)
+---
+
+If you use Docusaurus, install and configure `@docsearch/docusaurus-adapter` to get the latest DocSearch features on your current Docusaurus version.
+
+## Why this adapter exists
+
+Docusaurus ships an excellent built-in Algolia integration (`@docusaurus/theme-search-algolia`), but Docusaurus (Meta-maintained) and DocSearch don't always release on the same cadence.
+
+The DocSearch adapter lets us ship new DocSearch features (including Ask AI sidepanel support) without forcing users to wait for a Docusaurus integration update.
+
+In practice, this means:
+
+- Faster access to new DocSearch capabilities.
+- Better compatibility for Ask AI + sidepanel features.
+- A dedicated search integration path maintained in the DocSearch project.
+
+## Install
+
+```bash
+yarn add @docsearch/docusaurus-adapter
+# or
+npm install @docsearch/docusaurus-adapter
+```
+
+## Configuration
+
+Keep `@docusaurus/preset-classic`, add the adapter plugin, and configure search under `themeConfig.docsearch` (preferred):
+
+```js title="docusaurus.config.mjs"
+export default {
+ plugins: ['@docsearch/docusaurus-adapter'],
+ themeConfig: {
+ docsearch: {
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+ askAi: {
+ assistantId: 'YOUR_ASSISTANT_ID',
+ sidePanel: true,
+ },
+ contextualSearch: true,
+ },
+ },
+};
+```
+
+## `docsearch` vs `algolia` keys
+
+- `themeConfig.docsearch` is the canonical key.
+- `themeConfig.algolia` is supported as a backward-compatible alias.
+- Do not define both keys at the same time.
+
+Using `themeConfig.docsearch` helps avoid built-in Docusaurus search-theme validation conflicts when you want newer DocSearch options like `askAi.sidePanel`.
+
+## Customizing Search UI (SearchBar/SearchPage)
+
+If you want to customize search behavior or UI, customize the adapter theme components (`@theme/SearchBar` and `@theme/SearchPage`) from the adapter integration path.
+
+This keeps your customization aligned with DocSearch feature updates and avoids coupling to the built-in Docusaurus Algolia theme implementation.
diff --git a/packages/website/versioned_docs/version-v4/examples.mdx b/packages/website/versioned_docs/version-v4/examples.mdx
new file mode 100644
index 00000000..6241cd50
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/examples.mdx
@@ -0,0 +1,428 @@
+---
+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.
diff --git a/packages/website/versioned_docs/version-v4/how-does-it-work.mdx b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
new file mode 100644
index 00000000..3cc42427
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
@@ -0,0 +1,51 @@
+---
+title: How does it work?
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+Getting up and ready with DocSearch is a straightforward process that requires three steps: you apply, we configure the crawler and the Algolia app for you, and you integrate our UI in your frontend. You only need to copy and paste a JavaScript snippet.
+
+
+
+## You apply
+
+The first thing you'll need to do is to apply for DocSearch by [filling out the form on this page][1] (double check first that [you qualify][2]). We are receiving a lot of requests, so this form makes sure we won't be forgetting anyone.
+
+We guarantee that we will answer every request, but as we receive a lot of applications, please give us a couple of days to get back to you :)
+
+## We create your Algolia application and a dedicated crawler
+
+Once we receive [your application][1], we'll have a look at your website, create an Algolia application and a dedicated [crawler][5] for it. Your crawler comes with [a configuration file][6] which defines which URLs we should crawl or ignore, as well as the specific CSS selectors to use for selecting headers, subheaders, etc.
+
+This step still requires some manual work and human brain, but thanks to the +4,000 configs we already created, we're able to automate most of it. Once this creation finishes, we'll run a first indexing of your website and have it run automatically at a random time of the week.
+
+**With the Crawler, comes [a dedicated interface][8] for you to:**
+
+- Start, schedule and monitor your crawls
+- Edit and test your config file directly with [DocSearch v3][7]
+
+**With the Algolia application comes access to the dashboard for you to:**
+
+- Browse your index and see how your content is indexed
+- Various analytics to understand how your search performs and ensure that your users are able to find what theyβre searching for
+- Trials for other Algolia features
+- Team management
+
+## You update your website
+
+We'll then get back to you with the JavaScript snippet you'll need to add to your website. This will bind your [DocSearch component][7] to display results from your Algolia index on each keystroke in a pop-up modal.
+
+Now that DocSearch is set, you don't have anything else to do. We'll keep crawling your website and update your search results automatically. All we ask is that you keep the "Search by Algolia" logo next to your search results.
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: /docs/who-can-apply
+[3]: https://github.com/algolia/docsearch-configs/tree/master/configs
+[4]: /docs/styling
+[5]: https://www.algolia.com/products/search-and-discovery/crawler/
+[6]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[7]: /docs/v3/docsearch
+[8]: https://crawler.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/integrations.md b/packages/website/versioned_docs/version-v4/integrations.md
new file mode 100644
index 00000000..59806313
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/integrations.md
@@ -0,0 +1,45 @@
+---
+title: Supported Integrations
+---
+
+We worked with **documentation website generators** to have DocSearch directly embedded as a first class citizen in the websites they produce.
+
+## Our great integrations
+
+So, if you're using one of the following tools, check out their documentation to see how to enable DocSearch on your website:
+
+- [Docusaurus v1][1] - [How to enable search][2]
+- [Docusaurus v2 & v3][3] - [DocSearch adapter (recommended)][23] / [Using Algolia DocSearch][4]
+- [VuePress][5] - [Algolia Search][6]
+- [VitePress][21] - [Search][22]
+- [Starlight][7] - [Algolia Search][8]
+- [LaRecipe][9] - [Algolia Search][10]
+- [Orchid][11] - [Algolia Search][12]
+- [Smooth DOC][13] - [DocSearch][14]
+- [Docsy][15] - [Configure Algolia DocSearch][16]
+- [Lotus Docs][19] - [Enabling the DocSearch Plugin][20]
+- [Sphinx](https://www.sphinx-doc.org/en/master/) - [Algolia DocSearch for Sphinx](https://sphinx-docsearch.readthedocs.io/)
+
+If you're maintaining a similar tool and want us to add you to the list, [feel free to make a pull request](https://github.com/algolia/docsearch/edit/main/packages/website/docs/integrations.md) and [contribute to Code Exchange](https://www.algolia.com/developers/code-exchange/contribute/). We're happy to help.
+
+[1]: https://v1.docusaurus.io/
+[2]: https://v1.docusaurus.io/docs/en/search
+[3]: https://docusaurus.io/
+[4]: https://docusaurus.io/docs/search#using-algolia-docsearch
+[5]: https://vuepress.vuejs.org/
+[6]: https://vuepress.vuejs.org/theme/default-theme-config.html#algolia-search
+[7]: https://starlight.astro.build/
+[8]: https://starlight.astro.build/guides/site-search/#algolia-docsearch
+[9]: https://larecipe.saleem.dev/docs/2.2/overview
+[10]: https://larecipe.saleem.dev/docs/2.2/search#available-engines
+[11]: https://orchid.run
+[12]: https://orchid.run/plugins/orchidsearch#algolia-docsearch
+[13]: https://next-smooth-doc.vercel.app/
+[14]: https://next-smooth-doc.vercel.app/docs/docsearch/
+[15]: https://www.docsy.dev/
+[16]: https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch
+[19]: https://lotusdocs.dev/docs/
+[20]: https://lotusdocs.dev/docs/guides/features/docsearch/#enabling-the-docsearch-plugin
+[21]: https://vitepress.dev/
+[22]: https://vitepress.dev/reference/default-theme-search#algolia-search
+[23]: /docs/docusaurus-adapter
diff --git a/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
new file mode 100644
index 00000000..3dbf5caa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
@@ -0,0 +1,67 @@
+---
+title: "[Pre-v4] Manage your crawls"
+---
+
+:::caution
+This UI is deprecated and no longer maintained. For the latest instructions, please use the new documentation: [Crawler Configuration Visual UI](./crawler-configuration-visual). You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+:::
+
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+DocSearch comes with the [Algolia Crawler web interface](https://crawler.algolia.com/) that allows you to configure how and when your Algolia index will be populated.
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+The live editor allows you to update your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## Search preview
+
+From the [`editor`](#update-your-config), you have access to a `Search preview` tab to browse search results with [`DocSearch v3`](/docs/v3/docsearch).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to [debug selectors](https://www.algolia.com/doc/tools/crawler/getting-started/crawler-configuration/#debugging-selectors) or how we crawl your website.
+
+
+
+
diff --git a/packages/website/versioned_docs/version-v4/mcp/installation.mdx b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
new file mode 100644
index 00000000..300b20c2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
@@ -0,0 +1,32 @@
+---
+title: Install DocSearch MCP
+sidebar_label: Installation
+---
+
+import MCPInstall from '@site/src/components/mcp/MCPInstall';
+
+DocSearch MCP is a remote MCP server. Point any MCP-compatible client at this endpoint β no authentication required:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+The fastest path is the **DocSearch CLI** β one command that configures your client for you. Prefer to set things up yourself? Install it as a **plugin** (ships the MCP server plus client guidance like rules, skills, and commands) or **manually** (just the MCP server config). Pick your client below.
+
+
+
+## Verify the install
+
+Ask your MCP client a public documentation question, for example:
+
+```text
+Use DocSearch MCP to find the current Next.js middleware matcher docs.
+```
+
+The client should call the DocSearch tools and answer with content from the matching documentation, ideally with source links.
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/overview.mdx b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
new file mode 100644
index 00000000..1d3aeae5
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: DocSearch MCP
+sidebar_label: Overview
+---
+
+DocSearch MCP lets AI clients search current public developer documentation from the DocSearch corpus.
+
+Use it when you want an assistant to answer questions from public docs instead of relying only on model training data. The public endpoint does not require authentication:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+## What it does
+
+DocSearch MCP exposes documentation search through the [Model Context Protocol](https://modelcontextprotocol.io/). MCP-compatible clients connect to the endpoint and call DocSearch tools while answering your questions.
+
+The endpoint is focused on public developer documentation. You do not need an Algolia application ID, search API key, or DocSearch application to use it.
+
+## How it works
+
+Most lookups are a single call: name the product and ask your question, and DocSearch finds the right documentation set and returns the matching content together.
+
+When a question spans several products, or you want to inspect and hand-pick documentation sets first, there is a two-step flow: resolve the documentation sets, then query the ones you choose.
+
+## Available tools
+
+### `algolia_docsearch_search_docs`
+
+The one-shot tool, and the right default for most lookups. Give it a `library` (the product, SDK, or platform) and a `query` (your question); it resolves the best matching documentation set and returns ranked content in a single call. If the library is ambiguous, it returns candidate documentation sets to choose from instead.
+
+### `algolia_docsearch_resolve_docset`
+
+Step 1 of the manual flow. Finds the documentation sets that best match a product, library, or platform and returns candidates β each with a `docset_id`, title, description, and ranking signals to help pick the best match.
+
+### `algolia_docsearch_query_docs`
+
+Step 2 of the manual flow. Retrieves documentation content for one or more `docset_id`s returned by `algolia_docsearch_resolve_docset`. Pass several at once when a question spans multiple products.
+
+## Next steps
+
+- [Install DocSearch MCP](/docs/mcp/installation)
+- [Use DocSearch MCP](/docs/mcp/usage)
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/usage.mdx b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
new file mode 100644
index 00000000..fb7b8a9b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
@@ -0,0 +1,113 @@
+---
+title: Use DocSearch MCP
+sidebar_label: Usage
+---
+
+DocSearch MCP works best when your client knows to search public documentation before answering library, framework, API, or SDK questions.
+
+## Ask documentation questions
+
+After installation, ask your client about public developer docs in natural language:
+
+```text
+How do I configure middleware matchers in Next.js?
+```
+
+```text
+Show me the current Stripe webhook signature verification docs.
+```
+
+```text
+What is the current setup for Algolia InstantSearch React?
+```
+
+If your client does not automatically use MCP tools, mention DocSearch MCP explicitly:
+
+```text
+Use DocSearch MCP to look up React Server Components data fetching.
+```
+
+## Use the Claude Code command
+
+The Claude Code plugin includes a manual command:
+
+```text
+/algolia-docsearch:docs [topic]
+```
+
+Examples:
+
+```text
+/algolia-docsearch:docs Next.js middleware matcher
+/algolia-docsearch:docs Stripe webhook signature verification
+/algolia-docsearch:docs Algolia InstantSearch React configure search client
+```
+
+## Tool flow
+
+DocSearch MCP exposes three tools. Most of the time the client only needs the one-shot tool; the two-step flow is for multi-product questions or when you want to hand-pick documentation sets.
+
+You can ask in natural language β full sentences and questions work well. For the one-shot tool, keep `library` to the product name and put the actual question in `query`.
+
+### One-shot: `algolia_docsearch_search_docs`
+
+The client names the product and asks the question in a single call:
+
+```json
+{
+ "library": "Next.js",
+ "query": "how do middleware matchers work"
+}
+```
+
+It returns ranked documentation content for the best matching set. If the library is ambiguous, it returns candidate documentation sets instead so the client can pick one and fall back to `algolia_docsearch_query_docs`.
+
+### Two-step: resolve, then query
+
+For questions that span several products, or when the client wants to choose documentation sets explicitly:
+
+1. `algolia_docsearch_resolve_docset` finds documentation sets:
+
+```json
+{
+ "query": "Next.js app router"
+}
+```
+
+It returns candidates, each with a `docset_id`.
+
+2. `algolia_docsearch_query_docs` retrieves content for the chosen `docset_id`(s):
+
+```json
+{
+ "query": "middleware matcher config",
+ "docsetIds": ["nextjs"]
+}
+```
+
+Pass multiple `docsetIds` when a question spans more than one product.
+
+## Tips
+
+- Be specific about the product and topic you want.
+- Include a version when it matters.
+- Ask for source URLs if you want the client to show where the answer came from.
+- If the first result is too broad, ask for a narrower topic.
+
+## Troubleshooting
+
+### The client does not call DocSearch MCP
+
+Make sure the MCP server is enabled in your client and named `algolia-docsearch`. If you installed the plugin, check that the plugin is enabled too.
+
+### The result is about the wrong product
+
+Ask again with the official product name. For the one-shot tool, set `library` to the vendor's product name (for example, `Algolia InstantSearch` rather than `search`).
+
+### The client cannot connect
+
+Confirm that your client supports remote HTTP MCP servers and that the configured URL is:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
diff --git a/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
new file mode 100644
index 00000000..e8edf61e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
@@ -0,0 +1,87 @@
+---
+title: Migrating from the legacy scraper
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+With the new version of the [DocSearch UI][1], we wanted to go further and provide better tooling for you to create and maintain your config file, and some extra Algolia features that you all have been requesting for a long time!
+
+## What's new?
+
+### Scraper
+
+The DocSearch infrastructure now leverages the [Algolia Crawler][2]. We've teamed up with our friends and created a new [DocSearch helper][4], that extracts records as we were previously doing with our beloved [DocSearch scraper][3]!
+
+The best part is that you no longer need to install any tooling on your side if you want to maintain or update your index!
+
+We now provide a web interface **[legacy][7]** or **[new](https://dashboard.algolia.com/crawler)** that will allow you to:
+
+- Start, schedule and monitor your crawls
+- Edit your config file from our live editor
+- Test your results directly with [DocSearch v3][1] or [DocSearch v4][32]
+
+### Algolia application and credentials
+
+We've received a lot of requests asking for:
+
+- A way to manage team members
+- Browse and see how Algolia records are indexed
+- See and subscribe to other Algolia features
+
+They are now all available, in **your own Algolia application**, for free :D
+
+## FAQ
+
+You can find answers related to the DocSearch migration in our [Crawler FAQ page](/docs/crawler).
+
+### Useful links
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+## Config file key mapping
+
+Below are the keys that can be found in the [`legacy` DocSearch configs][14] and their translation to an [Algolia Crawler config][16]. For more detailed information on the Algolia Crawler, see [the official documentation][15].
+
+| `legacy` | `current` | description |
+| --- | --- | --- |
+| `start_urls` | [`startUrls`][20] | Now accepts URLs only, see [`helpers.docsearch`][30] to handle custom variables |
+| `page_rank` | [`pageRank`][31] | Can be added to the `recordProps` in [`helpers.docsearch`][30], should be passed as a **string** |
+| `js_render` | [`renderJavaScript`][21] | Unchanged |
+| `js_wait` | [`renderJavascript.waitTime`][22] | See documentation of [`renderJavaScript`][21] |
+| `index_name` | **removed**, see [`actions`][23] | Handled directly in the [`actions`][23] |
+| `sitemap_urls` | [`sitemaps`][24] | Unchanged |
+| `stop_urls` | [`exclusionPatterns`][25] | Supports [`micromatch`][27] |
+| `selectors_exclude` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `custom_settings` | [`initialIndexSettings`][26] | Unchanged |
+| `scrape_start_urls` | **removed** | Can be handled with [`exclusionPatterns`][25] |
+| `strip_chars` | **removed** | `#` are removed automatically from anchor links, edge cases should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `conversation_id` | **removed** | Not needed anymore |
+| `nb_hits` | **removed** | Not needed anymore |
+| `sitemap_alternate_links` | **removed** | Not needed anymore |
+| `stop_content` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+
+[1]: /docs/v3/docsearch
+[2]: https://www.algolia.com/products/search-and-discovery/crawler/
+[3]: /docs/legacy/run-your-own
+[4]: /docs/record-extractor
+[7]: https://crawler.algolia.com/
+[14]: /docs/legacy/config-file
+[15]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[16]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[20]: https://www.algolia.com/doc/tools/crawler/apis/configuration/start-urls/
+[21]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[22]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/#parameter-param-waittime
+[23]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-indexname
+[24]: https://www.algolia.com/doc/tools/crawler/apis/configuration/sitemaps/
+[25]: https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/
+[26]: https://www.algolia.com/doc/tools/crawler/apis/configuration/initial-index-settings/
+[27]: https://github.com/micromatch/micromatch
+[28]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[29]: /docs/record-extractor
+[30]: /docs/record-extractor#introduction
+[31]: /docs/record-extractor#pagerank
+[32]: /docs/docsearch
diff --git a/packages/website/docs/migrating-from-v3.md b/packages/website/versioned_docs/version-v4/migrating-from-v3.md
similarity index 100%
rename from packages/website/docs/migrating-from-v3.md
rename to packages/website/versioned_docs/version-v4/migrating-from-v3.md
diff --git a/packages/website/versioned_docs/version-v4/record-extractor.md b/packages/website/versioned_docs/version-v4/record-extractor.md
new file mode 100644
index 00000000..64c34ca7
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/record-extractor.md
@@ -0,0 +1,345 @@
+---
+title: Record Extractor
+---
+
+## Introduction
+
+:::info
+
+This documentation will only contain information regarding the **helpers.docsearch** method, see **[Algolia Crawler Documentation][7]** for more information on the **[Algolia Crawler][8]**.
+
+:::
+
+Pages are extracted by a [`recordExtractor`][9]. These extractors are assigned to [`actions`][12] via the [`recordExtractor`][9] parameter. This parameter links to a function that returns the data you want to index, organized in an array of JSON objects.
+
+_The helpers are a collection of functions to help you extract content and generate Algolia records._
+
+### Useful links
+
+- [Extracting records with the Algolia Crawler][11]
+- [`recordExtractor` parameters][10]
+
+## Usage
+
+The most common way to use the DocSearch helper, is to return its result to the [`recordExtractor`][9] function.
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Manipulate the DOM with Cheerio
+
+The [`Cheerio instance ($)`](https://cheerio.js.org/) allows you to manipulate the DOM:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ $(".my-warning-message").remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Provide fallback selectors
+
+Fallback selectors can be useful when retrieving content that might not exist in some pages:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ // `.exists h1` will be selected if `.exists-probably h1` does not exists.
+ lvl0: {
+ selectors: [".exists-probably h1", ".exists h1"],
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ // `.exists p, .exists li` will be selected.
+ content: [
+ ".does-not-exists p, .does-not-exists li",
+ ".exists p, .exists li",
+ ],
+ },
+ });
+},
+```
+
+### Provide raw text (`defaultValue`)
+
+_Only the `lvl0` and [custom variables][13] selectors support this option_
+
+You might want to structure your search results differently than your website, or provide a `defaultValue` to a potentially non-existent selector:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably h1",
+ defaultValue: "myRawTextIfDoesNotExists",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably .language",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ },
+ });
+},
+```
+
+### Indexing content for faceting
+
+_These selectors also support [`defaultValue`](#provide-raw-text-defaultvalue) and [fallback selectors](#provide-fallback-selectors)_
+
+You might want to index content that will be used as filters in your frontend (e.g. `version` or `lang`), you can define any custom variable to the `recordProps` object to add them to your Algolia records:
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ foo: ".bar",
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".does-not-exists",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ version: {
+ // You can send raw values without `selectors`
+ defaultValue: ["latest", "stable"],
+ },
+ },
+ });
+},
+```
+
+The following `version`, `lang` and `foo` attributes will be available in your records:
+
+```json
+foo: "valueFromBarSelector",
+language: ["en", "en-US"],
+version: ["latest", "stable"]
+```
+
+You can now use them to [filter your search in the frontend][16]
+
+### Boost search results with `pageRank`
+
+This parameter allows you to boost records using a custom ranking attribute built from the current `pathsToMatch`. Pages with highest [`pageRank`](#pagerank) will be returned before pages with a lower [`pageRank`](#pagerank). The default value is 0 and you can pass any numeric value **as a string**, including negative values.
+
+Search results are sorted by weight (desc), so you can have both boosted and non boosted results. The weight of each result will be computed for a given query based on multiple factors: match level, position, etc. and the pageRank value will be added to this final weight. The pageRank on its own may not be enough to influence the results of your query depending on how your [overall ranking is set up](https://www.algolia.com/doc/guides/managing-results/relevance-overview/in-depth/ranking-criteria/). If changing the pageRank value doesn't influence your search results enough, even with large values, move weight.pageRank higher in the Ranking and Sorting page for your index.
+
+You can view the computed weight directly from the Algolia dashboard (dashboard.algolia.com->search->perform a search->mouse hover over the "ranking criteria" icon bottom right of each record). That will give you an idea of what pageRank value is acceptable for your case.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers, url }) => {
+ const isDocPage = /\/[\w-]+\/docs\//.test(url.pathname);
+ const isBlogPage = /\/[\w-]+\/blog\//.test(url.pathname);
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ pageRank: isDocPage ? "-2000" : isBlogPage ? "-1000" : "0",
+ },
+ });
+ },
+},
+```
+
+### Reduce the number of records
+
+If you encounter the `Extractors returned too many records` error when your page outputs more than 750 records, the [`aggregateContent`](#aggregatecontent) option helps you reduce the number of records at the `content` level of the extractor.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ aggregateContent: true,
+ });
+ },
+},
+```
+
+### Reduce the record size
+
+If you encounter the `Records extracted are too big` error when crawling your website, it is usually because there is too much information in your records, or because your page is too large. The [`recordVersion`](#recordversion) option helps you reduce the records size by removing informations that are only used with [DocSearch v2](/docs/legacy/dropdown).
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ recordVersion: "v3",
+ });
+ },
+},
+```
+
+## `recordProps` API Reference
+
+### `lvl0`
+
+> `type: Lvl0` | **required**
+
+```ts
+type Lvl0 = {
+ selectors: string | string[];
+ defaultValue?: string;
+};
+```
+
+### `lvl1`, `content`
+
+> `type: string | string[]` | **required**
+
+### `lvl2`, `lvl3`, `lvl4`, `lvl5`, `lvl6`
+
+> `type: string | string[]` | **optional**
+
+### `pageRank`
+
+> `type: number` | **optional**
+
+See the [live example](#boost-search-results-with-pagerank)
+
+### Custom variables
+
+> `type: string | string[] | CustomVariable` | **optional**
+
+```ts
+type CustomVariable =
+ | {
+ defaultValue: string | string[];
+ }
+ | {
+ selectors: string | string[];
+ defaultValue?: string | string[];
+ };
+```
+
+Custom variables are used to [`filter your search`](/docs/v3/docsearch#filtering-your-search), you can define them in the [`recordProps`](#indexing-content-for-faceting)
+
+## `helpers.docsearch` API Reference
+
+### `aggregateContent`
+
+> `type: boolean` | default: `true` | **optional**
+
+[This option](#reduce-the-number-of-records) groups the Algolia records created at the `content` level of the selector into a single record for its matching heading.
+
+### `recordVersion`
+
+> `type: 'v3' | 'v2'` | default: `v2` | **optional**
+
+This option removes content from the Algolia records that are only used for [DocSearch v2](/docs/legacy/dropdown). If you are using [the latest version of DocSearch](/docs/v3/docsearch), you can [set it to `v3`](#reduce-the-record-size).
+
+### `indexHeadings`
+
+> `type: boolean | { from: number, to: number }` | default: `true` | **optional**
+
+This option tells the crawler if the `headings` (`lvlX`) should be indexed.
+
+- When `false`, only records for the `content` level will be created.
+- When `from, to` is provided, only records for the `lvlX` to `lvlY` will be created.
+
+[1]: /docs/v3/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/migrating-from-legacy
+[6]: /docs/legacy/run-your-own
+[7]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[8]: https://www.algolia.com/products/search-and-discovery/crawler/
+[9]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[10]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor-2
+[11]: https://www.algolia.com/doc/tools/crawler/guides/extracting-data/#extracting-records
+[12]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/
+[13]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: /docs/v3/docsearch/#filtering-your-search
diff --git a/packages/website/versioned_docs/version-v4/required-configuration.mdx b/packages/website/versioned_docs/version-v4/required-configuration.mdx
new file mode 100644
index 00000000..9b33aed2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/required-configuration.mdx
@@ -0,0 +1,189 @@
+---
+title: Required configuration
+---
+
+This section gives you the best practices to optimize our crawl. Adopting the following specification is required to let our crawler build the best experience from your website. You will need to update your website and follow these rules.
+
+:::info
+
+If your website is generated, thanks to one of [our supported tools][1], you do not need to change your website as it is already compliant with our requirements.
+
+:::
+
+## The generic configuration example
+
+You can find the default DocSearch config template below and tweak it with some examples from our [`complex extractors` section][12].
+
+If you are using one of [our integrations][13], please see [the templates page][11].
+
+
+docsearch-default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ startUrls: ['https://YOUR_START_URL.io/'],
+ sitemaps: ['https://YOUR_START_URL.io/sitemap.xml'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_START_URL.io/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+### Overview of a clear layout
+
+A website implementing these best practices will look simple and clear, as shown below:
+
+
+
+The main blue element will be your `.DocSearch-content` container. More details in the following guidelines.
+
+### Use the right classes as [`recordProps`][2]
+
+You can add some specific static classes to help us find your content role. These classes can not involve any style changes. These dedicated classes will help us to create a great learn-as-you-type experience from your documentation.
+
+- Add a static class `DocSearch-content` to the main container of your textual content. Most of the time, this tag is a `` or an `` HTML element.
+
+- Every searchable `lvl` element outside this main documentation container (for instance in a sidebar) must be a `global` selector. They will be globally picked up and injected to every record built from your page. Be careful, the level value matters and every matching element must have an increasing level along the HTML flow. A level `X` (for `lvlX`) should appear after a level `Y` while `X > Y`.
+
+- `lvlX` selectors should use the standard title tags like `h1`, `h2`, `h3`, etc. You can also use static classes. Set a unique `id` or `name` attribute to these elements as detailed below.
+
+- Every DOM element matching the `lvlX` selectors must have a unique `id` or `name` attribute. This will help the redirection to directly scroll down to the exact place of the matching elements. These attributes define the right anchor to use.
+
+- Every textual element (recordProps `content`) must be wrapped in a `` or `
` tag. This content must be atomic and split into small entities. Be careful to never nest one matching element into another one as it will create duplicates.
+
+- Stay consistent and do not forget that we need to have some consistency along the HTML flow.
+
+## Introduce global information as meta tags
+
+Our crawler automatically extracts information from our DocSearch specific meta tags:
+
+```html
+
+
+```
+
+The crawl adds the `content` value of these `meta` tags to all records extracted from the page. The meta tags `name` must follow the `docsearch:$NAME` pattern. `$NAME` is the name of the attribute set to all records.
+
+The `docsearch:version` meta tag can be a set [of comma-separated tokens][5], each of which is a version relevant to the page. These tokens must be compliant with [the SemVer specification][6] or only contain alphanumeric characters (e.g. `latest`, `next`, etc.). As facet filters, these version tokens are case-insensitive.
+
+For example, all records extracted from a page with the following meta tag:
+
+```html
+
+```
+
+The `version` attribute of these records will be :
+
+```json
+version:["2.0.0-alpha.62", "latest"]
+```
+
+You can then [transform these attributes as `facetFilters`][3] to [filter over them from the UI][10].
+
+## Nice to have
+
+- Your website should have [an updated sitemap][7]. This is key to let our crawler know what should be updated. Do not worry, we will still crawl your website and discover embedded hyperlinks to find your great content.
+
+- Every page needs to have their full context available. Using global elements might help (see above).
+
+- Make sure your documentation content is also available without JavaScript rendering on the client-side. If you absolutely need JavaScript turned on, you need to [set `renderJavaScript: true` in your configuration][8].
+
+Any questions? Connect with us on [Discord][14] or [support][9].
+
+[1]: /docs/integrations
+[2]: record-extractor#recordprops-api-reference
+[3]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[5]: https://html.spec.whatwg.org/dev/common-microsyntaxes.html#comma-separated-tokens
+[6]: https://semver.org/
+[7]: https://www.sitemaps.org/
+[8]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[9]: https://support.algolia.com/
+[10]: /docs/v3/docsearch#filtering-your-search
+[11]: /docs/templates
+[12]: /docs/record-extractor#introduction
+[13]: /docs/integrations
+[14]: https://alg.li/discord
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
new file mode 100644
index 00000000..b22ca01f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
@@ -0,0 +1,144 @@
+---
+title: Advanced use cases
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+This guide will cover some advanced implementations/use cases for the Sidepanel. The examples below assume you're using the Sidepanel React package,
+available from `@docsearch/sidepanel`. The `@docsearch/sidepanel` package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Complex implementation
+
+Below is an example of a more complex implementation with `searchParameters`, a different `variant`, and some translations.
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+function App() {
+ return (
+
+
+
+
+ );
+}
+```
+
+## Dynamic importing
+
+Sidepanel is built in a way that allows for dynamic importing of its components to help reduce bundle size. Below is a brief example of how to do so:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton } from '@docsearch/sidepanel/button';
+import type { Sidepanel as SidepanelType } from '@docsearch/sidepanel/sidepanel';
+import { useState } from 'react';
+
+let Sidepanel: typeof SidepanelType | null = null;
+
+async function importSidepanelIfNeeded() {
+ if (Sidepanel) {
+ return;
+ }
+
+ const { Sidepanel: Panel } = await import('@docsearch/sidepanel/sidepanel');
+
+ Sidepanel = Panel;
+}
+
+export default function DynamicSidepanel() {
+ const [sidepanelLoaded, setSidepanelLoaded] = useState(false);
+
+ const loadSidepanel = () => {
+ importSidepanelIfNeeded().then(() => {
+ setSidepanelLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {sidepanelLoaded && Sidepanel && (
+
+ )}
+
+ );
+}
+```
+
+## Hybrid Mode
+
+Hybrid Mode allows you to combine the Sidepanel and the original DocSearch Modal in one integrated experience.
+
+You can trigger the Modal for search and the Sidepanel for AI-powered assistance.
+
+Learn more in the [Hybrid Mode guide][1].
+
+[1]: /docs/sidepanel/hybrid
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
new file mode 100644
index 00000000..6e3a1b5e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
@@ -0,0 +1,186 @@
+---
+title: Sidepanel API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `assistantId`
+
+> `type: string` | **required**
+
+The ID for which Ask AI assistant to use.
+
+## `indexName`
+
+> `type: string` | **required**
+
+The name of the index to be used with the Ask AI service.
+
+## `agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `agentStudio` is true, the Ask AI chat will use Algolia's [Agent Studio][2] as the chat backend instead of the Ask AI backend. More can be learned about setting up Agent Studio on their dedicated [documentation page][3].
+
+## `searchParameters`
+
+> `type: AskAiSearchParameters | Record>` | **optional**
+
+Additional search parameters used to scope Ask AI or Agent Studio retrieval.
+
+- When `agentStudio` is omitted or `false`, pass a flat object such as `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- When `agentStudio` is `true`, `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+```tsx
+
+```
+
+```tsx
+
+```
+
+## `variant`
+
+> `type: 'floating' | 'inline'` | default: `'floating'` | **optional**
+
+Variant of the Sidepanel positioning.
+
+- `inline` pushes page content when opened.
+- `floating` is positioned above all other content on the page.
+
+## `side`
+
+> `type: 'right' | 'left'` | default: `'right'` | **optional**
+
+The side of the page which the panel will originate from.
+
+## `width`
+
+> `type: number | string` | default: `'360px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its default state.
+
+## `expandedWidth`
+
+> `type: number | string` | default: `'580px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its expanded state.
+
+## `suggestedQuestions`
+
+> `type: boolean` | default: `false` | **optional**
+
+Enables displaying suggested questions on new conversation screen.
+
+More information on setting up Suggested Questions can be found on [Algolia Docs][1]
+
+## `keyboardShortcuts`
+
+> `type: { 'Ctrl/Cmd+I': boolean }` | **optional**
+
+Configuration for keyboard shortcuts. Allows enabling/disabling specific shortcuts.
+
+### Default behavior
+
+- `Ctrl/Cmd+I` - Opens and closes the Sidepanel
+
+### Interface
+
+```ts
+interface SidepanelShortcuts {
+ 'Ctrl/Cmd+I'?: boolean; // default: true
+}
+```
+
+## `theme`
+
+> `type: 'light' | 'dark'` | default: `'light'` | **optional**
+
+## `portalContainer` (React only)
+
+> `type: Element | DocumentFragment` | default: `document.body` | **optional**
+
+The container element where the panel should be portaled to. Use this when you need the Sidepanel to render in a custom DOM node.
+
+:::warning
+This prop only exists in the React based versions of Sidepanel. If you are using the `@docsearch/sidepanel-js` package, use the `container` option instead.
+:::
+
+
+
+ ```tsx
+ // assume you have a dedicated DOM node in your HTML
+
+
+ const portalEl = document.getElementById('sidepanel-root');
+
+
+ ```
+
+
+
+ ```js
+ sidepanel({
+ // The element that will contain the Sidepanel Button and Sidepanel
+ container: '#sidepanel-root',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+ })
+ ```
+
+
+
+[1]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/suggested-questions
+[2]: https://www.algolia.com/products/ai/agent-studio
+[3]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
new file mode 100644
index 00000000..13d31f95
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
@@ -0,0 +1,136 @@
+---
+title: Get started with Sidepanel
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Sidepanel is available from version `>= 4.4`
+:::
+
+## Introduction
+
+DocSearch Sidepanel is a new experience separate from the DocSearch Modal experience. Sidepanel is built entirely for usage with Ask AI and can be used completely standalone or in [Hybrid mode][1] with the Modal.
+
+## Installation
+
+To get started with Sidepanel, first you will need to install the needed packages:
+
+
+
+
+```bash
+npm install @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+npm install @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+yarn add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+pnpm add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+bun add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+### Without package manager
+
+```html
+
+
+
+
+```
+
+## Implementation
+
+The simplest implementation of Sidepanel would be as follows:
+
+
+
+```tsx
+import { DocSearchSidepanel } from '@docsearch/react/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function App() {
+ return (
+
+ );
+}
+```
+
+
+
+You will need a `container` DOM node to render the Sidepanel into:
+
+```html
+
+```
+
+```js
+import sidepanel from '@docsearch/sidepanel-js';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+sidepanel({
+ container: '#docsearch-sidepanel',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+});
+```
+
+
+
+This is just the most basic form of implementation. To learn about other implementation methods, you can read our [Advanced use cases][2].
+
+To learn more about the different configuration options for Sidepanel, you can read our [Sidepanel API References][3].
+
+[1]: /docs/sidepanel/hybrid
+[2]: /docs/sidepanel/advanced-use-cases
+[3]: /docs/sidepanel/api-reference
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
new file mode 100644
index 00000000..0be6f2cb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
@@ -0,0 +1,100 @@
+---
+title: Hybrid Mode
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Currently Hybrid Mode is only available when using the React usage approach. Hybrid Mode is not available in the JavaScript-only (vanilla) integration.
+:::
+
+## Introduction
+
+Sidepanel can run alongside the DocSearch Modal through what we call "Hybrid Mode." When a user initiates an Ask AI action from within
+the DocSearch Modal, such as submitting a prompt or selecting an AI-related suggestion, the interface automatically transitions into the Sidepanel for
+the continuation of the conversation.
+
+## Set up
+
+To set up the Hybrid Mode experience, you will need the following:
+
+- [DocSearch Modal][1] packages installed
+- Sidepanel Component package installed
+
+The Sidepanel Component package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+Once everything is installed, you can set up Hybrid Mode as such:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function HybridMode() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+There is no manual opt-in for Hybrid Mode to work. When both the Modal and Sidepanel are rendered inside the same `` context, Hybrid Mode is enabled automatically. No additional configuration is required.
+
+[1]: /docs/docsearch#installation
diff --git a/packages/website/versioned_docs/version-v4/styling.md b/packages/website/versioned_docs/version-v4/styling.md
new file mode 100644
index 00000000..554fe0c0
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/styling.md
@@ -0,0 +1,48 @@
+---
+title: Styling
+---
+
+:::info
+
+The following content is for **[DocSearch v4][2]**. If you are using **[DocSearch v3][3]**, see the **[legacy][4]** documentation.
+
+:::
+
+## Introduction
+
+DocSearch v4 comes with a theme package called `@docsearch/css`, which offers a sleek out of the box theme!
+
+:::note
+
+This package is a dependency of [`@docsearch/js`][1] and [`@docsearch/react`][1], you don't need to install it if you are using a package manager!
+
+:::
+
+## Installation
+
+```bash
+yarn add @docsearch/css@4
+# or
+npm install @docsearch/css@4
+```
+
+If you donβt want to use a package manager, you can use a standalone endpoint:
+
+```html
+
+```
+
+## Files
+
+```
+@docsearch/css
+βββ dist/style.css # all styles
+βββ dist/_variables.css # CSS variables
+βββ dist/button.css # CSS for the button
+βββ dist/modal.css # CSS for the modal
+```
+
+[1]: /docs/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/v3/docsearch
diff --git a/packages/website/versioned_docs/version-v4/templates.mdx b/packages/website/versioned_docs/version-v4/templates.mdx
new file mode 100644
index 00000000..b14126d9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/templates.mdx
@@ -0,0 +1,1069 @@
+---
+title: Config Templates
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+To help you create the best search experience for your users, we provide out-of-the-box crawler config templates for multiple websites generators. If you'd like to add a new template to our list, or believe we should update an existing one, please [let us know on Discord][1] or [open a pull request][2].
+
+> If you want to better understand the default parameters of the configs below, take a look at the [Crawler documentation](https://www.algolia.com/doc/tools/crawler/apis/configuration/).
+
+## Getting Started
+
+Once approved for DocSearch, we will automatically create a Crawler on your behalf, include your URL, and the Algolia credentials for your appId, apiKey, and indexName. If we detect that you are using any of the predefined generators, we'll attempt to automatically assign the proper template that matches your generator. However, this is not guaranteed. If no specific generator is detected, we will apply the default template seen below.
+
+## Updating the Template
+
+You can manually update the crawler template by going to dashboard.algolia.com, click "Data sources", select your crawler, and go to the editor page. From there you can edit the JavaScript directly. Note that you can make draft changes without saving, test the changes using the "URL Tester", and then "Save" once you're happy with your changes.
+
+## Default Template
+
+
+default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ indexPrefix: 'crawler_',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL'],
+ renderJavaScript: false,
+ sitemaps: [],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v1 Template
+
+
+docusaurus-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/docs/',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/blog/',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/docs/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Docs',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['docs'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/blog/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Blog',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['blog'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang', 'language', 'version', 'tags'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v2 & v3 Template
+
+
+docusaurus-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // priority order: deepest active sub list header -> navbar active item -> 'Documentation'
+ // Extracting the breadcrumb titles for better accessibility.
+ const navbarTitle = $(".navbar__item.navbar__link--active").text();
+ const pageBreadcrumbTitles = $(".breadcrumbs__link")
+ .toArray()
+ .map((item) => $(item).text().trim())
+ .filter(Boolean);
+ const lvl0 =
+ [navbarTitle, ...pageBreadcrumbTitles].join(" / ") || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: lvl0,
+ },
+ lvl1: ['header h1', 'article h1'],
+ lvl2: 'article h2',
+ lvl3: 'article h3',
+ lvl4: 'article h4',
+ lvl5: 'article h5, article td:first-child',
+ lvl6: 'article h6',
+ content: 'article p, article li, article td:last-child',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ 'language',
+ 'version',
+ 'docusaurus_tag',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+## Astro Starlight Template
+
+
+starlight.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Get the top level menu item
+ const lvl0 =
+ $('details:has(a[aria-current="page"])')
+ .find("summary")
+ .find("span")
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: "main h1",
+ lvl2: "main h2",
+ lvl3: "main h3",
+ lvl4: "main h4",
+ lvl5: "main h5",
+ lvl6: "main h6",
+ content: "main p, main li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v1 Template
+
+
+vuepress-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: 'p.sidebar-heading.open',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content__default h1',
+ lvl2: '.content__default h2',
+ lvl3: '.content__default h3',
+ lvl4: '.content__default h4',
+ lvl5: '.content__default h5',
+ content: '.content__default p, .content__default li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v2 Template
+
+
+vuepress-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vitepress Template
+
+
+vitepress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content h1',
+ lvl2: '.content h2',
+ lvl3: '.content h3',
+ lvl4: '.content h4',
+ lvl5: '.content h5',
+ content: '.content p, .content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Rspress Template
+
+
+rspress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ const lvl0 =
+ $(".rspress-nav-menu-item.rspress-nav-menu-item-active")
+ .first()
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: ".rspress-doc h1",
+ lvl2: ".rspress-doc h2",
+ lvl3: ".rspress-doc h3",
+ lvl4: ".rspress-doc h4",
+ lvl5: ".rspress-doc h5",
+ lvl6: ".rspress-doc pre > code", // if you want to search code blocks, add this line
+ content: ".rspress-doc p, .rspress-doc li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: "v3",
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## pkgdown Template
+
+
+pkgdown.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/index.html',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/reference',
+ 'https://YOUR_WEBSITE_URL/articles',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ exclusionPatterns: [
+ '**/reference/',
+ '**/reference/index.html',
+ '**/articles/',
+ '**/articles/index.html',
+ ],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/index.html**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ defaultValue: 'YOUR_INDEX_NAME Home page',
+ },
+ lvl1: '.contents h2',
+ lvl2: '.contents h3',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li, .contents .pre',
+ tags: {
+ defaultValue: ['homepage'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/reference**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.ref-arguments th',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['reference'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/articles**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.contents h2, .contents h3',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['articles'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+[1]: https://alg.li/discord
+[2]: https://github.com/algolia/docsearch
diff --git a/packages/website/versioned_docs/version-v4/tips.md b/packages/website/versioned_docs/version-v4/tips.md
new file mode 100644
index 00000000..57d1c4fa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/tips.md
@@ -0,0 +1,71 @@
+---
+title: Tips for a good search
+---
+
+DocSearch can work with almost any website, but we've found that some site structures yield more relevant results or faster indexing time. On this page we'll share some tips on how to make the most out of DocSearch.
+
+## Use a `sitemap.xml`
+
+If you provide a sitemap in your configuration, DocSearch will use it to directly browse the pages to index. Pages are still crawled which means we extract every compliant link.
+
+We highly recommend you add a `sitemap.xml` to your website if you don't have one already. This will not only make the indexing faster, but also provide you more control over which pages to index.
+
+Sitemaps are also considered good practice for other aspects, including SEO ([more information on sitemaps][1]).
+
+## Structure the hierarchy of information
+
+DocSearch works better on structured documentation. Relevance of results is based on the structural hierarchy of content. In simpler terms, it means that we read the ``, ..., `` headings of your page to guess the hierarchy of information. This hierarchy brings contextual information to your records.
+
+Documentation starts by explaining generic concepts first and then goes deeper into specifics. This is represented in your HTML markup by the hierarchy of headings you're using. For example, concepts discussed under a `` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+
+DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+
+Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+
+_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+
+## Set a unique class to the element holding the content
+
+DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
+
+Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+
+## Add anchors to headings
+
+When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+
+DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+
+## Marking the active page(s) in the navigation
+
+If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+
+For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
+
+The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+
+## Consistency of your content
+
+Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+
+The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+
+Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+
+Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+
+## Avoid duplicates by promoting unicity
+
+The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+
+Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+
+## Conciseness
+
+What is clearly thought out is clearly and concisely expressed.
+
+We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+
+[1]: https://www.sitemaps.org/index.html
+[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
+[3]: https://www.algolia.com/doc/guides/searching/faceting/
diff --git a/packages/website/docs/v4/askai-api.mdx b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
similarity index 97%
rename from packages/website/docs/v4/askai-api.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-api.mdx
index a01ff9e1..3edf58b2 100644
--- a/packages/website/docs/v4/askai-api.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
@@ -23,4 +23,4 @@ The official documentation includes:
- Integration examples with Next.js and Vercel AI SDK
- Error handling and best practices
-For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/askai).
+For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/v4/askai).
diff --git a/packages/website/docs/v4/askai-errors.mdx b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-errors.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
index 60b6d10b..53eb6f47 100644
--- a/packages/website/docs/v4/askai-errors.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
@@ -161,5 +161,5 @@ The request exceeded the model's maximum context length. This happens when the c
[1]: /docs/api#askai
[2]: https://sitesearch.algolia.com/docs/experiences/search-askai#configuration
[3]: https://www.algolia.com/doc/guides/algolia-ai/askai/reference/api
-[4]: /docs/v4/askai-whitelisted-domains
+[4]: /docs/v4/v4/askai-whitelisted-domains
[5]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/models
diff --git a/packages/website/docs/v4/askai-markdown-indexing.mdx b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-markdown-indexing.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
index 4160f9ef..4900f1b9 100644
--- a/packages/website/docs/v4/askai-markdown-indexing.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
@@ -39,7 +39,7 @@ The easiest way to set up markdown indexing is through the Crawler UI, which aut
- **Content Tag**: Specify the HTML content selector (typically `main`)
- **Template**: Choose the template that matches your documentation framework:
- **Docusaurus** - For Docusaurus sites
- - **VitePress** - For VitePress sites
+ - **VitePress** - For VitePress sites
- **Astro/Starlight** - For Astro/Starlight sites
- **Non-DocSearch (Generic)** - For custom sites or other frameworks
@@ -245,7 +245,7 @@ class CustomAskAI {
async sendMessage(conversationId, messages, searchParameters = {}) {
const token = await this.getToken();
-
+
const response = await fetch(`${this.baseUrl}/chat`, {
method: 'POST',
headers: {
@@ -270,14 +270,14 @@ class CustomAskAI {
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
-
+
return {
async *[Symbol.asyncIterator]() {
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
-
+
const chunk = decoder.decode(value, { stream: true });
if (chunk.trim()) {
yield chunk;
@@ -323,7 +323,7 @@ for await (const chunk of stream) {
- Integration with existing chat systems
- Custom analytics and monitoring
-> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/askai-api).
+> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/v4/askai-api).
**Using Facet Filters with Your Markdown Index:**
diff --git a/packages/website/docs/v4/askai-models.mdx b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
similarity index 71%
rename from packages/website/docs/v4/askai-models.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-models.mdx
index fff60ff5..63f10810 100644
--- a/packages/website/docs/v4/askai-models.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
@@ -2,7 +2,7 @@
title: Bring Your Own LLM
---
-import { ProvidersTable } from '../../src/components/ProvidersTable'
+import { ProvidersTable } from '@site/src/components/ProvidersTable';
Ask AI currently supports a Bring Your Own LLM (BYOLLM) model selection, allowing you to connect your preferred provider.
diff --git a/packages/website/docs/v4/askai-prompts.mdx b/packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-prompts.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
diff --git a/packages/website/docs/v4/askai-whitelisted-domains.mdx b/packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-whitelisted-domains.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
diff --git a/packages/website/docs/v4/askai.mdx b/packages/website/versioned_docs/version-v4/v4/askai.mdx
similarity index 98%
rename from packages/website/docs/v4/askai.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai.mdx
index 0cc29de5..9a561f57 100644
--- a/packages/website/docs/v4/askai.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai.mdx
@@ -118,5 +118,5 @@ This view gives you a centralized place to organize, reuse, and fine-tune your a
## Next steps
-- [Prompting with Ask AI](/docs/v4/askai-prompts)
-- [Ask AI Whitelisted Domains](/docs/v4/askai-whitelisted-domains)
+- [Prompting with Ask AI](/docs/v4/v4/askai-prompts)
+- [Ask AI Whitelisted Domains](/docs/v4/v4/askai-whitelisted-domains)
diff --git a/packages/website/versioned_docs/version-v4/what-is-docsearch.md b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
new file mode 100644
index 00000000..c371ae12
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
@@ -0,0 +1,32 @@
+---
+title: What is DocSearch?
+sidebar_label: What is DocSearch?
+---
+
+## Why?
+
+We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+
+It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+
+## Quick description
+
+We split DocSearch into a crawler and a frontend library.
+
+- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
+- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+
+## How to feature DocSearch?
+
+DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+
+DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
+
+You can now [apply to the program][3].
+
+[1]: https://opencollective.com/algolia
+[2]: /docs/who-can-apply
+[3]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[4]: https://www.algolia.com/products/search-and-discovery/crawler/
+[5]: https://dashboard.algolia.com/crawler
+[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
diff --git a/packages/website/versioned_docs/version-v4/who-can-apply.md b/packages/website/versioned_docs/version-v4/who-can-apply.md
new file mode 100644
index 00000000..cec7c5ae
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/who-can-apply.md
@@ -0,0 +1,30 @@
+---
+title: Who can apply?
+---
+
+**Open for all developer documentation and technical blogs.**
+
+We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all public online technical documentations and technical blogs.
+
+We usually turn down applications when they are not production ready or have non-technical content on the website.
+
+## Application process
+
+To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+
+- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+
+- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+
+- β
Please review [DocSearch Plan Terms and Conditions][2].
+
+## Process duration
+
+DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+
+Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
+[3]: integrations.md
+[4]: https://alg.li/discord
diff --git a/packages/website/versioned_sidebars/version-v4-sidebars.json b/packages/website/versioned_sidebars/version-v4-sidebars.json
new file mode 100644
index 00000000..74276efe
--- /dev/null
+++ b/packages/website/versioned_sidebars/version-v4-sidebars.json
@@ -0,0 +1,81 @@
+{
+ "docs": [
+ {
+ "type": "category",
+ "label": "Introduction",
+ "items": ["what-is-docsearch", "who-can-apply"]
+ },
+ {
+ "type": "category",
+ "label": "DocSearch v4",
+ "items": ["docsearch", "docusaurus-adapter", "composable-api", "styling", "api", "examples", "migrating-from-v3"]
+ },
+ {
+ "type": "category",
+ "label": "MCP",
+ "items": ["mcp/overview", "mcp/installation", "mcp/usage"]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Ask AI",
+ "items": [
+ "v4/askai",
+ "v4/askai-api",
+ "v4/askai-prompts",
+ "v4/askai-whitelisted-domains",
+ "v4/askai-models",
+ "v4/askai-markdown-indexing",
+ "v4/askai-errors",
+ {
+ "type": "link",
+ "label": "Full Documentation",
+ "href": "https://www.algolia.com/doc/guides/algolia-ai/askai"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Sidepanel",
+ "items": [
+ "sidepanel/getting-started",
+ "sidepanel/advanced-use-cases",
+ "sidepanel/hybrid",
+ "sidepanel/api-reference"
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Crawler",
+ "items": ["create-crawler", "record-extractor", "templates", "crawler-configuration-visual", "manage-your-crawls"]
+ },
+ {
+ "type": "category",
+ "label": "Requirements, tips, FAQ",
+ "items": [
+ {
+ "type": "category",
+ "label": "FAQ",
+ "items": ["crawler", "docsearch-program"]
+ },
+ {
+ "type": "doc",
+ "id": "tips"
+ },
+ {
+ "type": "doc",
+ "id": "integrations"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Under the hood",
+ "items": ["how-does-it-work", "required-configuration"]
+ },
+ {
+ "type": "category",
+ "label": "Miscellaneous",
+ "items": ["migrating-from-legacy"]
+ }
+ ]
+}
diff --git a/packages/website/versions.json b/packages/website/versions.json
index dbac805d..9b27128c 100644
--- a/packages/website/versions.json
+++ b/packages/website/versions.json
@@ -1 +1 @@
-["v3", "legacy"]
+["v4", "v3", "legacy"]
` is more specific than content under an `` on the same page. Content that appears earlier on the page ranks higher.
-DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+DocSearch uses this structure to improve relevance. V5 also uses the populated hierarchy levels to render result breadcrumbs. Keep headings in order and avoid skipping levels where possible so each result retains its page context.
-Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+Choose a documentation depth that gives each result enough context. For large pages, use four levels, from `lvl0` to `lvl3`. Use at least three levels.
-_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+You can use classes, such as ``, instead of `` elements.
## Set a unique class to the element holding the content
DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
-Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+A unique identifier makes your configuration more robust and limits indexing to relevant content. Use it to exclude unrelated headers, sidebars, and footers.
## Add anchors to headings
-When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+Add a custom anchor to each heading. Define anchors with an `id` or `name` HTML attribute so browsers can scroll directly to the corresponding position. Links can target an anchor with `#` followed by its value.
-DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+DocSearch uses these anchors to send users to the location of the selected result.
-## Marking the active page(s) in the navigation
+## Mark active pages in the navigation
-If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+If you use multi-level navigation, mark each active level with a custom CSS class. The crawler can use this class to determine where the current page fits in the website hierarchy.
For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
-The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+Use any valid CSS class name that can be part of a CSS selector.
## Consistency of your content
-Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+Use the same heading structure across documentation pages. Make each page topic and outline clear, and avoid selectors that create records without enough context, such as standalone introductions or asides.
-The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+Write selectors that match documentation pages but exclude landing pages, tables of contents, and other unrelated content. Add a dedicated class, such as `.DocSearch-content`, to the main documentation container.
-Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+Use consistent terms for the same concepts. You can also configure [synonyms][5] for terms your users search interchangeably.
-Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+## Avoid duplicate content
-## Avoid duplicates by promoting unicity
+Split broad topics into focused pages. Avoid catch-all pages that make it difficult to identify the relevant result.
-The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+Duplicate content adds noise and can mislead users. Don't repeat all documentation content on a landing or summary page. If you need duplicate records for separate datasets, such as different versions, use [facets][3] to distinguish them.
-Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+## Index metadata for v5
+
+Add each attribute used by the v5 `facets` option to `attributesForFaceting`. DocSearch supports up to five facet controls. For a result badge, index a short value such as `version`, include it in `attributesToRetrieve`, and pass its property path to `resultBadgeKey`. See the [v5 JavaScript API reference][4].
## Conciseness
-What is clearly thought out is clearly and concisely expressed.
+Keep content focused on one task or concept, and use short headings and paragraphs.
-We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+For more guidance, read [How to build a helpful search for technical documentation][2].
[1]: https://www.sitemaps.org/index.html
[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
[3]: https://www.algolia.com/doc/guides/searching/faceting/
+[4]: /docs/packages/js/api-reference#facets
+[5]: https://www.algolia.com/doc/guides/managing-results/must-do/searchable-attributes/#synonyms
diff --git a/packages/website/docs/v5-breaking-changes.mdx b/packages/website/docs/v5-breaking-changes.mdx
new file mode 100644
index 00000000..f3ec2ef5
--- /dev/null
+++ b/packages/website/docs/v5-breaking-changes.mdx
@@ -0,0 +1,236 @@
+---
+title: v5 breaking changes
+description: Complete user-facing breaking changes and compatibility notes for DocSearch v5.
+---
+
+This page lists the user-facing changes between the v4.6.0 package source and `5.0.0-beta.0`. Use it with the [v4 migration guide](./migrating-from-v4).
+
+## JavaScript entry points
+
+### The root export is AI-capable
+
+In v4, the root `@docsearch/js` export rendered the combined component and allowed Ask AI to be omitted. In v5, it renders `DocSearchAI`, and its `DocSearchProps` type requires `askAi`.
+
+Use the root entry when you configure Agent Studio:
+
+```js title="app.js"
+import docsearch from '@docsearch/js';
+```
+
+### Keyword-only search moved to `/docsearch`
+
+Use the new subpath when you don't need Ask AI:
+
+```js title="app.js"
+import docsearch from '@docsearch/js/docsearch';
+```
+
+This entry excludes Ask AI code.
+
+### The UMD bundle is split
+
+- `dist/umd/index.js` includes keyword search and Ask AI.
+- `dist/umd/docsearch.js` includes keyword search only.
+- Both bundles expose `window.docsearch`.
+- Loading both bundles causes the later script to replace the same global.
+
+### An exports map restricts JavaScript imports
+
+`@docsearch/js` now exports only `.` and `./docsearch`. Replace imports of internal distribution files with one of these public entry points. Direct CDN URLs to the two documented UMD files remain supported by the package layout.
+
+## React components
+
+### `DocSearch` is keyword-only
+
+V4's `DocSearch` accepted `askAi` and `interceptAskAiEvent`. V5's `DocSearch` contains keyword search only and no longer declares those props.
+
+### `DocSearchAI` owns the AI experience
+
+Use `DocSearchAI` for keyword search and Ask AI:
+
+```jsx title="Search.jsx"
+import { DocSearchAI } from '@docsearch/react';
+```
+
+`DocSearchAIProps` extends `DocSearchProps`, requires `askAi`, and adds `interceptAskAiEvent`.
+
+The package also adds `@docsearch/react/docsearchAi` and `@docsearch/react/askaiModal` subpaths.
+
+### The Ask AI modal is separate
+
+`DocSearchModal` is keyword-only. `DocSearchAskAiModal` contains the combined keyword and AI modal. Composable integrations that rendered `DocSearchModal` with `askAi` must switch to `DocSearchAskAiModal` and its required provider callbacks. Review the [Composable API](/docs/composable-api) instead of constructing these props without the provider.
+
+`@docsearch/modal` exports the AI modal from its root and from `@docsearch/modal/askai`.
+
+## Ask AI and Agent Studio
+
+### The legacy transport is removed
+
+V5 no longer requests a legacy Ask AI token or sends chat requests to the v4 Ask AI endpoint. All Ask AI conversations use the Agent Studio completions endpoint.
+
+Create and configure an assistant in [Agent Studio](/docs/agent-studio/getting-started) before upgrading.
+
+### `askAi.agentStudio` is removed
+
+The backend switch is no longer needed because Agent Studio is the only backend. Remove both `agentStudio: true` and `agentStudio: false`.
+
+### `askAi.useStagingEnv` is removed
+
+The staging endpoint switch isn't part of `DocSearchAskAi` in v5.
+
+### Flat Ask AI search parameters are removed
+
+`DocSearchAskAi.searchParameters` now always uses `AgentStudioSearchParameters`: an object keyed by index name.
+
+```js title="app.js"
+searchParameters: {
+ docs: {
+ filters: 'language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ distinct: true,
+ },
+}
+```
+
+Each value supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`. The Agent Studio type omits `facetFilters`.
+
+### Agent Studio credentials are sent directly
+
+Ask AI requests use the configured application ID and API key in `x-algolia-application-id` and `x-algolia-api-key` headers. Memory authentication adds `x-algolia-secure-user-token`. Check the permissions and domain restrictions of keys that were issued for the legacy transport.
+
+### Feedback uses Agent Studio
+
+Feedback now posts to Agent Studio and supports negative-feedback reason tags and notes. Stored conversation messages can contain `feedbackTags` and `feedbackNotes` in addition to the like or dislike value.
+
+### Agent Studio configuration is nested under `askAi`
+
+Dynamic `indices`, custom `tools`, `memory`, and keyword `promptSuggestions` belong inside the `askAi` object. `interceptAskAiEvent` remains a top-level integration callback.
+
+### Suggested questions have two sources
+
+- `askAi.suggestedQuestions` determines whether DocSearch loads published questions for the assistant from `algolia_ask_ai_suggested_questions` on the new-conversation screen.
+- `askAi.promptSuggestions` searches a configured index containing a `prompt` attribute and displays those prompts with keyword results.
+
+These options aren't interchangeable.
+
+## Search configuration
+
+### The Docusaurus adapter configuration changed
+
+The v5 adapter reads `themeConfig.docsearch` and rejects the former `themeConfig.algolia` key. It also requires `indices` and rejects `indexName` and root `searchParameters`.
+
+Replace `searchPagePath` with `searchPage`. Move `askAi.sidePanel` to the root `sidePanel` option. Remove legacy Ask AI credentials and the `askAi.agentStudio` switch. Follow [Migrate the Docusaurus adapter from v4](/docs/packages/docusaurus-adapter/migrating-from-v4) for before-and-after configurations.
+
+### At least one index is required at runtime
+
+Pass `indices` or `indexName`. V5 throws this error when neither produces an index:
+
+```text
+Must supply either `indexName` or `indices` for DocSearch to work
+```
+
+### `indexName` remains deprecated
+
+`indexName` still works; it isn't removed in v5. If present, DocSearch places it before all `indices` entries. Passing the same index through both options sends duplicate requests.
+
+### Root `searchParameters` remains deprecated
+
+The root option applies only to `indexName`. Move search parameters to each `DocSearchIndex` in `indices`.
+
+### Multiple indices share one result flow
+
+V5 creates one source for each index response and combines hit totals across responses. Result order follows the normalized index order. Review code that assumes one index or source identifier.
+
+## New keyword search behavior
+
+### Facets add requests and filters
+
+The new `facets` option fetches facet values with a zero-hit query for every configured index. DocSearch merges and sorts values, supports at most five keys after trimmed, lowercase duplicate checks, and displays only facets with values.
+
+A selected value is appended to that index's existing `facetFilters`. Account for the additional facet-value request in analytics, rate estimates, and search-client mocks.
+
+### Result badges require retrieved attributes
+
+The new `resultBadgeKey` reads a property path from each hit. The default `attributesToRetrieve` list doesn't include custom badge properties. Add them to each relevant index's `searchParameters.attributesToRetrieve`.
+
+### Result markup and grouping changed
+
+V5 refreshes the modal and result markup, renders breadcrumbs, introduces source panels, and adds facet and badge elements. CSS selectors, DOM tests, snapshots, and custom overrides that target v4 internals can break.
+
+Use public component props for behavior and review [Styling](/docs/packages/css/styling) for visual changes.
+
+## Styles and builds
+
+### Ask AI styles have a separate source bundle
+
+The complete `@docsearch/css` stylesheet still imports button, modal, and Ask AI rules. React also exposes split style entries:
+
+- `@docsearch/react/style/variables`
+- `@docsearch/react/style/button`
+- `@docsearch/react/style/modal`
+- `@docsearch/react/style/askai`
+- `@docsearch/react/style/sidepanel`
+
+If you assemble styles by component, add `style/askai` for `DocSearchAI` or `DocSearchAskAiModal`.
+
+### Generated React file names changed
+
+The documented package subpaths remain stable, but their targets changed from names such as `dist/esm/DocSearchModal.js` to generated entry files such as `dist/esm/modal.js`. Imports that bypassed the package exports can break.
+
+### The React `main` field now points to ESM
+
+`@docsearch/react` changes `main` from `dist/umd/index.js` to `dist/esm/index.js`. Consumers that resolve `main` instead of the package exports need an ESM-compatible build pipeline. The explicit `unpkg` and `jsdelivr` fields continue to point to `dist/umd/index.js`.
+
+### The browser target is ES2017
+
+V5's tsdown builds target ES2017. Provide transpilation or polyfills if your browser support policy extends below that target.
+
+## Public controls
+
+### JavaScript instances don't expose Sidepanel state
+
+`DocSearchInstance` exposes `open`, `close`, `openAskAi`, `destroy`, `isReady`, and `isOpen`. It doesn't expose `openSidepanel`, `isSidepanelOpen`, or `isSidepanelSupported`.
+
+### React refs include Sidepanel controls
+
+`DocSearchRef` exposes the JavaScript-style modal controls plus `openSidepanel`, `isSidepanelOpen`, and `isSidepanelSupported`. `openSidepanel` does nothing until a Sidepanel view registers. On mobile, `openAskAi` and standard Ask AI actions fall back to the modal.
+
+See [hybrid mode](/docs/hybrid-mode) for the supported integration.
+
+### Deprecated keyboard hook fields remain
+
+`UseDocSearchKeyboardEventsProps.onInput` and `searchButtonRef` are accepted for compatibility but are deprecated and aren't used by the v5 React hook implementation.
+
+## Compatibility
+
+### React peer range
+
+`@docsearch/react`, `@docsearch/core`, `@docsearch/modal`, and `@docsearch/sidepanel` declare these optional peers:
+
+- `react`: `>=16.8.0 <20.0.0`
+- `react-dom`: `>=16.8.0 <20.0.0`
+- `@types/react`: `>=16.8.0 <20.0.0`
+
+`@docsearch/react` also accepts optional `search-insights` versions `>=1 <3`.
+
+### Package versions must match
+
+The `5.0.0-beta.0` packages depend on matching beta versions of the other DocSearch packages. Don't mix v4 and v5 packages in a Composable API or Sidepanel tree.
+
+### CSS remains a separate install for top-level integrations
+
+Install `@docsearch/css@^5.0.0-beta`, then import `@docsearch/css`. For a CDN integration, load `dist/style.css` from the same caret beta range.
+
+## Additive v5 APIs
+
+These additions aren't breaking by themselves, but they replace common v4 custom implementations:
+
+- `facets` and `DocSearchFacet` for keyword filters.
+- `resultBadgeKey` for hit metadata.
+- `DocSearchAI` and `DocSearchAskAiModal` for AI-capable React views.
+- `AgentStudioIndices` and `AgentStudioSearchControls` for dynamic search tools.
+- `ToolCalls` and `ToolDefinition` for custom Agent Studio tools.
+- `Memory` for user-scoped Agent Studio memory.
+- `PromptSuggestions` for keyword-query prompt suggestions.
+- Ask AI feedback tags and notes.
+- Split JavaScript, React, and style entries for smaller keyword-only builds.
diff --git a/packages/website/docs/what-is-docsearch.md b/packages/website/docs/what-is-docsearch.md
index 5b9cc3c9..cd0ecc17 100644
--- a/packages/website/docs/what-is-docsearch.md
+++ b/packages/website/docs/what-is-docsearch.md
@@ -1,24 +1,27 @@
---
title: What is DocSearch?
+description: Understand how DocSearch provides search for technical documentation.
sidebar_label: What is DocSearch?
---
## Why?
-We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+We created DocSearch because developers spend a lot of time reading documentation, and finding relevant information in large documentation sites can be difficult. Building good search is a challenge.
-It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+Algolia has extensive experience building search interfaces. We use that experience to extract content from technical documentation and make it searchable from the first keystroke.
-## Quick description
+## Overview
-We split DocSearch into a crawler and a frontend library.
+DocSearch has two independent parts: indexing and the frontend search experience.
-- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
-- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+- The [Algolia Crawler][4] extracts your documentation into an Algolia index. Use the [Crawler interface][5] to edit the crawler configuration, monitor crawls, and trigger new crawls.
+- The [DocSearch v5 packages][7] query that index and render keyword search or Ask AI in your frontend. They are built on [Algolia Autocomplete][6].
+
+Crawler configuration and record schema versions don't select the installed DocSearch frontend package version. You can update the frontend package without changing how the crawler is scheduled.
## How to feature DocSearch?
-DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+DocSearch is free for eligible documentation sites. Read [the eligibility requirements][2] and apply. After approval and indexing, add a [DocSearch v5 package][7] or a supported framework integration to your website. Keep the "Search by Algolia" link displayed.
DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
@@ -30,3 +33,4 @@ You can now [apply to the program][3]
[4]: https://www.algolia.com/products/search-and-discovery/crawler/
[5]: https://dashboard.algolia.com/crawler
[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[7]: /docs/packages/overview
diff --git a/packages/website/docs/who-can-apply.md b/packages/website/docs/who-can-apply.md
index 320814d0..317b2249 100644
--- a/packages/website/docs/who-can-apply.md
+++ b/packages/website/docs/who-can-apply.md
@@ -1,30 +1,32 @@
---
title: Who can apply?
+description: Check whether your documentation project is eligible for DocSearch.
---
-**Open for all developer documentation and technical blogs.**
+**Open to developer documentation and technical blogs.**
-We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all online technical documentations and technical blogs.
+We built DocSearch to improve search on large technical documentation sites. We offer the free DocSearch program to public technical documentation and technical blogs.
We usually turn down applications when they are not production ready or have non-technical content on the website.
## Application process
-To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+To [apply][1] to the DocSearch program, follow the onboarding process in the Algolia dashboard. Submit your domain for validation against the program requirements. If your domain meets the criteria, you can create your DocSearch crawler.
-- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+- Use one of our [supported integrations][3] or a [DocSearch v5 package][5] after your content is indexed.
-- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+- Verify your domain ownership within 7 days of approval to continue using the crawler.
-- β
Please review [DocSearch Plan Terms and Conditions][2].
+- Review the [DocSearch Plan Terms and Conditions][2].
## Process duration
-DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+The application process includes automated validation. If we can't determine your eligibility automatically, we'll conduct a manual review that may take one to two business days.
-Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+Once approved, continue the onboarding process to create your DocSearch crawler. After the crawler indexes your data, choose the frontend package or framework integration separately. Updating the frontend doesn't change your crawler or index format.
[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
[3]: integrations.md
[4]: https://alg.li/discord
+[5]: /docs/packages/overview
diff --git a/packages/website/docusaurus.config.mjs b/packages/website/docusaurus.config.mjs
index f1605941..8c70af8f 100644
--- a/packages/website/docusaurus.config.mjs
+++ b/packages/website/docusaurus.config.mjs
@@ -50,7 +50,10 @@ export default {
'https://github.com/algolia/docsearch/edit/main/packages/website/',
versions: {
current: {
- label: 'Latest (v4.x)',
+ label: 'Beta (v5.0.0-beta.x)',
+ },
+ v4: {
+ label: 'Stable (v4.x)',
},
v3: {
label: 'Legacy (v3.x)',
@@ -138,9 +141,9 @@ export default {
],
},
announcementBar: {
- id: 'announcement-bar',
+ id: 'docsearch-v5-beta',
content:
- 'π Get Ask AI now! Turn your docs site search into an AI-powered assistant β faster answers, fewer tickets, better self-serve. Get Started Now',
+ 'DocSearch 5.0.0-beta is available. Migrate from v4 or choose a package.',
},
colorMode: {
defaultMode: 'light',
@@ -165,8 +168,12 @@ export default {
to: 'docs/v3/docsearch',
},
{
- label: 'DocSearch v4 - Beta',
- to: 'docs/docsearch',
+ label: 'DocSearch v4',
+ to: 'docs/v4/docsearch',
+ },
+ {
+ label: 'DocSearch v5 beta',
+ to: 'docs/packages/overview',
},
],
},
diff --git a/packages/website/sidebars.js b/packages/website/sidebars.js
index cc5d370b..c4fbae84 100644
--- a/packages/website/sidebars.js
+++ b/packages/website/sidebars.js
@@ -13,19 +13,87 @@ export default {
{
type: 'category',
label: 'Introduction',
- items: ['what-is-docsearch', 'who-can-apply'],
+ items: [
+ 'what-is-docsearch',
+ 'who-can-apply',
+ 'migrating-from-v4',
+ 'v5-breaking-changes',
+ ],
},
{
type: 'category',
- label: 'DocSearch v4',
+ label: 'Packages',
items: [
- 'docsearch',
- 'docusaurus-adapter',
+ 'packages/overview',
+ {
+ type: 'category',
+ label: '@docsearch/js',
+ items: ['packages/js/getting-started', 'packages/js/api-reference'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/react',
+ items: [
+ 'packages/react/getting-started',
+ 'packages/react/api-reference',
+ 'packages/react/examples',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/modal',
+ items: ['packages/modal/overview', 'packages/modal/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel',
+ items: [
+ 'packages/sidepanel/getting-started',
+ 'packages/sidepanel/advanced-use-cases',
+ 'packages/sidepanel/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/sidepanel-js',
+ items: [
+ 'packages/sidepanel-js/getting-started',
+ 'packages/sidepanel-js/api',
+ ],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/css',
+ items: ['packages/css/styling', 'packages/css/bundle-exports'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/core',
+ items: ['packages/core/overview', 'packages/core/api'],
+ },
+ {
+ type: 'category',
+ label: '@docsearch/docusaurus-adapter',
+ items: [
+ 'packages/docusaurus-adapter/getting-started',
+ 'packages/docusaurus-adapter/configuration-reference',
+ 'packages/docusaurus-adapter/migrating-from-v4',
+ ],
+ },
'composable-api',
- 'styling',
- 'api',
- 'examples',
- 'migrating-from-v3',
+ 'hybrid-mode',
+ ],
+ },
+ {
+ type: 'category',
+ label: 'Agent Studio',
+ items: [
+ 'agent-studio/getting-started',
+ 'agent-studio/dynamic-indices',
+ 'agent-studio/tools',
+ 'agent-studio/memory',
+ 'agent-studio/prompt-suggestions',
+ 'agent-studio/feedback',
],
},
{
@@ -33,34 +101,6 @@ export default {
label: 'MCP',
items: ['mcp/overview', 'mcp/installation', 'mcp/usage'],
},
- {
- type: 'category',
- label: 'Algolia Ask AI',
- items: [
- 'v4/askai',
- 'v4/askai-api',
- 'v4/askai-prompts',
- 'v4/askai-whitelisted-domains',
- 'v4/askai-models',
- 'v4/askai-markdown-indexing',
- 'v4/askai-errors',
- {
- type: 'link',
- label: 'Full Documentation',
- href: 'https://www.algolia.com/doc/guides/algolia-ai/askai',
- },
- ],
- },
- {
- type: 'category',
- label: 'Sidepanel',
- items: [
- 'sidepanel/getting-started',
- 'sidepanel/advanced-use-cases',
- 'sidepanel/hybrid',
- 'sidepanel/api-reference',
- ],
- },
{
type: 'category',
label: 'Algolia Crawler',
diff --git a/packages/website/src/components/Home.js b/packages/website/src/components/Home.js
index a8a4ea86..ee5dbb91 100644
--- a/packages/website/src/components/Home.js
+++ b/packages/website/src/components/Home.js
@@ -116,9 +116,9 @@ function Home() {
+ eyebrow="Interactive demo"
+ title="See DocSearch in action"
+ />
diff --git a/packages/website/versioned_docs/version-v4/api.mdx b/packages/website/versioned_docs/version-v4/api.mdx
new file mode 100644
index 00000000..ecf87ebb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/api.mdx
@@ -0,0 +1,935 @@
+---
+title: API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+
+
+
+## `container`
+
+> `type: string | HTMLElement` | **required**
+
+The container for the DocSearch search box. You can either pass a [CSS selector][5] or an [Element][6]. If there are several containers matching the selector, DocSearch picks up the first one.
+
+## `environment`
+
+> `type: typeof window` | `default: window` | **optional**
+
+The environment in which your application is running.
+
+This is useful if youβre using DocSearch in a different context than `window`.
+
+
+
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `indices`
+
+> `type: Array`
+
+The list of indices and their _optional_ `searchParameters` to be used for keyword search.
+
+[Algolia Search Parameters][7]
+
+:::tip
+
+The ordering matters in the list, as results are ordered based on `indices` order.
+
+:::
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+
+
+
+```js
+docsearch({
+ // ...
+ indices: ['YOUR_ALGOLIA_INDEX'],
+ // ...
+});
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```js
+docsearch({
+ // ...
+ indices: [
+ {
+ name: 'YOUR_ALGOLIA_INDEX',
+ searchParameters: {
+ facetFilters: ['language:en'],
+ // ...
+ },
+ },
+ ],
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use custom `searchParameters` for the index
+
+```jsx
+
+```
+
+
+
+
+## `indexName`
+
+> `type: string` | **deprecated**
+
+:::warning[Deprecation warning]
+
+`indexName` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+Your Algolia index name.
+
+> While `indexName` is in deprecation, it is required to pass either `indices` or `indexName`. Not passing either will result in an `Error` being thrown.
+
+## `placeholder`
+
+> `type: string` | `default: "Search docs"` | **optional**
+
+The placeholder of the input of the DocSearch pop-up modal. Note: If you add a placeholder, it will replace the dynamic placeholder based on `askAi`. It would be better to edit [translations](#translations) instead.
+
+## `askAi`
+
+> `type: AskAiObject` | `string` | **optional**
+
+Your Algolia Assistant ID.
+
+
+
+
+```js
+docsearch({
+ // ...
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ // ...
+});
+```
+
+or if you want to use different credentials for `askAi` and add search parameters
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ indexName: 'ANOTHER_INDEX_NAME',
+ apiKey: 'ANOTHER_SEARCH_API_KEY',
+ appId: 'ANOTHER_APP_ID',
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ // Filtering parameters
+ facetFilters: ['language:en', 'version:latest'],
+ filters: 'type:content AND language:en',
+
+ // Content control parameters
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+
+ // Deduplication
+ distinct: true,
+ },
+
+ // Enables/disables showing suggested questions on Ask AI's new conversation screen
+ // NOTE: Only available with version >= 4.3
+ suggestedQuestions: true,
+ },
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+in case you want to use different credentials for `askAi`
+
+```jsx
+= 4.3
+ suggestedQuestions: true,
+ }}
+/>
+```
+
+
+
+
+:::tip[Ask AI supports these essential search parameters for optimal performance:]
+
+- **Filtering**: `facetFilters: ['type:content']` - Filter by language, version, or content type
+- **Complex filtering**: `filters: 'type:content AND language:en'` - Apply complex filtering rules
+- **Content control**: `attributesToRetrieve: ['title', 'content', 'url']` - Control which attributes are retrieved
+- **Search scope**: `restrictSearchableAttributes: ['title', 'content']` - Limit search to specific fields
+- **Deduplication**: `distinct: true` - Remove duplicate results (`boolean | number | string`)
+
+These parameters provide the essential functionality for Ask AI while keeping the API simple and focused.
+
+:::
+
+### `askAi.agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`askAi.agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `askAi.agentStudio` is `true`, the Ask AI chat will use Algolia's [Agent Studio][12] as the chat backend instead of the Ask AI backend. Learn more on [Algolia Agent Studio Docs][13].
+
+```js
+docsearch({
+ // ...
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+::::info[Search parameter shapes]
+
+- Standard Ask AI (`agentStudio` omitted or `false`): `searchParameters` is a flat object and supports `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- Agent Studio (`agentStudio: true`): `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+::::
+
+## `searchParameters`
+
+> `type: SearchParameters` | **optional** | **deprecated**
+
+:::warning[Deprecation warning]
+
+`searchParameters` is currently being planned for deprecation. The new recommended property to use is `indices`.
+
+:::
+
+The [Algolia Search Parameters][7].
+
+## `transformItems`
+
+> `type: function` | `default: items => items` | **optional**
+
+Receives the items from the search response, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them.
+
+
+
+
+```js
+docsearch({
+ // ...
+ transformItems(items) {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return items.map((item) => ({
+ ...item,
+ content: item.content.toUpperCase(),
+ }));
+ }}
+/>
+```
+
+
+
+
+## `hitComponent`
+
+> `type: ({ hit, children }, { html }) => JSX.Element | string | Function` | `default: Hit` | **optional**
+
+The component to display each item. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ hit, children }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ hit, children }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the `hit` object which contains all the data for the search result, and `children` which is the default rendered content.
+
+See the [default implementation][8].
+
+
+
+
+```js
+docsearch({
+ // ...
+ hitComponent({ hit, children }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+
+ ${children}
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ π
+ {children}
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `transformSearchClient`
+
+> `type: function` | `default: DocSearchTransformClient => DocSearchTransformClient` | **optional**
+
+Useful for transforming the [Algolia Search Client][10], for example to [debounce search queries][9]
+
+## `disableUserPersonalization`
+
+> `type: boolean` | `default: false` | **optional**
+
+Disable saving recent searches and favorites to the local storage.
+
+## `initialQuery`
+
+> `type: string` | **optional**
+
+The search input initial query.
+
+## `navigator`
+
+> `type: Navigator` | **optional**
+
+An implementation of [Algolia Autocomplete][1]βs Navigator API to redirect the user when opening a link.
+
+Learn more on the [Navigator API][11] documentation.
+
+## `translations`
+
+> `type: Partial` | `default: docSearchTranslations` | **optional**
+
+Allow translations of any raw text and aria-labels present in the DocSearch button or modal components.
+
+
+docSearchTranslations
+
+
+```ts
+const translations: DocSearchTranslations = {
+ button: {
+ buttonText: 'Search',
+ buttonAriaLabel: 'Search',
+ },
+ modal: {
+ searchBox: {
+ clearButtonTitle: 'Clear',
+ clearButtonAriaLabel: 'Clear the query',
+ closeButtonText: 'Close',
+ closeButtonAriaLabel: 'Close',
+ placeholderText: undefined, // fallback: 'Search docs' or 'Search docs or ask AI a question'
+ placeholderTextAskAi: undefined, // fallback: 'Ask another question...'
+ placeholderTextAskAiStreaming: 'Answering...',
+ // can only be one of the following
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/enterkeyhint#value
+ enterKeyHint: 'search',
+ enterKeyHintAskAi: 'enter',
+ searchInputLabel: 'Search',
+ backToKeywordSearchButtonText: 'Back to keyword search',
+ backToKeywordSearchButtonAriaLabel: 'Back to keyword search',
+ newConversationPlaceholder: 'Ask a question',
+ conversationHistoryTitle: 'My conversation history',
+ startNewConversationText: 'Start a new conversation',
+ viewConversationHistoryText: 'Conversation history'
+ },
+ startScreen: {
+ recentSearchesTitle: 'Recent',
+ noRecentSearchesText: 'No recent searches',
+ saveRecentSearchButtonTitle: 'Save this search',
+ removeRecentSearchButtonTitle: 'Remove this search from history',
+ favoriteSearchesTitle: 'Favorite',
+ removeFavoriteSearchButtonTitle: 'Remove this search from favorites',
+ recentConversationsTitle: 'Recent conversations',
+ removeRecentConversationButtonTitle:
+ 'Remove this conversation from history',
+ },
+ errorScreen: {
+ titleText: 'Unable to fetch results',
+ helpText: 'You might want to check your network connection.',
+ },
+ noResultsScreen: {
+ noResultsText: 'No results found for',
+ suggestedQueryText: 'Try searching for',
+ reportMissingResultsText: 'Believe this query should return results?',
+ reportMissingResultsLinkText: 'Let us know.',
+ },
+ resultsScreen: {
+ askAiPlaceholder: 'Ask AI: ',
+ noResultsAskAiPlaceholder: 'Didn't find it in the docs? Ask AI to help: ',
+ },
+ askAiScreen: {
+ disclaimerText:
+ 'Answers are generated with AI which can make mistakes. Verify responses.',
+ relatedSourcesText: 'Related sources',
+ thinkingText: 'Thinking...',
+ copyButtonText: 'Copy',
+ copyButtonCopiedText: 'Copied!',
+ copyButtonTitle: 'Copy',
+ likeButtonTitle: 'Like',
+ dislikeButtonTitle: 'Dislike',
+ thanksForFeedbackText: 'Thanks for your feedback!',
+ preToolCallText: 'Searching...',
+ duringToolCallText: 'Searching for ',
+ afterToolCallText: 'Searched for',
+ // If provided, these override the default rendering of aggregated tool calls:
+ aggregatedToolCallNode: undefined, // (queries: string[], onSearchQueryClick: (query: string) => void) => React.ReactNode
+ aggregatedToolCallText: undefined, // (queries: string[]) => { before?: string; separator?: string; lastSeparator?: string; after?: string }
+ // Text to show when user has stopped streaming a message
+ stoppedStreamingText: 'You stopped this response',
+ },
+ footer: {
+ selectText: 'Select',
+ submitQuestionText: 'Submit question',
+ selectKeyAriaLabel: 'Enter key',
+ navigateText: 'Navigate',
+ navigateUpKeyAriaLabel: 'Arrow up',
+ navigateDownKeyAriaLabel: 'Arrow down',
+ closeText: 'Close',
+ backToSearchText: 'Back to search',
+ closeKeyAriaLabel: 'Escape key',
+ poweredByText: 'Powered by',
+ },
+ newConversation: {
+ newConversationTitle: 'How can I help you today?',
+ newConversationDescription: 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.'
+ }
+ },
+};
+```
+
+
+
+
+## `getMissingResultsUrl`
+
+> `type: ({ query: string }) => string` | **optional**
+
+Function to return the URL of your documentation repository.
+
+
+
+
+```js
+docsearch({
+ // ...
+ getMissingResultsUrl({ query }) {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
+ }}
+/>
+```
+
+
+
+
+When provided, an informative message wrapped with your link will be displayed on no results searches. The default text can be changed using the [translations](#translations) property.
+
+
+
+
+
+## `keyboardShortcuts`
+
+> `type: KeyboardShortcuts` | **optional**
+
+Configuration for keyboard shortcuts that trigger the search modal.
+
+### Default behavior:
+
+- `Ctrl/Cmd+K` - Opens and closes the search modal
+- `/` - Opens the search modal (doesn't close)
+
+### Interface:
+
+```typescript
+interface KeyboardShortcuts {
+ 'Ctrl/Cmd+K'?: boolean; // default: true
+ '/'?: boolean; // default: true
+}
+```
+
+
+
+
+```js
+// Default - all shortcuts enabled
+docsearch({
+ // ...
+});
+
+// Disable slash shortcut
+docsearch({
+ // ...
+ keyboardShortcuts: { '/': false },
+});
+
+// Disable Ctrl/Cmd+K shortcut (also hides button hint)
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false },
+});
+
+// Disable all keyboard shortcuts
+docsearch({
+ // ...
+ keyboardShortcuts: { 'Ctrl/Cmd+K': false, '/': false },
+});
+```
+
+
+
+
+
+```jsx
+{
+ /* Default - all shortcuts enabled */
+}
+ ;
+
+{
+ /* Disable slash shortcut */
+}
+ ;
+
+{
+ /* Disable Ctrl/Cmd+K shortcut (also hides button hint) */
+}
+ ;
+
+{
+ /* Disable all keyboard shortcuts */
+}
+ ;
+```
+
+
+
+
+:::info[Keyboard Shortcut Behavior]
+
+- **Ctrl/Cmd+K**: Toggle shortcut that both opens and closes the modal
+- **/**: Character shortcut that only opens the modal (prevents interference with search typing)
+- **Escape**: Always works to close the modal regardless of Configuration
+
+:::
+
+## `resultsFooterComponent`
+
+> `type: ({ state }, { html }) => JSX.Element | string | Function` | **optional**
+
+The component to display below the search results. Supports template patterns:
+
+- **HTML strings with html helper** (recommended for JS CDN): `({ state }, { html }) => html...`
+- **JSX templates** (for React/Preact): `({ state }) => ...`
+- **Function-based templates**: `(props) => string | JSX.Element | Function`
+
+You get access to the [current state](https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/types/AutocompleteState.ts) which allows you to retrieve the number of hits returned, the query etc.
+
+
+
+
+```js
+docsearch({
+ // ...
+ resultsFooterComponent({ state }, { html }) {
+ // Using HTML strings with html helper
+ return html`
+
+ `;
+ },
+});
+```
+
+
+
+
+
+```jsx
+ {
+ // Using JSX templates
+ return (
+
+ );
+ }}
+/>
+```
+
+
+
+
+## `maxResultsPerGroup`
+
+> `type: number` | **optional**
+
+The maximum number of results to display per search group. Default is 5.
+
+[You can find a working example without JSX in this sandbox](https://codesandbox.io/s/docsearch-v3-maxresultspergroup-without-jsx-ct9m22?file=/src/index.js)
+
+
+
+
+```js
+docsearch({
+ // ...
+ maxResultsPerGroup: 7,
+});
+```
+
+
+
+
+
+## `recentSearchesLimit`
+
+> `type: number` | `default: 7` | **optional**
+
+The maximum number of recent searches that are stored for the user. Default is 7.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesLimit: 12,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `recentSearchesWithFavoritesLimit`
+
+> `type: number` | `default: 4` | **optional**
+
+The maximum number of recent searches that are stored when the user has favorited searches. Default is 4.
+
+
+
+
+```js
+docsearch({
+ // ...
+ recentSearchesWithFavoritesLimit: 5,
+ // ...
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+## `portalContainer` (React-only)
+
+> `type: Element | DocumentFragment` | `default: document.body` | **optional**
+
+The element where the DocSearch modal will be portaled. Use this when you need the overlay to render in a custom DOM nodeβfor example when working inside a shadow root, a specific layout container, or a modal manager. When omitted, the modal portals to `document.body`.
+
+:::warning
+
+This prop only exists in `@docsearch/react`. If you are using **`@docsearch/js`**, use the [`container`](#container) option insteadβthe value you pass there is both the **mount point** of the search button _and_ the portal target for the modal.
+
+:::
+
+
+
+
+```jsx
+// assume you have a dedicated modal root in your html
+;
+
+const portalEl = document.getElementById('modal-root');
+
+ ;
+```
+
+
+
+
+
+```js
+docsearch({
+ // the element that will **contain the button** and **host the modal portal**
+ container: '#modal-root',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+});
+```
+
+
+
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[6]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[7]: https://www.algolia.com/doc/api-reference/search-api-parameters/
+[8]: https://github.com/algolia/docsearch/blob/main/packages/docsearch-react/src/Hit.tsx
+[9]: https://codesandbox.io/s/docsearch-v3-debounced-search-gnx87
+[10]: https://www.algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/?client=javascript
+[11]: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/keyboard-navigation/
+[12]: https://www.algolia.com/products/ai/agent-studio
+[13]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/composable-api.mdx b/packages/website/versioned_docs/version-v4/composable-api.mdx
new file mode 100644
index 00000000..314b6e1b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/composable-api.mdx
@@ -0,0 +1,315 @@
+---
+title: Composable API
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+The Composable API is available from version `>= 4.3`
+:::
+
+DocSearch has a new Composable API for rendering the DocSearch button and modal. This API was
+introduced to help with more explicit control over where and how the components are rendered within a page.
+
+## Introduction
+
+The Composable API was introduced to help give more flexibility on how you render and use DocSearch on your website. With it,
+you have more control of where, when and how you want to bundle the components and render them.
+
+With Composable API comes two new NPM packages:
+
+- `@docsearch/core` - Shared core logic for managing different states of DocSearch
+- `@docsearch/modal` - The actual components used for the DocSearch Modal
+
+:::warning
+Because of the nature of composability, this API is only available within React, and not within the `@docsearch/js` package.
+:::
+
+## Getting Started
+
+In order to start using the Composable API, you will need to install the following three packages:
+
+
+
+
+```bash
+npm install @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/core @docsearch/modal @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+The most simple implementation would be as follows:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+:::info
+The actual components MUST be rendered within the `` Provider in order for them to communicate with the global state.
+:::
+
+This setup is slightly more involved with now rendering three different components:
+
+- `` is the parent element which controls and shares all state with the child components
+- ` ` is the actual button element that is rendered and triggers the DocSearch Modal to open
+- ` ` is the main modal containing the search form, search results, and Ask AI
+
+
+### Ask AI
+
+Using Ask AI with the Composable API is quite similar to the normal way of using DocSearch. All that is needed is the `askAi` configuration:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import '@docsearch/css/style.css';
+
+export function Search() {
+ return (
+
+
+
+
+ );
+}
+```
+
+You can find more information on Ask AI, and its setup in its [dedicated docs][2].
+
+### Advanced
+
+```tsx
+export default function AdvancedSearch(): JSX.Element {
+ return (
+
+
+
+
+ );
+}
+```
+
+### Bundle saving exports
+
+To help aid in trimming initial bundle size, the `@docsearch/modal` package exposes explicit file exports as well:
+
+```ts
+import { DocSearchButton } from '@docsearch/modal/button';
+import { DocSearchModal } from '@docsearch/modal/modal';
+```
+
+Here is a basic example of delaying the loading of the `DocSearchModal` code until the search button is clicked:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton } from '@docsearch/modal/button';
+import type { DocSearchModal as DocSearchModalType } from '@docsearch/modal/modal';
+import { useState } from 'react';
+
+let DocSearchModal: typeof DocSearchModalType | null = null;
+
+async function importDocSearchModalIfNeeded() {
+ if (DocSearchModal) {
+ return;
+ }
+
+ const { DocSearchModal: Modal } = await import('@docsearch/modal/modal');
+
+ DocSearchModal = Modal;
+}
+
+export default function DynamicModal() {
+ const [modalLoaded, setModalLoaded] = useState(false);
+
+ const loadModal = () => {
+ importDocSearchModalIfNeeded().then(() => {
+ setModalLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {modalLoaded && DocSearchModal && (
+
+ )}
+
+ );
+}
+```
+
+## Components
+
+### ` `
+
+The ` ` component from the `@docsearch/core` package is the main state handler for all of DocSearch.
+It utilizes [React Context][1] to enable sharing its state across nested components.
+
+#### Props
+
+```ts
+interface DocSearchProps {
+ // React children to be rendered within the DocSearch Provider
+ children: Array | JSX.Element | React.ReactNode | null;
+ // Theme to be set enabling style changes for `light` or `dark` themes
+ theme?: 'light' | 'dark';
+ // Initial starting query for keyword search
+ initialQuery?: string;
+ // Manage supported keyboard shortcuts for opening/closing the DocSearch Modal
+ keyboardShortcuts?: {
+ 'Ctrl/Cmd+K': boolean,
+ '/': boolean,
+ };
+}
+```
+
+### ` `
+
+The main DocSearch search button to trigger the DocSearch Modal.
+
+#### Props
+
+```ts
+interface DocSearchButtonProps {
+ // Optional callback for when the button is clicked. The original click event is passed.
+ onClick?: (event: React.MouseEvent) => void;
+ // Translation strings specific to the button.
+ translations: {
+ buttonText?: string;
+ buttonAriaLabel?: string;
+ };
+}
+```
+
+### ` `
+
+The main keyword search Modal used to search your documentation.
+
+#### Props
+
+```ts
+interface DocSearchModalProps {
+ /**
+ * Algolia application id used by the search client.
+ */
+ appId: string;
+ /**
+ * Public api key with search permissions for the index.
+ */
+ apiKey: string;
+ /**
+ * Name of the algolia index to query.
+ *
+ * @deprecated `indexName` will be removed in a future version. Please use `indices` property going forward.
+ */
+ indexName?: string;
+ /**
+ * List of indices and _optional_ searchParameters to be used for search.
+ *
+ * @see {@link https://docsearch.algolia.com/docs/api#indices}
+ */
+ indices?: Array;
+ /**
+ * Configuration or assistant id to enable ask ai mode. Pass a string assistant id or a full config object.
+ */
+ askAi?: DocSearchAskAi | string;
+ // ...
+}
+```
+
+More property documentation can be found in the [DocSearch API Reference][3] page.
+
+[1]: https://react.dev/reference/react/createContext
+[2]: /docs/v4/v4/askai
+[3]: /docs/api
diff --git a/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
new file mode 100644
index 00000000..cc913ea4
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler-configuration-visual.mdx
@@ -0,0 +1,96 @@
+---
+title: New Crawler UI/UX
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+The Algolia Crawler Visual UI provides an updated, user-friendly way to manage your crawl settings and monitor your indexing process. This guide covers the main features of the new interface.
+
+## DocSearch Tab
+
+The Crawler UI now includes a dedicated **DocSearch** tab. This tab provides everything you need to implement DocSearch on your site, including:
+
+- **Implementation code**: Copy-paste ready code snippets for integrating DocSearch into your frontend.
+- **API keys**: Your unique Application ID and Search API Key for connecting to your Algolia index.
+- **Quick links**: Access to review your records, explore documentation, and join the support Discord.
+
+
+
+
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `Monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+You can update your crawler configuration in two ways:
+
+**Visual Configuration UI:**
+Quickly edit common options without writing code using the new Visual Configuration interface.
+
+
+
+
+
+**Code Editor:**
+For advanced configuration, use the live code editor to directly modify your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to debug selectors or see how the crawler interprets your site.
+
+
+
+
+
+## Suggestions
+
+The **Suggestions** section in the Crawler UI provides actionable feedback to help you improve your crawl and data extraction. After each crawl, you'll see recommendations for:
+
+- Fixing redirect or domain issues
+- Addressing ignored or failed URLs
+- Adding missing sitemaps
+
+Each suggestion includes a description, a solution, and quick links to relevant documentation or monitoring tools, so you can resolve issues efficiently and optimize your search experience.
+
+
+
+
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/crawler.mdx b/packages/website/versioned_docs/version-v4/crawler.mdx
new file mode 100644
index 00000000..f2e4b3f9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/crawler.mdx
@@ -0,0 +1,120 @@
+---
+title: DocSearch x Algolia Crawler
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][3] team know.
+
+You can also read our [Crawler FAQ](https://www.algolia.com/doc/tools/crawler/troubleshooting/crawl-status/), to understand how it behaves:
+
+- [One of my pages wasn't crawled](https://www.algolia.com/doc/tools/crawler/troubleshooting/extraction-issues/#a-page-wasnt-crawled)
+- [Why are my pages skipped?](https://www.algolia.com/doc/tools/crawler/troubleshooting/fetching-issues/)
+
+For questions related to the DocSearch program, please see our [DocSearch program FAQ](/docs/docsearch-program).
+
+## How often will you crawl my website?
+
+Crawls are scheduled at a random time once a week. You can [configure this schedule from the config file](https://www.algolia.com/doc/tools/crawler/apis/configuration/schedule/) or trigger one manually from [the Crawler interface][2].
+
+## Why do I have duplicate content in my results?
+
+This can happen when you have more than one URL pointing to the same content, for example with `./docs`, `./docs/` and `./docs/index.html`.
+
+We recommend configuring canonical URLs on your website, you can read more on the ["Consolidate duplicate URLs" guide by Google](https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls).
+
+Ultimately, it is possible to set the [`exclusionPatterns`](https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/) to all the patterns you want to exclude.
+
+## Are the [`docsearch-scraper`](https://github.com/algolia/docsearch-scraper) and [`docsearch-configs`](https://github.com/algolia/docsearch-configs) repository still maintained?
+
+We've deprecated our legacy infrastructure, but you can still use it to [run your own instance](/docs/legacy/run-your-own) and plug it to [DocSearch v3](/docs/v3/docsearch)!
+
+## How to migrate
+
+> Every owner should have received a migration email from Algolia with the details. If you were not part of the previous `index` owners, or the maintainer has changed, you can request access via [our support page](https://www.algolia.com/support/).
+
+All the steps are detailed in the email you've received, but in order to use the new infrastructure you need to:
+
+- Join the Algolia application with the invite included in the email
+- Update your frontend integration with the credentials received in the email.
+
+
+
+
+```js app.js
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_NEW_ALGOLIA_APP_ID',
+ apiKey: 'YOUR_NEW_ALGOLIA_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME', // it does not change
+});
+```
+
+
+
+
+
+```jsx App.js
+
+```
+
+
+
+
+
+## What should I do with my legacy config and credentials?
+
+You can forget about them, we will do the cleaning once all of our users have migrated to the new infrastructure!
+
+You should use [the dedicated web interface][2] to make any changes to your index.
+
+## Why do I see two Algolia apps in my dashboard?
+
+We did not remove access to the legacy DocSearch application (`BH4D9OD16A`) to give you the time to get familiar with our new infrastructure. `BH4D9OD16A` will remain available until the migration has been completed for all the DocSearch users.
+
+## Search yields no results
+
+If your search does not yield any results, but there is no error in [your browser developer tools](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), there might be an issue with your index.
+
+Make sure that:
+
+1. [Your Crawler config](/docs/record-extractor) matches your website structure
+
+We provide [config templates](/docs/templates) for many website generators, but you can also use them as a base. To debug your selectors, we recommend using [the URL tester](/docs/manage-your-crawls/#url-tester).
+
+2. Your index settings are up to date (you'll see a banner in [the search preview](/docs/manage-your-crawls/#search-preview) if not)
+
+The Crawler only applies `index settings` at index creation time, to keep the Algolia dashboard as the source of truth. If you have drastically changed your config, or moved to a website generator, we recommend you to delete your index from the Algolia dashboard before starting a new crawl.
+
+## Can I delete my crawler?
+
+No. Well, you can but once you do things will not work correctly. We automatically create a default crawler that is associated with your DocSearch application and deleting it with the intention of creating a new one will not work as expected.
+
+## What if I delete my DocSearch Crawler?
+
+The fastest way will be to connect with us on our [Discord](https://alg.li/discord). Alternatively, email us at the address below and we will get to it as soon as we can.
+
+## Can I use the Crawler on password protected sites?
+
+The Crawler as used with DocSearch applications cannot be used for password protected sites that require a login. If you need this functionality, you need to utilize a regular Algolia plan https://www.algolia.com/pricing and add a crawler to it. Note that while it is free to add a pay-as-you-go crawler, the free tier does have limitations.
+
+## Links related to the migration
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+[1]: https://alg.li/discord
+[2]: https://dashboard.algolia.com/crawler
+[3]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/create-crawler.mdx b/packages/website/versioned_docs/version-v4/create-crawler.mdx
new file mode 100644
index 00000000..5e7c5124
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/create-crawler.mdx
@@ -0,0 +1,78 @@
+---
+title: Create a New Crawler
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+# Create a New Crawler
+
+:::info
+New DocSearch apps created after **July 2nd, 2024** can now use the Algolia Crawler UI to set up and manage their crawls. This guide walks you through the process of adding your domain, verifying ownership, creating a crawler, and running your first test crawl. You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+
+If you signed up before July 2nd, 2024, you can still use the Crawler UI, but creating and managing a Crawler is more streamlined for users who joined after that date.
+
+Learn more about the [New Crawler UI/UX features](./crawler-configuration-visual).
+:::
+
+## Add domains
+
+1. Sign in to the [Algolia dashboard](https://dashboard.algolia.com/crawler).
+2. In the left sidebar, select **Data sources**.
+3. Select **Crawler**:
+ - Click **Add your domain** and enter the domains or subdomains you want to crawl (e.g., `example.com`, `www.example.com`).
+ - If youβve already added a domain, click the **Domains** tab.
+4. Click **Add domain**.
+
+
+
+
+
+> **Note:** You must verify your domain within a 7-day grace period after adding it. Additionally, your domain must be approved for use by the DocSearch team before you can proceed with crawling.
+
+## Verify your domain
+
+You must verify ownership of each domain you want to crawl. The default method is email verification, but you can also use a meta tag, HTML file, robots.txt, or DNS record.
+
+### Meta tag
+1. In the **Meta tag** tab, click **Copy** to copy the verification tag.
+2. Add the tag to your site's `` section.
+3. Publish your site and click **Verify now** in the Crawler dashboard.
+
+### HTML file
+1. In the **HTML file** tab, click **Copy** to copy the verification file content.
+2. Save it as a new HTML file and upload it to your web server.
+3. Add the fileβs URL in the dashboard and click **Verify now**.
+
+### robots.txt
+1. In the **Robots.txt** tab, click **Copy** to copy the verification code.
+2. Paste it into your site's `robots.txt` file.
+3. Publish and click **Verify now**.
+
+### DNS
+1. In the **DNS** tab, copy the provided DNS TXT record.
+2. Add it to your DNS providerβs settings.
+3. Click **Verify now** after the record propagates (may take up to 72 hours).
+
+## Create a new crawler
+
+Once your domain is verified and approved by our DocSearch team:
+1. Go to the **Crawler** page in the dashboard.
+2. Click **New Crawler** and fill in:
+ - **Crawler name** (descriptive)
+ - **App ID** (your Algolia application ID)
+ - **Start URL** (usually your home page)
+ - **Crawler template** (choose a template or default)
+3. Click **Create** to finish and run a test crawl.
+
+## Run the test crawl
+
+The initial crawl will visit up to 100 URLs to test access and extraction. You can monitor progress in the **Overview** page. After completion, review the extracted records in the Algolia dashboard.
+
+## Next steps
+
+- Edit your crawler configuration for scheduled crawls, inclusion/exclusion rules, and extraction settings.
+- Use the Crawlerβs suggestions for further optimization.
+- For more details, see the [official Algolia documentation](https://www.algolia.com/doc/tools/crawler/getting-started/create-crawler/).
\ No newline at end of file
diff --git a/packages/website/versioned_docs/version-v4/docsearch-program.md b/packages/website/versioned_docs/version-v4/docsearch-program.md
new file mode 100644
index 00000000..29d65ae2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch-program.md
@@ -0,0 +1,131 @@
+---
+title: DocSearch program
+---
+
+If you're not finding the answer to your question on this website, this page will help you. If you're still unsure, don't hesitate to connect with us on [Discord][1] or let our [support][4] team know.
+
+For questions related to the DocSearch x Algolia Crawler, please see our [Crawler FAQ](/docs/crawler).
+
+## What do I need to install on my side?
+
+You just need to [implement DocSearch in your frontend](/docs/docsearch) with the credentials received by email when your application has been deployed.
+
+DocSearch leverages the [Algolia Crawler](https://www.algolia.com/products/search-and-discovery/crawler/), which offers a web [interface](https://dashboard.algolia.com/crawler) to create, monitor, edit, start your Crawlers. If you have any questions regarding it, please see our [Crawler FAQ](/docs/crawler).
+
+## How much does it cost?
+
+It's free!
+
+We know that paying for search infrastructure is a cost not all open source projects can afford. That's why we decided to keep DocSearch free for everyone. All we ask in exchange is that you keep the "Search by [Algolia][2]" logo displayed next to the search results.
+
+If this is not possible for you, you're free to [open your own Algolia account](https://www.algolia.com/pricing) and run [DocSearch on your own][3] without this limitation. In that case, though, depending on the size of your documentation, you might need a paid account (free accounts can hold as much as 10k records).
+
+## What data are you collecting?
+
+We save the data we extract from your website markup, which we put in a custom JSON format instead of HTML. This is the data we put in the Algolia DocSearch index. The selectors in your config define what data to scrape.
+
+As the website owner, we also give you access to your own Algolia application. This will let you see how your website is indexed in Algolia, detailed analytics about the anonymized searches in your website, team managements, and more!
+
+## Where is my data hosted?
+
+We host the DocSearch data on Algolia's servers, with replications around the globe. You can find more details about the actual [server specs here](https://www.algolia.com/doc/guides/infrastructure/servers/), and more complete information in our [privacy policy](https://www.algolia.com/policies/privacy).
+
+## How do I upgrade my DocSearch app?
+
+Depending on what you are looking for you have a few options!
+
+### Upgrade #1: I want a specific feature, like Rules, added to my existing DocSearch application
+
+[Reach out to us](https://algolia.com/support) and we may be able to help!
+
+### Upgrade #2: I want to remove the Algolia logo
+
+This would disqualify you from the free DocSearch program. We do offer an open-source
+[legacy version](https://docsearch.algolia.com/docs/legacy/run-your-own) of the DocSearch Crawler that you can use and
+host yourself or you can use our [API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript) but you will need to use a new Algolia application and pay for its usage.
+
+### Upgrade #3: Algolia is awesome, I want to use it for my whole site
+
+That's awesome! Please reach out to our [sales team](https://www.algolia.com/contactus/)
+who can help you figure out the right plan for you. Once you have your new application
+created you can simply copy and paste [your Crawler config](https://docsearch.algolia.com/docs/templates) into your new application's
+Crawler.
+
+## Can I use DocSearch on non-doc pages?
+
+The free DocSearch we provide will **only** crawl open-source projects documentation pages or technical blogs. To use it on other parts of your website, you'll need to create your own Algolia account and either:
+
+- Run the [DocSearch crawler][3] on your own
+- Use one of our other [framework integrations or API clients](https://www.algolia.com/doc/api-client/getting-started/install/javascript/?client=javascript)
+
+## Can you index code samples?
+
+Yes, but we do not recommend it.
+
+Code samples are a great way for humans to understand how people use a specific method. It often requires boilerplate code though, repeated across examples, which adds noise to the results.
+
+## A documentation website I like does not use DocSearch. What can I do?
+
+We'd love to help!
+
+If one of your favorite tool documentation websites is missing DocSearch, we encourage you to file an issue in their repository explaining how DocSearch could help. Feel free to [let us know on Discord][1] as well and we'll provide all the help we can.
+
+## How did we build this website?
+
+We build this website with [Docusaurus v2](https://docusaurus.io/). We were helped by a great man who inspired us a lot, Endi. We want [to pay a tribute to this exceptional human being that will be always part of the DocSearch project](https://docusaurus.io/blog/2020/01/07/tribute-to-endi). Rest in peace mate!
+
+## Can I share the `apiKey` in my repo?
+
+The `apiKey` the DocSearch team provides is [a search-only key](https://www.algolia.com/doc/guides/security/api-keys/#search-only-api-key) and can be safely shared publicly. You can track it in your version control system (e.g. git). If you are running the scraper on your own, please make sure to create a search-only key and [do not share your Admin key](https://www.algolia.com/doc/guides/security/api-keys/#admin-api-key).
+
+## Why is the email API key different in the dashboard?
+
+Every Algolia app comes with a default "Search API Key" which can be seen in the dashboard. That key allow you to list indices, settings, and search on **every** index owned by your application. In the case of a DocSearch application, in your acceptance email we provide a search **ONLY** API key scoped to only your DocSearch index. If for any reason you need to recover the API key sent in the email, just connect with our [support](https://algolia.com/support) team.
+
+## How do I rotate my API keys?
+
+Please reach out to our [support](https://algolia.com/support) team.
+
+## Can I have multiple projects under the same Algolia application?
+
+We recommend having a single Algolia application per project. Please [apply](https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply) if you'd like to use DocSearch in an other project of yours.
+
+### Why?
+
+The information of the initially applied project is used everywhere when we deploy your app:
+
+- The scope of your API keys
+- The name of your Algolia application/Crawler
+- The indices we generate
+- The allowed domains of your Crawler
+
+This allows us to easily scope issues when reaching out for support.
+
+## Support
+
+:::caution
+
+Please make sure to **first read the documentation before reaching out**.
+
+Here are some links to help you:
+
+- [The Algolia Crawler documentation](https://www.algolia.com/doc/tools/crawler/getting-started/overview/)
+- [The Algolia Crawler FAQ](/docs/crawler)
+- [The DocSearch FAQ](/docs/docsearch-program)
+- [The Algolia documentation](https://www.algolia.com/doc/)
+
+You can also take a look at [the Algolia academy](https://academy.algolia.com/trainings) to understand more about Algolia.
+
+:::
+
+Please be informed that while Algolia does not provide support for DocSearch itself, we can support requests for the following products:
+
+- The Algolia Crawler, reach out [via the support page](https://algolia.com/support).
+- The Algolia Dashboard, reach out [via the support page](https://algolia.com/support).
+
+For any issue related to [the DocSearch UI library](https://github.com/algolia/docsearch), please open a [GitHub issue](https://github.com/algolia/docsearch/issues).
+
+[1]: https://alg.li/discord
+[2]: https://www.algolia.com/
+[3]: /docs/legacy/run-your-own
+[4]: https://support.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/docsearch.mdx b/packages/website/versioned_docs/version-v4/docsearch.mdx
new file mode 100644
index 00000000..9c17704f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docsearch.mdx
@@ -0,0 +1,418 @@
+---
+title: Getting Started with v4
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+DocSearch v4 provides a significant upgrade over previous versions, offering enhanced accessibility, responsiveness, and an improved search experience for your documentation. Built on [Algolia Autocomplete][1], DocSearch v4 ensures a seamless integration trusted by leading documentation sites worldwide.
+
+## Installation
+
+> Looking for the Composable API documentation? You can find it [here][17].
+
+DocSearch packages are available on the [npm registry][10].
+
+### Docusaurus users
+
+If your docs site is powered by Docusaurus, use [`@docsearch/docusaurus-adapter`](/docs/docusaurus-adapter) for the latest DocSearch features (including new Ask AI capabilities such as sidepanel support), while keeping `@docusaurus/preset-classic`.
+
+
+
+
+```bash
+yarn add @docsearch/js@4
+# or with npm
+npm install @docsearch/js@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+```bash
+yarn add @docsearch/react@4
+# or
+npm install @docsearch/react@4
+```
+
+### Without package manager
+
+Include CSS in your website's ``:
+
+```html
+
+```
+
+And the JavaScript at the end of your ``:
+
+```html
+
+```
+
+
+
+
+
+### Optimize first query performance
+
+Enhance your users' first search experience by using `preconnect`, see [Performance optimization](#preconnect) below
+
+## Implementation
+
+
+
+
+DocSearch requires a dedicated container in your HTML
+
+```html
+
+```
+
+Initialize DocSearch by passing your container:
+
+```js app.js
+import docsearch from '@docsearch/js';
+
+import '@docsearch/css';
+
+docsearch({
+ container: '#docsearch',
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+});
+```
+
+DocSearch generates an accessible, fully-functional search input for you automatically.
+
+
+
+
+
+Integrating DocSearch into your React app is straightforward:
+
+```jsx App.js
+import { DocSearch } from '@docsearch/react';
+
+import '@docsearch/css';
+
+function App() {
+ return (
+
+ );
+}
+
+export default App;
+```
+
+DocSearch generates a fully accessible search input out-of-the-box.
+
+
+
+
+
+### Quick Testing (without credentials)
+
+If you'd like to test DocSearch immediately without your own credentials, use our demo configuration:
+
+
+
+
+```js
+docsearch({
+ appId: 'PMZUYBQDAK',
+ apiKey: '24b09689d5b4223813d9b8e48563c8f6',
+ indexName: 'docsearch',
+ askAi: 'askAIDemo',
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+Or use our new dedicated [DocSearch Playground](https://community.algolia.com/docsearch-playground/)
+
+### Using DocSearch with Ask AI
+
+DocSearch v4 introduces support for Ask AI, Algolia's advanced, AI-powered search capability. Ask AI enhances the user experience by providing contextually relevant and intelligent responses directly from your documentation. You can also use the same `askAi` configuration object to route chat through Agent Studio.
+
+To enable Ask AI, you can add your Algolia Assistant ID as a string, or use an object for more advanced configuration (such as specifying a different index, credentials, search parameters, or enabling Agent Studio):
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: 'YOUR_ALGOLIA_ASSISTANT_ID',
+});
+```
+
+
+
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ indexName: 'YOUR_MARKDOWN_INDEX', // Optional: use a different index for Ask AI
+ apiKey: 'YOUR_SEARCH_API_KEY', // Optional: use a different API key for Ask AI
+ appId: 'YOUR_APP_ID', // Optional: use a different App ID for Ask AI
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'], // Optional: filter Ask AI context
+ },
+ suggestedQuestions: true // Optional: enable loading suggested questions on the Ask AI new conversation screen
+ },
+});
+```
+
+
+
+
+- Use the string form for a simple setup.
+- Use the object form to customize which index, credentials, or filters Ask AI uses.
+- The suggested questions feature is controlled on the [Dashboard](https://dashboard.algolia.com) in the Ask AI section.
+
+### Using Agent Studio with DocSearch
+
+To use [Algolia Agent Studio](https://www.algolia.com/doc/guides/algolia-ai/agent-studio) as the chat backend, set `agentStudio: true` inside the `askAi` object.
+
+```js
+docsearch({
+ appId: 'YOUR_APP_ID',
+ indexName: 'YOUR_INDEX_NAME',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ agentStudio: true,
+ searchParameters: {
+ YOUR_INDEX_NAME: {
+ filters: 'type:content AND language:en',
+ attributesToRetrieve: ['title', 'content', 'url'],
+ restrictSearchableAttributes: ['title', 'content'],
+ distinct: 'url',
+ },
+ },
+ },
+});
+```
+
+- `agentStudio` is configured inside `askAi`, not as a top-level DocSearch prop.
+- When `agentStudio: true`, `searchParameters` must be keyed by index name.
+- Agent Studio search parameters support `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+### Filtering search results
+
+#### Keyword search
+
+If your website uses [DocSearch meta tags][13] or if you've added [custom variables to your config][14], you'll be able to use the [`facetFilters`][16] option to scope your search results to a [`facet`][15]
+
+This is useful to limit the scope of the search to one language or one version.
+
+
+
+
+```js
+docsearch({
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+});
+```
+
+
+
+
+
+```jsx
+
+```
+
+
+
+
+
+#### Ask AI
+
+Filtering also applies when using Ask AI. This is useful to limit the scope of the LLM's search to only relevant results.
+
+:::info
+We recommend using the `facetFilters` option when using Ask AI with multiple languages or any multi-faceted index.
+:::
+
+
+
+```js
+docsearch({
+ askAi: {
+ assistantId: 'YOUR_ALGOLIA_ASSISTANT_ID',
+ searchParameters: {
+ facetFilters: ['language:en', 'version:1.0.0'],
+ },
+ },
+});
+```
+
+
+
+```jsx
+
+```
+
+
+
+
+:::tip
+You can use `facetFilters: ['type:content']` to ensure Ask AI only uses records where the `type` attribute is `content` (i.e., only records that actually have content). This is useful if your index contains records for navigation, metadata, or other non-content types.
+:::
+
+### Sending events
+
+You can send search events to your DocSearch index by passing in the `insights` parameter when creating your DocSearch instance.
+
+
+
+
+```diff
+docsearch({
+ // other options
++ insights: true,
+});
+```
+
+
+
+
+
+```diff
+
+```
+
+
+
+
+
+## Performance optimization
+
+### Preconnect
+
+Improve the loading speed of your initial search request by adding this snippet into your website's `` section:
+
+```html
+
+```
+
+This helps the browser establish a quick connection with Algolia, enhancing user experience, especially on mobile devices.
+
+[1]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/integrations
+[6]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
+[7]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+[8]: https://codesandbox.io/s/docsearch-js-v3-playground-z9oxj
+[9]: https://codesandbox.io/s/docsearch-react-v3-playground-619yg
+[10]: https://www.npmjs.com/
+[11]: /docs/api#container
+[12]: /docs/api
+[13]: /docs/required-configuration#introduce-global-information-as-meta-tags
+[14]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: https://www.algolia.com/doc/guides/managing-results/refine-results/filtering/#facetfilters
+[17]: /docs/composable-api
diff --git a/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
new file mode 100644
index 00000000..4ae81493
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/docusaurus-adapter.mdx
@@ -0,0 +1,61 @@
+---
+title: Docusaurus Adapter (Recommended)
+---
+
+If you use Docusaurus, install and configure `@docsearch/docusaurus-adapter` to get the latest DocSearch features on your current Docusaurus version.
+
+## Why this adapter exists
+
+Docusaurus ships an excellent built-in Algolia integration (`@docusaurus/theme-search-algolia`), but Docusaurus (Meta-maintained) and DocSearch don't always release on the same cadence.
+
+The DocSearch adapter lets us ship new DocSearch features (including Ask AI sidepanel support) without forcing users to wait for a Docusaurus integration update.
+
+In practice, this means:
+
+- Faster access to new DocSearch capabilities.
+- Better compatibility for Ask AI + sidepanel features.
+- A dedicated search integration path maintained in the DocSearch project.
+
+## Install
+
+```bash
+yarn add @docsearch/docusaurus-adapter
+# or
+npm install @docsearch/docusaurus-adapter
+```
+
+## Configuration
+
+Keep `@docusaurus/preset-classic`, add the adapter plugin, and configure search under `themeConfig.docsearch` (preferred):
+
+```js title="docusaurus.config.mjs"
+export default {
+ plugins: ['@docsearch/docusaurus-adapter'],
+ themeConfig: {
+ docsearch: {
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ indexName: 'YOUR_INDEX_NAME',
+ askAi: {
+ assistantId: 'YOUR_ASSISTANT_ID',
+ sidePanel: true,
+ },
+ contextualSearch: true,
+ },
+ },
+};
+```
+
+## `docsearch` vs `algolia` keys
+
+- `themeConfig.docsearch` is the canonical key.
+- `themeConfig.algolia` is supported as a backward-compatible alias.
+- Do not define both keys at the same time.
+
+Using `themeConfig.docsearch` helps avoid built-in Docusaurus search-theme validation conflicts when you want newer DocSearch options like `askAi.sidePanel`.
+
+## Customizing Search UI (SearchBar/SearchPage)
+
+If you want to customize search behavior or UI, customize the adapter theme components (`@theme/SearchBar` and `@theme/SearchPage`) from the adapter integration path.
+
+This keeps your customization aligned with DocSearch feature updates and avoids coupling to the built-in Docusaurus Algolia theme implementation.
diff --git a/packages/website/versioned_docs/version-v4/examples.mdx b/packages/website/versioned_docs/version-v4/examples.mdx
new file mode 100644
index 00000000..6241cd50
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/examples.mdx
@@ -0,0 +1,428 @@
+---
+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.
diff --git a/packages/website/versioned_docs/version-v4/how-does-it-work.mdx b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
new file mode 100644
index 00000000..3cc42427
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/how-does-it-work.mdx
@@ -0,0 +1,51 @@
+---
+title: How does it work?
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+Getting up and ready with DocSearch is a straightforward process that requires three steps: you apply, we configure the crawler and the Algolia app for you, and you integrate our UI in your frontend. You only need to copy and paste a JavaScript snippet.
+
+
+
+## You apply
+
+The first thing you'll need to do is to apply for DocSearch by [filling out the form on this page][1] (double check first that [you qualify][2]). We are receiving a lot of requests, so this form makes sure we won't be forgetting anyone.
+
+We guarantee that we will answer every request, but as we receive a lot of applications, please give us a couple of days to get back to you :)
+
+## We create your Algolia application and a dedicated crawler
+
+Once we receive [your application][1], we'll have a look at your website, create an Algolia application and a dedicated [crawler][5] for it. Your crawler comes with [a configuration file][6] which defines which URLs we should crawl or ignore, as well as the specific CSS selectors to use for selecting headers, subheaders, etc.
+
+This step still requires some manual work and human brain, but thanks to the +4,000 configs we already created, we're able to automate most of it. Once this creation finishes, we'll run a first indexing of your website and have it run automatically at a random time of the week.
+
+**With the Crawler, comes [a dedicated interface][8] for you to:**
+
+- Start, schedule and monitor your crawls
+- Edit and test your config file directly with [DocSearch v3][7]
+
+**With the Algolia application comes access to the dashboard for you to:**
+
+- Browse your index and see how your content is indexed
+- Various analytics to understand how your search performs and ensure that your users are able to find what theyβre searching for
+- Trials for other Algolia features
+- Team management
+
+## You update your website
+
+We'll then get back to you with the JavaScript snippet you'll need to add to your website. This will bind your [DocSearch component][7] to display results from your Algolia index on each keystroke in a pop-up modal.
+
+Now that DocSearch is set, you don't have anything else to do. We'll keep crawling your website and update your search results automatically. All we ask is that you keep the "Search by Algolia" logo next to your search results.
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: /docs/who-can-apply
+[3]: https://github.com/algolia/docsearch-configs/tree/master/configs
+[4]: /docs/styling
+[5]: https://www.algolia.com/products/search-and-discovery/crawler/
+[6]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[7]: /docs/v3/docsearch
+[8]: https://crawler.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/integrations.md b/packages/website/versioned_docs/version-v4/integrations.md
new file mode 100644
index 00000000..59806313
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/integrations.md
@@ -0,0 +1,45 @@
+---
+title: Supported Integrations
+---
+
+We worked with **documentation website generators** to have DocSearch directly embedded as a first class citizen in the websites they produce.
+
+## Our great integrations
+
+So, if you're using one of the following tools, check out their documentation to see how to enable DocSearch on your website:
+
+- [Docusaurus v1][1] - [How to enable search][2]
+- [Docusaurus v2 & v3][3] - [DocSearch adapter (recommended)][23] / [Using Algolia DocSearch][4]
+- [VuePress][5] - [Algolia Search][6]
+- [VitePress][21] - [Search][22]
+- [Starlight][7] - [Algolia Search][8]
+- [LaRecipe][9] - [Algolia Search][10]
+- [Orchid][11] - [Algolia Search][12]
+- [Smooth DOC][13] - [DocSearch][14]
+- [Docsy][15] - [Configure Algolia DocSearch][16]
+- [Lotus Docs][19] - [Enabling the DocSearch Plugin][20]
+- [Sphinx](https://www.sphinx-doc.org/en/master/) - [Algolia DocSearch for Sphinx](https://sphinx-docsearch.readthedocs.io/)
+
+If you're maintaining a similar tool and want us to add you to the list, [feel free to make a pull request](https://github.com/algolia/docsearch/edit/main/packages/website/docs/integrations.md) and [contribute to Code Exchange](https://www.algolia.com/developers/code-exchange/contribute/). We're happy to help.
+
+[1]: https://v1.docusaurus.io/
+[2]: https://v1.docusaurus.io/docs/en/search
+[3]: https://docusaurus.io/
+[4]: https://docusaurus.io/docs/search#using-algolia-docsearch
+[5]: https://vuepress.vuejs.org/
+[6]: https://vuepress.vuejs.org/theme/default-theme-config.html#algolia-search
+[7]: https://starlight.astro.build/
+[8]: https://starlight.astro.build/guides/site-search/#algolia-docsearch
+[9]: https://larecipe.saleem.dev/docs/2.2/overview
+[10]: https://larecipe.saleem.dev/docs/2.2/search#available-engines
+[11]: https://orchid.run
+[12]: https://orchid.run/plugins/orchidsearch#algolia-docsearch
+[13]: https://next-smooth-doc.vercel.app/
+[14]: https://next-smooth-doc.vercel.app/docs/docsearch/
+[15]: https://www.docsy.dev/
+[16]: https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch
+[19]: https://lotusdocs.dev/docs/
+[20]: https://lotusdocs.dev/docs/guides/features/docsearch/#enabling-the-docsearch-plugin
+[21]: https://vitepress.dev/
+[22]: https://vitepress.dev/reference/default-theme-search#algolia-search
+[23]: /docs/docusaurus-adapter
diff --git a/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
new file mode 100644
index 00000000..3dbf5caa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
@@ -0,0 +1,67 @@
+---
+title: "[Pre-v4] Manage your crawls"
+---
+
+:::caution
+This UI is deprecated and no longer maintained. For the latest instructions, please use the new documentation: [Crawler Configuration Visual UI](./crawler-configuration-visual). You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+:::
+
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+DocSearch comes with the [Algolia Crawler web interface](https://crawler.algolia.com/) that allows you to configure how and when your Algolia index will be populated.
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+## Monitor your crawls
+
+The `monitoring` section helps you find crawl errors or improve your search results.
+
+
+
+
+
+## Update your config
+
+The live editor allows you to update your config file and test your URLs (`URL tester`).
+
+
+
+
+
+## Search preview
+
+From the [`editor`](#update-your-config), you have access to a `Search preview` tab to browse search results with [`DocSearch v3`](/docs/v3/docsearch).
+
+
+
+
+
+## URL tester
+
+From the [`editor`](#update-your-config), you can use the URL tester to [debug selectors](https://www.algolia.com/doc/tools/crawler/getting-started/crawler-configuration/#debugging-selectors) or how we crawl your website.
+
+
+
+
diff --git a/packages/website/versioned_docs/version-v4/mcp/installation.mdx b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
new file mode 100644
index 00000000..300b20c2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/installation.mdx
@@ -0,0 +1,32 @@
+---
+title: Install DocSearch MCP
+sidebar_label: Installation
+---
+
+import MCPInstall from '@site/src/components/mcp/MCPInstall';
+
+DocSearch MCP is a remote MCP server. Point any MCP-compatible client at this endpoint β no authentication required:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+The fastest path is the **DocSearch CLI** β one command that configures your client for you. Prefer to set things up yourself? Install it as a **plugin** (ships the MCP server plus client guidance like rules, skills, and commands) or **manually** (just the MCP server config). Pick your client below.
+
+
+
+## Verify the install
+
+Ask your MCP client a public documentation question, for example:
+
+```text
+Use DocSearch MCP to find the current Next.js middleware matcher docs.
+```
+
+The client should call the DocSearch tools and answer with content from the matching documentation, ideally with source links.
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/overview.mdx b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
new file mode 100644
index 00000000..1d3aeae5
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: DocSearch MCP
+sidebar_label: Overview
+---
+
+DocSearch MCP lets AI clients search current public developer documentation from the DocSearch corpus.
+
+Use it when you want an assistant to answer questions from public docs instead of relying only on model training data. The public endpoint does not require authentication:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
+
+## What it does
+
+DocSearch MCP exposes documentation search through the [Model Context Protocol](https://modelcontextprotocol.io/). MCP-compatible clients connect to the endpoint and call DocSearch tools while answering your questions.
+
+The endpoint is focused on public developer documentation. You do not need an Algolia application ID, search API key, or DocSearch application to use it.
+
+## How it works
+
+Most lookups are a single call: name the product and ask your question, and DocSearch finds the right documentation set and returns the matching content together.
+
+When a question spans several products, or you want to inspect and hand-pick documentation sets first, there is a two-step flow: resolve the documentation sets, then query the ones you choose.
+
+## Available tools
+
+### `algolia_docsearch_search_docs`
+
+The one-shot tool, and the right default for most lookups. Give it a `library` (the product, SDK, or platform) and a `query` (your question); it resolves the best matching documentation set and returns ranked content in a single call. If the library is ambiguous, it returns candidate documentation sets to choose from instead.
+
+### `algolia_docsearch_resolve_docset`
+
+Step 1 of the manual flow. Finds the documentation sets that best match a product, library, or platform and returns candidates β each with a `docset_id`, title, description, and ranking signals to help pick the best match.
+
+### `algolia_docsearch_query_docs`
+
+Step 2 of the manual flow. Retrieves documentation content for one or more `docset_id`s returned by `algolia_docsearch_resolve_docset`. Pass several at once when a question spans multiple products.
+
+## Next steps
+
+- [Install DocSearch MCP](/docs/mcp/installation)
+- [Use DocSearch MCP](/docs/mcp/usage)
+
+:::note
+
+Algolia DocSearch MCP is a free service and is provided by Algolia "AS IS" and "AS AVAILABLE" without warranty of any kind, and may be suspended, modified, or discontinued by Algolia at any time in its sole discretion. Algolia disclaims all obligation and liability arising out of or in connection with Your use of DocSearch MCP. You shall comply with all laws and governmental regulations in Your use of the DocSearch MCP.
+
+:::
diff --git a/packages/website/versioned_docs/version-v4/mcp/usage.mdx b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
new file mode 100644
index 00000000..fb7b8a9b
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/mcp/usage.mdx
@@ -0,0 +1,113 @@
+---
+title: Use DocSearch MCP
+sidebar_label: Usage
+---
+
+DocSearch MCP works best when your client knows to search public documentation before answering library, framework, API, or SDK questions.
+
+## Ask documentation questions
+
+After installation, ask your client about public developer docs in natural language:
+
+```text
+How do I configure middleware matchers in Next.js?
+```
+
+```text
+Show me the current Stripe webhook signature verification docs.
+```
+
+```text
+What is the current setup for Algolia InstantSearch React?
+```
+
+If your client does not automatically use MCP tools, mention DocSearch MCP explicitly:
+
+```text
+Use DocSearch MCP to look up React Server Components data fetching.
+```
+
+## Use the Claude Code command
+
+The Claude Code plugin includes a manual command:
+
+```text
+/algolia-docsearch:docs [topic]
+```
+
+Examples:
+
+```text
+/algolia-docsearch:docs Next.js middleware matcher
+/algolia-docsearch:docs Stripe webhook signature verification
+/algolia-docsearch:docs Algolia InstantSearch React configure search client
+```
+
+## Tool flow
+
+DocSearch MCP exposes three tools. Most of the time the client only needs the one-shot tool; the two-step flow is for multi-product questions or when you want to hand-pick documentation sets.
+
+You can ask in natural language β full sentences and questions work well. For the one-shot tool, keep `library` to the product name and put the actual question in `query`.
+
+### One-shot: `algolia_docsearch_search_docs`
+
+The client names the product and asks the question in a single call:
+
+```json
+{
+ "library": "Next.js",
+ "query": "how do middleware matchers work"
+}
+```
+
+It returns ranked documentation content for the best matching set. If the library is ambiguous, it returns candidate documentation sets instead so the client can pick one and fall back to `algolia_docsearch_query_docs`.
+
+### Two-step: resolve, then query
+
+For questions that span several products, or when the client wants to choose documentation sets explicitly:
+
+1. `algolia_docsearch_resolve_docset` finds documentation sets:
+
+```json
+{
+ "query": "Next.js app router"
+}
+```
+
+It returns candidates, each with a `docset_id`.
+
+2. `algolia_docsearch_query_docs` retrieves content for the chosen `docset_id`(s):
+
+```json
+{
+ "query": "middleware matcher config",
+ "docsetIds": ["nextjs"]
+}
+```
+
+Pass multiple `docsetIds` when a question spans more than one product.
+
+## Tips
+
+- Be specific about the product and topic you want.
+- Include a version when it matters.
+- Ask for source URLs if you want the client to show where the answer came from.
+- If the first result is too broad, ask for a narrower topic.
+
+## Troubleshooting
+
+### The client does not call DocSearch MCP
+
+Make sure the MCP server is enabled in your client and named `algolia-docsearch`. If you installed the plugin, check that the plugin is enabled too.
+
+### The result is about the wrong product
+
+Ask again with the official product name. For the one-shot tool, set `library` to the vendor's product name (for example, `Algolia InstantSearch` rather than `search`).
+
+### The client cannot connect
+
+Confirm that your client supports remote HTTP MCP servers and that the configured URL is:
+
+```text
+https://mcp.algolia.com/1/docsearch/mcp
+```
diff --git a/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
new file mode 100644
index 00000000..e8edf61e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/migrating-from-legacy.mdx
@@ -0,0 +1,87 @@
+---
+title: Migrating from the legacy scraper
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+With the new version of the [DocSearch UI][1], we wanted to go further and provide better tooling for you to create and maintain your config file, and some extra Algolia features that you all have been requesting for a long time!
+
+## What's new?
+
+### Scraper
+
+The DocSearch infrastructure now leverages the [Algolia Crawler][2]. We've teamed up with our friends and created a new [DocSearch helper][4], that extracts records as we were previously doing with our beloved [DocSearch scraper][3]!
+
+The best part is that you no longer need to install any tooling on your side if you want to maintain or update your index!
+
+We now provide a web interface **[legacy][7]** or **[new](https://dashboard.algolia.com/crawler)** that will allow you to:
+
+- Start, schedule and monitor your crawls
+- Edit your config file from our live editor
+- Test your results directly with [DocSearch v3][1] or [DocSearch v4][32]
+
+### Algolia application and credentials
+
+We've received a lot of requests asking for:
+
+- A way to manage team members
+- Browse and see how Algolia records are indexed
+- See and subscribe to other Algolia features
+
+They are now all available, in **your own Algolia application**, for free :D
+
+## FAQ
+
+You can find answers related to the DocSearch migration in our [Crawler FAQ page](/docs/crawler).
+
+### Useful links
+
+- [Docusaurus blog post](https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration)
+- [Algolia Dev chat 11-23-2021](https://www.youtube.com/watch?v=htsjpojpKtc&t=2404s)
+
+## Config file key mapping
+
+Below are the keys that can be found in the [`legacy` DocSearch configs][14] and their translation to an [Algolia Crawler config][16]. For more detailed information on the Algolia Crawler, see [the official documentation][15].
+
+| `legacy` | `current` | description |
+| --- | --- | --- |
+| `start_urls` | [`startUrls`][20] | Now accepts URLs only, see [`helpers.docsearch`][30] to handle custom variables |
+| `page_rank` | [`pageRank`][31] | Can be added to the `recordProps` in [`helpers.docsearch`][30], should be passed as a **string** |
+| `js_render` | [`renderJavaScript`][21] | Unchanged |
+| `js_wait` | [`renderJavascript.waitTime`][22] | See documentation of [`renderJavaScript`][21] |
+| `index_name` | **removed**, see [`actions`][23] | Handled directly in the [`actions`][23] |
+| `sitemap_urls` | [`sitemaps`][24] | Unchanged |
+| `stop_urls` | [`exclusionPatterns`][25] | Supports [`micromatch`][27] |
+| `selectors_exclude` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `custom_settings` | [`initialIndexSettings`][26] | Unchanged |
+| `scrape_start_urls` | **removed** | Can be handled with [`exclusionPatterns`][25] |
+| `strip_chars` | **removed** | `#` are removed automatically from anchor links, edge cases should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+| `conversation_id` | **removed** | Not needed anymore |
+| `nb_hits` | **removed** | Not needed anymore |
+| `sitemap_alternate_links` | **removed** | Not needed anymore |
+| `stop_content` | **removed** | Should be handled in the [`recordExtractor`][28] and [`helpers.docsearch`][29] |
+
+[1]: /docs/v3/docsearch
+[2]: https://www.algolia.com/products/search-and-discovery/crawler/
+[3]: /docs/legacy/run-your-own
+[4]: /docs/record-extractor
+[7]: https://crawler.algolia.com/
+[14]: /docs/legacy/config-file
+[15]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[16]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[20]: https://www.algolia.com/doc/tools/crawler/apis/configuration/start-urls/
+[21]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[22]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/#parameter-param-waittime
+[23]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-indexname
+[24]: https://www.algolia.com/doc/tools/crawler/apis/configuration/sitemaps/
+[25]: https://www.algolia.com/doc/tools/crawler/apis/configuration/exclusion-patterns/
+[26]: https://www.algolia.com/doc/tools/crawler/apis/configuration/initial-index-settings/
+[27]: https://github.com/micromatch/micromatch
+[28]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[29]: /docs/record-extractor
+[30]: /docs/record-extractor#introduction
+[31]: /docs/record-extractor#pagerank
+[32]: /docs/docsearch
diff --git a/packages/website/docs/migrating-from-v3.md b/packages/website/versioned_docs/version-v4/migrating-from-v3.md
similarity index 100%
rename from packages/website/docs/migrating-from-v3.md
rename to packages/website/versioned_docs/version-v4/migrating-from-v3.md
diff --git a/packages/website/versioned_docs/version-v4/record-extractor.md b/packages/website/versioned_docs/version-v4/record-extractor.md
new file mode 100644
index 00000000..64c34ca7
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/record-extractor.md
@@ -0,0 +1,345 @@
+---
+title: Record Extractor
+---
+
+## Introduction
+
+:::info
+
+This documentation will only contain information regarding the **helpers.docsearch** method, see **[Algolia Crawler Documentation][7]** for more information on the **[Algolia Crawler][8]**.
+
+:::
+
+Pages are extracted by a [`recordExtractor`][9]. These extractors are assigned to [`actions`][12] via the [`recordExtractor`][9] parameter. This parameter links to a function that returns the data you want to index, organized in an array of JSON objects.
+
+_The helpers are a collection of functions to help you extract content and generate Algolia records._
+
+### Useful links
+
+- [Extracting records with the Algolia Crawler][11]
+- [`recordExtractor` parameters][10]
+
+## Usage
+
+The most common way to use the DocSearch helper, is to return its result to the [`recordExtractor`][9] function.
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Manipulate the DOM with Cheerio
+
+The [`Cheerio instance ($)`](https://cheerio.js.org/) allows you to manipulate the DOM:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ $(".my-warning-message").remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ },
+ });
+},
+```
+
+### Provide fallback selectors
+
+Fallback selectors can be useful when retrieving content that might not exist in some pages:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ // `.exists h1` will be selected if `.exists-probably h1` does not exists.
+ lvl0: {
+ selectors: [".exists-probably h1", ".exists h1"],
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ // `.exists p, .exists li` will be selected.
+ content: [
+ ".does-not-exists p, .does-not-exists li",
+ ".exists p, .exists li",
+ ],
+ },
+ });
+},
+```
+
+### Provide raw text (`defaultValue`)
+
+_Only the `lvl0` and [custom variables][13] selectors support this option_
+
+You might want to structure your search results differently than your website, or provide a `defaultValue` to a potentially non-existent selector:
+
+```js
+recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably h1",
+ defaultValue: "myRawTextIfDoesNotExists",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".exists-probably .language",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ },
+ });
+},
+```
+
+### Indexing content for faceting
+
+_These selectors also support [`defaultValue`](#provide-raw-text-defaultvalue) and [fallback selectors](#provide-fallback-selectors)_
+
+You might want to index content that will be used as filters in your frontend (e.g. `version` or `lang`), you can define any custom variable to the `recordProps` object to add them to your Algolia records:
+
+```js
+recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "main p, main li",
+ // The variables below can be used to filter your search
+ foo: ".bar",
+ language: {
+ // It also supports the fallback DOM selectors syntax!
+ selectors: ".does-not-exists",
+ // Since custom variables are used for filtering, we allow sending
+ // multiple raw values
+ defaultValue: ["en", "en-US"],
+ },
+ version: {
+ // You can send raw values without `selectors`
+ defaultValue: ["latest", "stable"],
+ },
+ },
+ });
+},
+```
+
+The following `version`, `lang` and `foo` attributes will be available in your records:
+
+```json
+foo: "valueFromBarSelector",
+language: ["en", "en-US"],
+version: ["latest", "stable"]
+```
+
+You can now use them to [filter your search in the frontend][16]
+
+### Boost search results with `pageRank`
+
+This parameter allows you to boost records using a custom ranking attribute built from the current `pathsToMatch`. Pages with highest [`pageRank`](#pagerank) will be returned before pages with a lower [`pageRank`](#pagerank). The default value is 0 and you can pass any numeric value **as a string**, including negative values.
+
+Search results are sorted by weight (desc), so you can have both boosted and non boosted results. The weight of each result will be computed for a given query based on multiple factors: match level, position, etc. and the pageRank value will be added to this final weight. The pageRank on its own may not be enough to influence the results of your query depending on how your [overall ranking is set up](https://www.algolia.com/doc/guides/managing-results/relevance-overview/in-depth/ranking-criteria/). If changing the pageRank value doesn't influence your search results enough, even with large values, move weight.pageRank higher in the Ranking and Sorting page for your index.
+
+You can view the computed weight directly from the Algolia dashboard (dashboard.algolia.com->search->perform a search->mouse hover over the "ranking criteria" icon bottom right of each record). That will give you an idea of what pageRank value is acceptable for your case.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers, url }) => {
+ const isDocPage = /\/[\w-]+\/docs\//.test(url.pathname);
+ const isBlogPage = /\/[\w-]+\/blog\//.test(url.pathname);
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ pageRank: isDocPage ? "-2000" : isBlogPage ? "-1000" : "0",
+ },
+ });
+ },
+},
+```
+
+### Reduce the number of records
+
+If you encounter the `Extractors returned too many records` error when your page outputs more than 750 records, the [`aggregateContent`](#aggregatecontent) option helps you reduce the number of records at the `content` level of the extractor.
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ aggregateContent: true,
+ });
+ },
+},
+```
+
+### Reduce the record size
+
+If you encounter the `Records extracted are too big` error when crawling your website, it is usually because there is too much information in your records, or because your page is too large. The [`recordVersion`](#recordversion) option helps you reduce the records size by removing informations that are only used with [DocSearch v2](/docs/legacy/dropdown).
+
+```js
+{
+ indexName: "YOUR_INDEX_NAME",
+ pathsToMatch: ["https://YOUR_WEBSITE_URL/api/**"],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "header h1",
+ },
+ lvl1: "article h2",
+ lvl2: "article h3",
+ lvl3: "article h4",
+ lvl4: "article h5",
+ lvl5: "article h6",
+ content: "article p, article li",
+ },
+ recordVersion: "v3",
+ });
+ },
+},
+```
+
+## `recordProps` API Reference
+
+### `lvl0`
+
+> `type: Lvl0` | **required**
+
+```ts
+type Lvl0 = {
+ selectors: string | string[];
+ defaultValue?: string;
+};
+```
+
+### `lvl1`, `content`
+
+> `type: string | string[]` | **required**
+
+### `lvl2`, `lvl3`, `lvl4`, `lvl5`, `lvl6`
+
+> `type: string | string[]` | **optional**
+
+### `pageRank`
+
+> `type: number` | **optional**
+
+See the [live example](#boost-search-results-with-pagerank)
+
+### Custom variables
+
+> `type: string | string[] | CustomVariable` | **optional**
+
+```ts
+type CustomVariable =
+ | {
+ defaultValue: string | string[];
+ }
+ | {
+ selectors: string | string[];
+ defaultValue?: string | string[];
+ };
+```
+
+Custom variables are used to [`filter your search`](/docs/v3/docsearch#filtering-your-search), you can define them in the [`recordProps`](#indexing-content-for-faceting)
+
+## `helpers.docsearch` API Reference
+
+### `aggregateContent`
+
+> `type: boolean` | default: `true` | **optional**
+
+[This option](#reduce-the-number-of-records) groups the Algolia records created at the `content` level of the selector into a single record for its matching heading.
+
+### `recordVersion`
+
+> `type: 'v3' | 'v2'` | default: `v2` | **optional**
+
+This option removes content from the Algolia records that are only used for [DocSearch v2](/docs/legacy/dropdown). If you are using [the latest version of DocSearch](/docs/v3/docsearch), you can [set it to `v3`](#reduce-the-record-size).
+
+### `indexHeadings`
+
+> `type: boolean | { from: number, to: number }` | default: `true` | **optional**
+
+This option tells the crawler if the `headings` (`lvlX`) should be indexed.
+
+- When `false`, only records for the `content` level will be created.
+- When `from, to` is provided, only records for the `lvlX` to `lvlY` will be created.
+
+[1]: /docs/v3/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/legacy/dropdown
+[5]: /docs/migrating-from-legacy
+[6]: /docs/legacy/run-your-own
+[7]: https://www.algolia.com/doc/tools/crawler/getting-started/overview/
+[8]: https://www.algolia.com/products/search-and-discovery/crawler/
+[9]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor
+[10]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/#parameter-param-recordextractor-2
+[11]: https://www.algolia.com/doc/tools/crawler/guides/extracting-data/#extracting-records
+[12]: https://www.algolia.com/doc/tools/crawler/apis/configuration/actions/
+[13]: /docs/record-extractor#indexing-content-for-faceting
+[15]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[16]: /docs/v3/docsearch/#filtering-your-search
diff --git a/packages/website/versioned_docs/version-v4/required-configuration.mdx b/packages/website/versioned_docs/version-v4/required-configuration.mdx
new file mode 100644
index 00000000..9b33aed2
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/required-configuration.mdx
@@ -0,0 +1,189 @@
+---
+title: Required configuration
+---
+
+This section gives you the best practices to optimize our crawl. Adopting the following specification is required to let our crawler build the best experience from your website. You will need to update your website and follow these rules.
+
+:::info
+
+If your website is generated, thanks to one of [our supported tools][1], you do not need to change your website as it is already compliant with our requirements.
+
+:::
+
+## The generic configuration example
+
+You can find the default DocSearch config template below and tweak it with some examples from our [`complex extractors` section][12].
+
+If you are using one of [our integrations][13], please see [the templates page][11].
+
+
+docsearch-default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ startUrls: ['https://YOUR_START_URL.io/'],
+ sitemaps: ['https://YOUR_START_URL.io/sitemap.xml'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_START_URL.io/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+### Overview of a clear layout
+
+A website implementing these best practices will look simple and clear, as shown below:
+
+
+
+The main blue element will be your `.DocSearch-content` container. More details in the following guidelines.
+
+### Use the right classes as [`recordProps`][2]
+
+You can add some specific static classes to help us find your content role. These classes can not involve any style changes. These dedicated classes will help us to create a great learn-as-you-type experience from your documentation.
+
+- Add a static class `DocSearch-content` to the main container of your textual content. Most of the time, this tag is a `` or an `` HTML element.
+
+- Every searchable `lvl` element outside this main documentation container (for instance in a sidebar) must be a `global` selector. They will be globally picked up and injected to every record built from your page. Be careful, the level value matters and every matching element must have an increasing level along the HTML flow. A level `X` (for `lvlX`) should appear after a level `Y` while `X > Y`.
+
+- `lvlX` selectors should use the standard title tags like `h1`, `h2`, `h3`, etc. You can also use static classes. Set a unique `id` or `name` attribute to these elements as detailed below.
+
+- Every DOM element matching the `lvlX` selectors must have a unique `id` or `name` attribute. This will help the redirection to directly scroll down to the exact place of the matching elements. These attributes define the right anchor to use.
+
+- Every textual element (recordProps `content`) must be wrapped in a `` or `
` tag. This content must be atomic and split into small entities. Be careful to never nest one matching element into another one as it will create duplicates.
+
+- Stay consistent and do not forget that we need to have some consistency along the HTML flow.
+
+## Introduce global information as meta tags
+
+Our crawler automatically extracts information from our DocSearch specific meta tags:
+
+```html
+
+
+```
+
+The crawl adds the `content` value of these `meta` tags to all records extracted from the page. The meta tags `name` must follow the `docsearch:$NAME` pattern. `$NAME` is the name of the attribute set to all records.
+
+The `docsearch:version` meta tag can be a set [of comma-separated tokens][5], each of which is a version relevant to the page. These tokens must be compliant with [the SemVer specification][6] or only contain alphanumeric characters (e.g. `latest`, `next`, etc.). As facet filters, these version tokens are case-insensitive.
+
+For example, all records extracted from a page with the following meta tag:
+
+```html
+
+```
+
+The `version` attribute of these records will be :
+
+```json
+version:["2.0.0-alpha.62", "latest"]
+```
+
+You can then [transform these attributes as `facetFilters`][3] to [filter over them from the UI][10].
+
+## Nice to have
+
+- Your website should have [an updated sitemap][7]. This is key to let our crawler know what should be updated. Do not worry, we will still crawl your website and discover embedded hyperlinks to find your great content.
+
+- Every page needs to have their full context available. Using global elements might help (see above).
+
+- Make sure your documentation content is also available without JavaScript rendering on the client-side. If you absolutely need JavaScript turned on, you need to [set `renderJavaScript: true` in your configuration][8].
+
+Any questions? Connect with us on [Discord][14] or [support][9].
+
+[1]: /docs/integrations
+[2]: record-extractor#recordprops-api-reference
+[3]: https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/
+[5]: https://html.spec.whatwg.org/dev/common-microsyntaxes.html#comma-separated-tokens
+[6]: https://semver.org/
+[7]: https://www.sitemaps.org/
+[8]: https://www.algolia.com/doc/tools/crawler/apis/configuration/render-java-script/
+[9]: https://support.algolia.com/
+[10]: /docs/v3/docsearch#filtering-your-search
+[11]: /docs/templates
+[12]: /docs/record-extractor#introduction
+[13]: /docs/integrations
+[14]: https://alg.li/discord
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
new file mode 100644
index 00000000..b22ca01f
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/advanced-use-cases.mdx
@@ -0,0 +1,144 @@
+---
+title: Advanced use cases
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Introduction
+
+This guide will cover some advanced implementations/use cases for the Sidepanel. The examples below assume you're using the Sidepanel React package,
+available from `@docsearch/sidepanel`. The `@docsearch/sidepanel` package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Complex implementation
+
+Below is an example of a more complex implementation with `searchParameters`, a different `variant`, and some translations.
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+function App() {
+ return (
+
+
+
+
+ );
+}
+```
+
+## Dynamic importing
+
+Sidepanel is built in a way that allows for dynamic importing of its components to help reduce bundle size. Below is a brief example of how to do so:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { SidepanelButton } from '@docsearch/sidepanel/button';
+import type { Sidepanel as SidepanelType } from '@docsearch/sidepanel/sidepanel';
+import { useState } from 'react';
+
+let Sidepanel: typeof SidepanelType | null = null;
+
+async function importSidepanelIfNeeded() {
+ if (Sidepanel) {
+ return;
+ }
+
+ const { Sidepanel: Panel } = await import('@docsearch/sidepanel/sidepanel');
+
+ Sidepanel = Panel;
+}
+
+export default function DynamicSidepanel() {
+ const [sidepanelLoaded, setSidepanelLoaded] = useState(false);
+
+ const loadSidepanel = () => {
+ importSidepanelIfNeeded().then(() => {
+ setSidepanelLoaded(true);
+ });
+ };
+
+ return (
+
+
+ {sidepanelLoaded && Sidepanel && (
+
+ )}
+
+ );
+}
+```
+
+## Hybrid Mode
+
+Hybrid Mode allows you to combine the Sidepanel and the original DocSearch Modal in one integrated experience.
+
+You can trigger the Modal for search and the Sidepanel for AI-powered assistance.
+
+Learn more in the [Hybrid Mode guide][1].
+
+[1]: /docs/sidepanel/hybrid
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
new file mode 100644
index 00000000..6e3a1b5e
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/api-reference.mdx
@@ -0,0 +1,186 @@
+---
+title: Sidepanel API Reference
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## `appId`
+
+> `type: string` | **required**
+
+Your Algolia application ID.
+
+## `apiKey`
+
+> `type: string` | **required**
+
+Your Algolia Search API key.
+
+## `assistantId`
+
+> `type: string` | **required**
+
+The ID for which Ask AI assistant to use.
+
+## `indexName`
+
+> `type: string` | **required**
+
+The name of the index to be used with the Ask AI service.
+
+## `agentStudio`
+
+> `type: boolean` | **optional** | **experimental**
+
+:::warning[Experimental]
+
+`agentStudio` is currently an experimental property. It is targeted to be stable in release `5.0.0`.
+
+:::
+
+If `agentStudio` is true, the Ask AI chat will use Algolia's [Agent Studio][2] as the chat backend instead of the Ask AI backend. More can be learned about setting up Agent Studio on their dedicated [documentation page][3].
+
+## `searchParameters`
+
+> `type: AskAiSearchParameters | Record>` | **optional**
+
+Additional search parameters used to scope Ask AI or Agent Studio retrieval.
+
+- When `agentStudio` is omitted or `false`, pass a flat object such as `facetFilters`, `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+- When `agentStudio` is `true`, `searchParameters` must be keyed by index name and supports `filters`, `attributesToRetrieve`, `restrictSearchableAttributes`, and `distinct`.
+
+```tsx
+
+```
+
+```tsx
+
+```
+
+## `variant`
+
+> `type: 'floating' | 'inline'` | default: `'floating'` | **optional**
+
+Variant of the Sidepanel positioning.
+
+- `inline` pushes page content when opened.
+- `floating` is positioned above all other content on the page.
+
+## `side`
+
+> `type: 'right' | 'left'` | default: `'right'` | **optional**
+
+The side of the page which the panel will originate from.
+
+## `width`
+
+> `type: number | string` | default: `'360px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its default state.
+
+## `expandedWidth`
+
+> `type: number | string` | default: `'580px'` | **optional**
+
+Width of the Sidepanel (px or any CSS width) while in its expanded state.
+
+## `suggestedQuestions`
+
+> `type: boolean` | default: `false` | **optional**
+
+Enables displaying suggested questions on new conversation screen.
+
+More information on setting up Suggested Questions can be found on [Algolia Docs][1]
+
+## `keyboardShortcuts`
+
+> `type: { 'Ctrl/Cmd+I': boolean }` | **optional**
+
+Configuration for keyboard shortcuts. Allows enabling/disabling specific shortcuts.
+
+### Default behavior
+
+- `Ctrl/Cmd+I` - Opens and closes the Sidepanel
+
+### Interface
+
+```ts
+interface SidepanelShortcuts {
+ 'Ctrl/Cmd+I'?: boolean; // default: true
+}
+```
+
+## `theme`
+
+> `type: 'light' | 'dark'` | default: `'light'` | **optional**
+
+## `portalContainer` (React only)
+
+> `type: Element | DocumentFragment` | default: `document.body` | **optional**
+
+The container element where the panel should be portaled to. Use this when you need the Sidepanel to render in a custom DOM node.
+
+:::warning
+This prop only exists in the React based versions of Sidepanel. If you are using the `@docsearch/sidepanel-js` package, use the `container` option instead.
+:::
+
+
+
+ ```tsx
+ // assume you have a dedicated DOM node in your HTML
+
+
+ const portalEl = document.getElementById('sidepanel-root');
+
+
+ ```
+
+
+
+ ```js
+ sidepanel({
+ // The element that will contain the Sidepanel Button and Sidepanel
+ container: '#sidepanel-root',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+ })
+ ```
+
+
+
+[1]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/suggested-questions
+[2]: https://www.algolia.com/products/ai/agent-studio
+[3]: https://www.algolia.com/doc/guides/algolia-ai/agent-studio
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
new file mode 100644
index 00000000..13d31f95
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/getting-started.mdx
@@ -0,0 +1,136 @@
+---
+title: Get started with Sidepanel
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Sidepanel is available from version `>= 4.4`
+:::
+
+## Introduction
+
+DocSearch Sidepanel is a new experience separate from the DocSearch Modal experience. Sidepanel is built entirely for usage with Ask AI and can be used completely standalone or in [Hybrid mode][1] with the Modal.
+
+## Installation
+
+To get started with Sidepanel, first you will need to install the needed packages:
+
+
+
+
+```bash
+npm install @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+npm install @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+yarn add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+pnpm add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+
+```bash
+bun add @docsearch/react @docsearch/css
+
+# Or if using JS based package
+
+bun add @docsearch/sidepanel-js @docsearch/css
+```
+
+
+
+
+> Or using your package manager of choice
+
+### Without package manager
+
+```html
+
+
+
+
+```
+
+## Implementation
+
+The simplest implementation of Sidepanel would be as follows:
+
+
+
+```tsx
+import { DocSearchSidepanel } from '@docsearch/react/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function App() {
+ return (
+
+ );
+}
+```
+
+
+
+You will need a `container` DOM node to render the Sidepanel into:
+
+```html
+
+```
+
+```js
+import sidepanel from '@docsearch/sidepanel-js';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+sidepanel({
+ container: '#docsearch-sidepanel',
+ indexName: 'YOUR_INDEX_NAME',
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_SEARCH_API_KEY',
+ assistantId: 'YOUR_ASSISTANT_ID',
+});
+```
+
+
+
+This is just the most basic form of implementation. To learn about other implementation methods, you can read our [Advanced use cases][2].
+
+To learn more about the different configuration options for Sidepanel, you can read our [Sidepanel API References][3].
+
+[1]: /docs/sidepanel/hybrid
+[2]: /docs/sidepanel/advanced-use-cases
+[3]: /docs/sidepanel/api-reference
diff --git a/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
new file mode 100644
index 00000000..0be6f2cb
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/sidepanel/hybrid.mdx
@@ -0,0 +1,100 @@
+---
+title: Hybrid Mode
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+:::info
+Currently Hybrid Mode is only available when using the React usage approach. Hybrid Mode is not available in the JavaScript-only (vanilla) integration.
+:::
+
+## Introduction
+
+Sidepanel can run alongside the DocSearch Modal through what we call "Hybrid Mode." When a user initiates an Ask AI action from within
+the DocSearch Modal, such as submitting a prompt or selecting an AI-related suggestion, the interface automatically transitions into the Sidepanel for
+the continuation of the conversation.
+
+## Set up
+
+To set up the Hybrid Mode experience, you will need the following:
+
+- [DocSearch Modal][1] packages installed
+- Sidepanel Component package installed
+
+The Sidepanel Component package can be installed as follows:
+
+
+
+
+```bash
+npm install @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+yarn add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+pnpm add @docsearch/sidepanel
+```
+
+
+
+
+
+```bash
+bun add @docsearch/sidepanel
+```
+
+
+
+
+> Or using your package manager of choice
+
+## Implementation
+
+Once everything is installed, you can set up Hybrid Mode as such:
+
+```tsx
+import { DocSearch } from '@docsearch/core';
+import { DocSearchButton, DocSearchModal } from '@docsearch/modal';
+import { SidepanelButton, Sidepanel } from '@docsearch/sidepanel';
+
+import '@docsearch/css/dist/style.css';
+import '@docsearch/css/dist/sidepanel.css';
+
+function HybridMode() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+There is no manual opt-in for Hybrid Mode to work. When both the Modal and Sidepanel are rendered inside the same `` context, Hybrid Mode is enabled automatically. No additional configuration is required.
+
+[1]: /docs/docsearch#installation
diff --git a/packages/website/versioned_docs/version-v4/styling.md b/packages/website/versioned_docs/version-v4/styling.md
new file mode 100644
index 00000000..554fe0c0
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/styling.md
@@ -0,0 +1,48 @@
+---
+title: Styling
+---
+
+:::info
+
+The following content is for **[DocSearch v4][2]**. If you are using **[DocSearch v3][3]**, see the **[legacy][4]** documentation.
+
+:::
+
+## Introduction
+
+DocSearch v4 comes with a theme package called `@docsearch/css`, which offers a sleek out of the box theme!
+
+:::note
+
+This package is a dependency of [`@docsearch/js`][1] and [`@docsearch/react`][1], you don't need to install it if you are using a package manager!
+
+:::
+
+## Installation
+
+```bash
+yarn add @docsearch/css@4
+# or
+npm install @docsearch/css@4
+```
+
+If you donβt want to use a package manager, you can use a standalone endpoint:
+
+```html
+
+```
+
+## Files
+
+```
+@docsearch/css
+βββ dist/style.css # all styles
+βββ dist/_variables.css # CSS variables
+βββ dist/button.css # CSS for the button
+βββ dist/modal.css # CSS for the modal
+```
+
+[1]: /docs/docsearch
+[2]: https://github.com/algolia/docsearch/
+[3]: https://github.com/algolia/docsearch/tree/master
+[4]: /docs/v3/docsearch
diff --git a/packages/website/versioned_docs/version-v4/templates.mdx b/packages/website/versioned_docs/version-v4/templates.mdx
new file mode 100644
index 00000000..b14126d9
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/templates.mdx
@@ -0,0 +1,1069 @@
+---
+title: Config Templates
+---
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+To help you create the best search experience for your users, we provide out-of-the-box crawler config templates for multiple websites generators. If you'd like to add a new template to our list, or believe we should update an existing one, please [let us know on Discord][1] or [open a pull request][2].
+
+> If you want to better understand the default parameters of the configs below, take a look at the [Crawler documentation](https://www.algolia.com/doc/tools/crawler/apis/configuration/).
+
+## Getting Started
+
+Once approved for DocSearch, we will automatically create a Crawler on your behalf, include your URL, and the Algolia credentials for your appId, apiKey, and indexName. If we detect that you are using any of the predefined generators, we'll attempt to automatically assign the proper template that matches your generator. However, this is not guaranteed. If no specific generator is detected, we will apply the default template seen below.
+
+## Updating the Template
+
+You can manually update the crawler template by going to dashboard.algolia.com, click "Data sources", select your crawler, and go to the editor page. From there you can edit the JavaScript directly. Note that you can make draft changes without saving, test the changes using the "URL Tester", and then "Save" once you're happy with your changes.
+
+## Default Template
+
+
+default.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ indexPrefix: 'crawler_',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL'],
+ renderJavaScript: false,
+ sitemaps: [],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl1: ['header h1', 'article h1', 'main h1', 'h1', 'head > title'],
+ content: ['article p, article li', 'main p, main li', 'p, li'],
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl2: ['article h2', 'main h2', 'h2'],
+ lvl3: ['article h3', 'main h3', 'h3'],
+ lvl4: ['article h4', 'main h4', 'h4'],
+ lvl5: ['article h5', 'main h5', 'h5'],
+ lvl6: ['article h6', 'main h6', 'h6'],
+ },
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v1 Template
+
+
+docusaurus-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/docs/',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/blog/',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/docs/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Docs',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['docs'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/blog/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.hash-link';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.navBreadcrumb h2 span',
+ defaultValue: 'Blog',
+ },
+ lvl1: '.post h1',
+ lvl2: '.post h2',
+ lvl3: '.post h3',
+ lvl4: '.post h4',
+ content: '.post article p, .post article li',
+ tags: {
+ defaultValue: ['blog'],
+ },
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang', 'language', 'version', 'tags'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Docusaurus v2 & v3 Template
+
+
+docusaurus-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // priority order: deepest active sub list header -> navbar active item -> 'Documentation'
+ // Extracting the breadcrumb titles for better accessibility.
+ const navbarTitle = $(".navbar__item.navbar__link--active").text();
+ const pageBreadcrumbTitles = $(".breadcrumbs__link")
+ .toArray()
+ .map((item) => $(item).text().trim())
+ .filter(Boolean);
+ const lvl0 =
+ [navbarTitle, ...pageBreadcrumbTitles].join(" / ") || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: lvl0,
+ },
+ lvl1: ['header h1', 'article h1'],
+ lvl2: 'article h2',
+ lvl3: 'article h3',
+ lvl4: 'article h4',
+ lvl5: 'article h5, article td:first-child',
+ lvl6: 'article h6',
+ content: 'article p, article li, article td:last-child',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ 'language',
+ 'version',
+ 'docusaurus_tag',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+## Astro Starlight Template
+
+
+starlight.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Get the top level menu item
+ const lvl0 =
+ $('details:has(a[aria-current="page"])')
+ .find("summary")
+ .find("span")
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: "main h1",
+ lvl2: "main h2",
+ lvl3: "main h3",
+ lvl4: "main h4",
+ lvl5: "main h5",
+ lvl6: "main h6",
+ content: "main p, main li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v1 Template
+
+
+vuepress-v1.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: 'p.sidebar-heading.open',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content__default h1',
+ lvl2: '.content__default h2',
+ lvl3: '.content__default h3',
+ lvl4: '.content__default h4',
+ lvl5: '.content__default h5',
+ content: '.content__default p, .content__default li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy_radio_camel.lvl0)',
+ 'unordered(hierarchy_radio.lvl0)',
+ 'unordered(hierarchy_radio_camel.lvl1)',
+ 'unordered(hierarchy_radio.lvl1)',
+ 'unordered(hierarchy_radio_camel.lvl2)',
+ 'unordered(hierarchy_radio.lvl2)',
+ 'unordered(hierarchy_radio_camel.lvl3)',
+ 'unordered(hierarchy_radio.lvl3)',
+ 'unordered(hierarchy_radio_camel.lvl4)',
+ 'unordered(hierarchy_radio.lvl4)',
+ 'unordered(hierarchy_radio_camel.lvl5)',
+ 'unordered(hierarchy_radio.lvl5)',
+ 'unordered(hierarchy_radio_camel.lvl6)',
+ 'unordered(hierarchy_radio.lvl6)',
+ 'unordered(hierarchy_camel.lvl0)',
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy_camel.lvl1)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy_camel.lvl2)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy_camel.lvl3)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy_camel.lvl4)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy_camel.lvl5)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy_camel.lvl6)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vuepress v2 Template
+
+
+vuepress-v2.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ ignoreCanonicalTo: false,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Vitepress Template
+
+
+vitepress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.content h1',
+ lvl2: '.content h2',
+ lvl3: '.content h3',
+ lvl4: '.content h4',
+ lvl5: '.content h5',
+ content: '.content p, .content li',
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: 'v3',
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## Rspress Template
+
+
+rspress.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: ['https://YOUR_WEBSITE_URL/'],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap-index.xml'],
+ ignoreCanonicalTo: true,
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ recordExtractor: ({ $, helpers }) => {
+ const lvl0 =
+ $(".rspress-nav-menu-item.rspress-nav-menu-item-active")
+ .first()
+ .text() || "Documentation";
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: "",
+ defaultValue: lvl0,
+ },
+ lvl1: ".rspress-doc h1",
+ lvl2: ".rspress-doc h2",
+ lvl3: ".rspress-doc h3",
+ lvl4: ".rspress-doc h4",
+ lvl5: ".rspress-doc h5",
+ lvl6: ".rspress-doc pre > code", // if you want to search code blocks, add this line
+ content: ".rspress-doc p, .rspress-doc li",
+ },
+ indexHeadings: true,
+ aggregateContent: true,
+ recordVersion: "v3",
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: [
+ 'type',
+ 'lang',
+ ],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ 'type',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ },
+ },
+});
+```
+
+
+
+
+## pkgdown Template
+
+
+pkgdown.js
+
+
+```js
+new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ maxDepth: 10,
+ startUrls: [
+ 'https://YOUR_WEBSITE_URL/index.html',
+ 'https://YOUR_WEBSITE_URL/',
+ 'https://YOUR_WEBSITE_URL/reference',
+ 'https://YOUR_WEBSITE_URL/articles',
+ ],
+ sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
+ exclusionPatterns: [
+ '**/reference/',
+ '**/reference/index.html',
+ '**/articles/',
+ '**/articles/index.html',
+ ],
+ discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
+ actions: [
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/index.html**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ defaultValue: 'YOUR_INDEX_NAME Home page',
+ },
+ lvl1: '.contents h2',
+ lvl2: '.contents h3',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li, .contents .pre',
+ tags: {
+ defaultValue: ['homepage'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/reference**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.ref-arguments th',
+ lvl3: '.ref-arguments td, .ref-description',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['reference'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ {
+ indexName: 'YOUR_INDEX_NAME',
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/articles**/**'],
+ recordExtractor: ({ $, helpers }) => {
+ // Removing DOM elements we don't want to crawl
+ const toRemove = '.dont-index';
+ $(toRemove).remove();
+
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.contents h1',
+ },
+ lvl1: '.contents .name',
+ lvl2: '.contents h2, .contents h3',
+ content: '.contents p, .contents li',
+ tags: {
+ defaultValue: ['articles'],
+ },
+ },
+ indexHeadings: { from: 2, to: 6 },
+ aggregateContent: true,
+ });
+ },
+ },
+ ],
+ initialIndexSettings: {
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: [
+ 'hierarchy',
+ 'content',
+ 'anchor',
+ 'url',
+ 'url_without_anchor',
+ ],
+ attributesToHighlight: ['hierarchy', 'content'],
+ attributesToSnippet: ['content:10'],
+ camelCaseAttributes: ['hierarchy', 'content'],
+ searchableAttributes: [
+ 'unordered(hierarchy.lvl0)',
+ 'unordered(hierarchy.lvl1)',
+ 'unordered(hierarchy.lvl2)',
+ 'unordered(hierarchy.lvl3)',
+ 'unordered(hierarchy.lvl4)',
+ 'unordered(hierarchy.lvl5)',
+ 'unordered(hierarchy.lvl6)',
+ 'content',
+ ],
+ distinct: true,
+ attributeForDistinct: 'url',
+ customRanking: [
+ 'desc(weight.pageRank)',
+ 'desc(weight.level)',
+ 'asc(weight.position)',
+ ],
+ ranking: [
+ 'words',
+ 'filters',
+ 'typo',
+ 'attribute',
+ 'proximity',
+ 'exact',
+ 'custom',
+ ],
+ highlightPreTag: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional',
+ separatorsToIndex: '_',
+ },
+ },
+});
+```
+
+
+
+
+[1]: https://alg.li/discord
+[2]: https://github.com/algolia/docsearch
diff --git a/packages/website/versioned_docs/version-v4/tips.md b/packages/website/versioned_docs/version-v4/tips.md
new file mode 100644
index 00000000..57d1c4fa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/tips.md
@@ -0,0 +1,71 @@
+---
+title: Tips for a good search
+---
+
+DocSearch can work with almost any website, but we've found that some site structures yield more relevant results or faster indexing time. On this page we'll share some tips on how to make the most out of DocSearch.
+
+## Use a `sitemap.xml`
+
+If you provide a sitemap in your configuration, DocSearch will use it to directly browse the pages to index. Pages are still crawled which means we extract every compliant link.
+
+We highly recommend you add a `sitemap.xml` to your website if you don't have one already. This will not only make the indexing faster, but also provide you more control over which pages to index.
+
+Sitemaps are also considered good practice for other aspects, including SEO ([more information on sitemaps][1]).
+
+## Structure the hierarchy of information
+
+DocSearch works better on structured documentation. Relevance of results is based on the structural hierarchy of content. In simpler terms, it means that we read the ``, ..., `` headings of your page to guess the hierarchy of information. This hierarchy brings contextual information to your records.
+
+Documentation starts by explaining generic concepts first and then goes deeper into specifics. This is represented in your HTML markup by the hierarchy of headings you're using. For example, concepts discussed under a `` are more specific than concepts discussed under a `` in the same page. The sooner the information comes up within the page, the higher is it ranked.
+
+DocSearch uses this structure to fine-tune the relevance of results as well as to provide potential filtering. Documentations that follow this pattern often have better relevance in their search results.
+
+Finding the right depth of your documentation tree and how to split up your content are two of the most complex tasks. For large pages, we recommend having 4 levels (from `lvl0` to `lvl3`). We recommend at least three different levels.
+
+_Note that you don't have to use `` tags and can use classes instead (e.g., `` )._
+
+## Set a unique class to the element holding the content
+
+DocSearch extracts content based on the HTML structure. We recommend that you add a custom `class` to the HTML element wrapping all your textual content. This will help narrow selectors to the relevant content.
+
+Having such a unique identifier will make your configuration more robust as it will make sure indexed content is relevant content. We found that this is the most reliable way to exclude content in headers, sidebars, and footers that are not relevant to the search.
+
+## Add anchors to headings
+
+When using headings (as mentioned above), you should also try to add a custom anchor to each of them. Anchors are specified by HTML attributes (`name` or `id`) added to headers that allow browsers to directly scroll to the right position in the page. They're accessible by clicking a link with `#` followed by the anchor.
+
+DocSearch will honor such anchors and automatically bring your users to the anchor closest to the search result they selected.
+
+## Marking the active page(s) in the navigation
+
+If you're using a multi-level navigation, we recommend that you mark each active level with a custom CSS class. This will make it easier for DocSearch to know _where_ the current page fits in the website hierarchy.
+
+For example, if your `troubleshooting.html` page is located under the "Installation" menu in your sidebar, we recommend that you add a custom CSS class to the "Installation" and "Troubleshooting" links in your sidebar.
+
+The name of the CSS class does not matter, as long as it's something that can be used as part of a CSS selector.
+
+## Consistency of your content
+
+Consistency is a pillar of meaningful documentation. It increases the **intelligibility** of a document and shortens the time required for a user to find the coveted information. The document **topic** should be **identifiable** and its **outline** should be demarcated.
+
+The hierarchy should always have the same size. Try to **avoid orphan records** such as the introduction/conclusion, or asides. The selectors must be efficient for **every document** and highlight the proper hierarchy. They need to match the coveted elements depending on their level. Be careful to avoid the **edge effect** by matching unexpected **superfluous elements**.
+
+Selectors should match information from **real document web pages** and stay ineffective for others ones (e.g., landing page, table of content, etc.). We urge the maintainer to define a **dedicated class** for the **main DOM container** that includes the actual document content such as `.DocSearch-content`
+
+Since documentation should be **interactive**, it is a key point to **verbalize concepts with standardized words**. This **redundancy**, empowered with the **search experience** (dropdown), will even enable the **learn-as-you-type experience**. The **way to find the information** plays a key role in **leading** the user to the **retrieved knowledge**. You can also use the **synonym feature**.
+
+## Avoid duplicates by promoting unicity
+
+The more time-consuming reading documentation is, the more painful and reluctant its use will be. You must avoid hazy points or catch-all. With being unhelpful, the catch-all document may be **confusing** and **counterproductive**.
+
+Duplicates introduce noise and mislead users. This is why you should always focus on the relevant content and avoid duplicating content within your site (for example landing page which contains all information, summing up, etc.). If duplicates are expected because they belong to multiple datasets (for example a different version), you should use [facets][3].
+
+## Conciseness
+
+What is clearly thought out is clearly and concisely expressed.
+
+We highly recommend that you read this blog post about [how to build a helpful search for technical documentation][2].
+
+[1]: https://www.sitemaps.org/index.html
+[2]: https://blog.algolia.com/how-to-build-a-helpful-search-for-technical-documentation-the-laravel-example/
+[3]: https://www.algolia.com/doc/guides/searching/faceting/
diff --git a/packages/website/docs/v4/askai-api.mdx b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
similarity index 97%
rename from packages/website/docs/v4/askai-api.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-api.mdx
index a01ff9e1..3edf58b2 100644
--- a/packages/website/docs/v4/askai-api.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-api.mdx
@@ -23,4 +23,4 @@ The official documentation includes:
- Integration examples with Next.js and Vercel AI SDK
- Error handling and best practices
-For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/askai).
+For more information about Ask AI in general, see the [Ask AI documentation](/docs/v4/v4/askai).
diff --git a/packages/website/docs/v4/askai-errors.mdx b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-errors.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
index 60b6d10b..53eb6f47 100644
--- a/packages/website/docs/v4/askai-errors.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-errors.mdx
@@ -161,5 +161,5 @@ The request exceeded the model's maximum context length. This happens when the c
[1]: /docs/api#askai
[2]: https://sitesearch.algolia.com/docs/experiences/search-askai#configuration
[3]: https://www.algolia.com/doc/guides/algolia-ai/askai/reference/api
-[4]: /docs/v4/askai-whitelisted-domains
+[4]: /docs/v4/v4/askai-whitelisted-domains
[5]: https://www.algolia.com/doc/guides/algolia-ai/askai/guides/models
diff --git a/packages/website/docs/v4/askai-markdown-indexing.mdx b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
similarity index 99%
rename from packages/website/docs/v4/askai-markdown-indexing.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
index 4160f9ef..4900f1b9 100644
--- a/packages/website/docs/v4/askai-markdown-indexing.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-markdown-indexing.mdx
@@ -39,7 +39,7 @@ The easiest way to set up markdown indexing is through the Crawler UI, which aut
- **Content Tag**: Specify the HTML content selector (typically `main`)
- **Template**: Choose the template that matches your documentation framework:
- **Docusaurus** - For Docusaurus sites
- - **VitePress** - For VitePress sites
+ - **VitePress** - For VitePress sites
- **Astro/Starlight** - For Astro/Starlight sites
- **Non-DocSearch (Generic)** - For custom sites or other frameworks
@@ -245,7 +245,7 @@ class CustomAskAI {
async sendMessage(conversationId, messages, searchParameters = {}) {
const token = await this.getToken();
-
+
const response = await fetch(`${this.baseUrl}/chat`, {
method: 'POST',
headers: {
@@ -270,14 +270,14 @@ class CustomAskAI {
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
-
+
return {
async *[Symbol.asyncIterator]() {
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
-
+
const chunk = decoder.decode(value, { stream: true });
if (chunk.trim()) {
yield chunk;
@@ -323,7 +323,7 @@ for await (const chunk of stream) {
- Integration with existing chat systems
- Custom analytics and monitoring
-> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/askai-api).
+> **π Learn More:** For complete API documentation, authentication details, advanced examples, and more integration patterns, see the [Ask AI API Reference](/docs/v4/v4/askai-api).
**Using Facet Filters with Your Markdown Index:**
diff --git a/packages/website/docs/v4/askai-models.mdx b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
similarity index 71%
rename from packages/website/docs/v4/askai-models.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-models.mdx
index fff60ff5..63f10810 100644
--- a/packages/website/docs/v4/askai-models.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai-models.mdx
@@ -2,7 +2,7 @@
title: Bring Your Own LLM
---
-import { ProvidersTable } from '../../src/components/ProvidersTable'
+import { ProvidersTable } from '@site/src/components/ProvidersTable';
Ask AI currently supports a Bring Your Own LLM (BYOLLM) model selection, allowing you to connect your preferred provider.
diff --git a/packages/website/docs/v4/askai-prompts.mdx b/packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-prompts.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-prompts.mdx
diff --git a/packages/website/docs/v4/askai-whitelisted-domains.mdx b/packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
similarity index 100%
rename from packages/website/docs/v4/askai-whitelisted-domains.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai-whitelisted-domains.mdx
diff --git a/packages/website/docs/v4/askai.mdx b/packages/website/versioned_docs/version-v4/v4/askai.mdx
similarity index 98%
rename from packages/website/docs/v4/askai.mdx
rename to packages/website/versioned_docs/version-v4/v4/askai.mdx
index 0cc29de5..9a561f57 100644
--- a/packages/website/docs/v4/askai.mdx
+++ b/packages/website/versioned_docs/version-v4/v4/askai.mdx
@@ -118,5 +118,5 @@ This view gives you a centralized place to organize, reuse, and fine-tune your a
## Next steps
-- [Prompting with Ask AI](/docs/v4/askai-prompts)
-- [Ask AI Whitelisted Domains](/docs/v4/askai-whitelisted-domains)
+- [Prompting with Ask AI](/docs/v4/v4/askai-prompts)
+- [Ask AI Whitelisted Domains](/docs/v4/v4/askai-whitelisted-domains)
diff --git a/packages/website/versioned_docs/version-v4/what-is-docsearch.md b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
new file mode 100644
index 00000000..c371ae12
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/what-is-docsearch.md
@@ -0,0 +1,32 @@
+---
+title: What is DocSearch?
+sidebar_label: What is DocSearch?
+---
+
+## Why?
+
+We created DocSearch because we are scratching our own itch. As developers, we spend a lot of time reading documentation, and it can be hard to find relevant information in large documentations. We're not blaming anyone here: building good search is a challenge.
+
+It happens that we are a search company and we actually have a lot of experience building search interfaces. We wanted to use those skills to help others. That's why we created a way to automatically extract content from tech documentation and make it available to everyone from the first keystroke.
+
+## Quick description
+
+We split DocSearch into a crawler and a frontend library.
+
+- Crawls are handled by the [Algolia Crawler][4] and scheduled to run once a week by default, you can then trigger new crawls yourself and monitor them directly from the [Crawler interface][5], which also offers a live editor where you can maintain your config.
+- The frontend library is built on top of [Algolia Autocomplete][6] and provides an immersive search experience through its modal.
+
+## How to feature DocSearch?
+
+DocSearch is entirely free and automated. The one thing we'll need from you is to read [our checklist][2] and apply! After that, we'll share with you the snippet needed to add DocSearch to your website. We ask that you keep the "Search by Algolia" link displayed.
+
+DocSearch is [one of our ways][1] to give back to the open source community for everything it did for us already.
+
+You can now [apply to the program][3].
+
+[1]: https://opencollective.com/algolia
+[2]: /docs/who-can-apply
+[3]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[4]: https://www.algolia.com/products/search-and-discovery/crawler/
+[5]: https://dashboard.algolia.com/crawler
+[6]: https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/
diff --git a/packages/website/versioned_docs/version-v4/who-can-apply.md b/packages/website/versioned_docs/version-v4/who-can-apply.md
new file mode 100644
index 00000000..cec7c5ae
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/who-can-apply.md
@@ -0,0 +1,30 @@
+---
+title: Who can apply?
+---
+
+**Open for all developer documentation and technical blogs.**
+
+We built DocSearch from the ground up with the idea of improving search on large technical documentations. For this reason, we are offering a free hosting version to all public online technical documentations and technical blogs.
+
+We usually turn down applications when they are not production ready or have non-technical content on the website.
+
+## Application process
+
+To [apply][1] to the DocSearch program, follow the DocSearch onboarding process in the Algolia dashboard where you'll submit your domain for an automated validation check against our requirements. If your domain meets all criteria, you'll be quickly approved to proceed with creating your DocSearch crawler.
+
+- β
Using one of our official integrations will streamline your implementation process after data ingestion.
+
+- β
You must verify your domain ownership within 7 days of approval to continue using the crawler.
+
+- β
Please review [DocSearch Plan Terms and Conditions][2].
+
+## Process duration
+
+DocSearch application process includes automated validation for faster processing. However, if we can't automatically determine your eligibility, we'll conduct a manual review that may take 1-2 business days.
+
+Once approved, you can continue the onboarding process to create your DocSearch crawler. After your data is ingested into Algolia, you'll need to implement the search UI using either our provided code snippet or one of our [integrations][3].
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: https://www.algolia.com/policies/docsearch-plan-specific-terms
+[3]: integrations.md
+[4]: https://alg.li/discord
diff --git a/packages/website/versioned_sidebars/version-v4-sidebars.json b/packages/website/versioned_sidebars/version-v4-sidebars.json
new file mode 100644
index 00000000..74276efe
--- /dev/null
+++ b/packages/website/versioned_sidebars/version-v4-sidebars.json
@@ -0,0 +1,81 @@
+{
+ "docs": [
+ {
+ "type": "category",
+ "label": "Introduction",
+ "items": ["what-is-docsearch", "who-can-apply"]
+ },
+ {
+ "type": "category",
+ "label": "DocSearch v4",
+ "items": ["docsearch", "docusaurus-adapter", "composable-api", "styling", "api", "examples", "migrating-from-v3"]
+ },
+ {
+ "type": "category",
+ "label": "MCP",
+ "items": ["mcp/overview", "mcp/installation", "mcp/usage"]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Ask AI",
+ "items": [
+ "v4/askai",
+ "v4/askai-api",
+ "v4/askai-prompts",
+ "v4/askai-whitelisted-domains",
+ "v4/askai-models",
+ "v4/askai-markdown-indexing",
+ "v4/askai-errors",
+ {
+ "type": "link",
+ "label": "Full Documentation",
+ "href": "https://www.algolia.com/doc/guides/algolia-ai/askai"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Sidepanel",
+ "items": [
+ "sidepanel/getting-started",
+ "sidepanel/advanced-use-cases",
+ "sidepanel/hybrid",
+ "sidepanel/api-reference"
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Algolia Crawler",
+ "items": ["create-crawler", "record-extractor", "templates", "crawler-configuration-visual", "manage-your-crawls"]
+ },
+ {
+ "type": "category",
+ "label": "Requirements, tips, FAQ",
+ "items": [
+ {
+ "type": "category",
+ "label": "FAQ",
+ "items": ["crawler", "docsearch-program"]
+ },
+ {
+ "type": "doc",
+ "id": "tips"
+ },
+ {
+ "type": "doc",
+ "id": "integrations"
+ }
+ ]
+ },
+ {
+ "type": "category",
+ "label": "Under the hood",
+ "items": ["how-does-it-work", "required-configuration"]
+ },
+ {
+ "type": "category",
+ "label": "Miscellaneous",
+ "items": ["migrating-from-legacy"]
+ }
+ ]
+}
diff --git a/packages/website/versions.json b/packages/website/versions.json
index dbac805d..9b27128c 100644
--- a/packages/website/versions.json
+++ b/packages/website/versions.json
@@ -1 +1 @@
-["v3", "legacy"]
+["v4", "v3", "legacy"]
docSearchTranslations
+
+
+
+
+
+
+
+
+
++ +:::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 +
+
+## You apply
+
+The first thing you'll need to do is to apply for DocSearch by [filling out the form on this page][1] (double check first that [you qualify][2]). We are receiving a lot of requests, so this form makes sure we won't be forgetting anyone.
+
+We guarantee that we will answer every request, but as we receive a lot of applications, please give us a couple of days to get back to you :)
+
+## We create your Algolia application and a dedicated crawler
+
+Once we receive [your application][1], we'll have a look at your website, create an Algolia application and a dedicated [crawler][5] for it. Your crawler comes with [a configuration file][6] which defines which URLs we should crawl or ignore, as well as the specific CSS selectors to use for selecting headers, subheaders, etc.
+
+This step still requires some manual work and human brain, but thanks to the +4,000 configs we already created, we're able to automate most of it. Once this creation finishes, we'll run a first indexing of your website and have it run automatically at a random time of the week.
+
+**With the Crawler, comes [a dedicated interface][8] for you to:**
+
+- Start, schedule and monitor your crawls
+- Edit and test your config file directly with [DocSearch v3][7]
+
+**With the Algolia application comes access to the dashboard for you to:**
+
+- Browse your index and see how your content is indexed
+- Various analytics to understand how your search performs and ensure that your users are able to find what theyβre searching for
+- Trials for other Algolia features
+- Team management
+
+## You update your website
+
+We'll then get back to you with the JavaScript snippet you'll need to add to your website. This will bind your [DocSearch component][7] to display results from your Algolia index on each keystroke in a pop-up modal.
+
+Now that DocSearch is set, you don't have anything else to do. We'll keep crawling your website and update your search results automatically. All we ask is that you keep the "Search by Algolia" logo next to your search results.
+
+[1]: https://dashboard.algolia.com/users/sign_up?selected_plan=docsearch&utm_source=docsearch.algolia.com&utm_medium=referral&utm_campaign=docsearch&utm_content=apply
+[2]: /docs/who-can-apply
+[3]: https://github.com/algolia/docsearch-configs/tree/master/configs
+[4]: /docs/styling
+[5]: https://www.algolia.com/products/search-and-discovery/crawler/
+[6]: https://www.algolia.com/doc/tools/crawler/apis/configuration/
+[7]: /docs/v3/docsearch
+[8]: https://crawler.algolia.com/
diff --git a/packages/website/versioned_docs/version-v4/integrations.md b/packages/website/versioned_docs/version-v4/integrations.md
new file mode 100644
index 00000000..59806313
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/integrations.md
@@ -0,0 +1,45 @@
+---
+title: Supported Integrations
+---
+
+We worked with **documentation website generators** to have DocSearch directly embedded as a first class citizen in the websites they produce.
+
+## Our great integrations
+
+So, if you're using one of the following tools, check out their documentation to see how to enable DocSearch on your website:
+
+- [Docusaurus v1][1] - [How to enable search][2]
+- [Docusaurus v2 & v3][3] - [DocSearch adapter (recommended)][23] / [Using Algolia DocSearch][4]
+- [VuePress][5] - [Algolia Search][6]
+- [VitePress][21] - [Search][22]
+- [Starlight][7] - [Algolia Search][8]
+- [LaRecipe][9] - [Algolia Search][10]
+- [Orchid][11] - [Algolia Search][12]
+- [Smooth DOC][13] - [DocSearch][14]
+- [Docsy][15] - [Configure Algolia DocSearch][16]
+- [Lotus Docs][19] - [Enabling the DocSearch Plugin][20]
+- [Sphinx](https://www.sphinx-doc.org/en/master/) - [Algolia DocSearch for Sphinx](https://sphinx-docsearch.readthedocs.io/)
+
+If you're maintaining a similar tool and want us to add you to the list, [feel free to make a pull request](https://github.com/algolia/docsearch/edit/main/packages/website/docs/integrations.md) and [contribute to Code Exchange](https://www.algolia.com/developers/code-exchange/contribute/). We're happy to help.
+
+[1]: https://v1.docusaurus.io/
+[2]: https://v1.docusaurus.io/docs/en/search
+[3]: https://docusaurus.io/
+[4]: https://docusaurus.io/docs/search#using-algolia-docsearch
+[5]: https://vuepress.vuejs.org/
+[6]: https://vuepress.vuejs.org/theme/default-theme-config.html#algolia-search
+[7]: https://starlight.astro.build/
+[8]: https://starlight.astro.build/guides/site-search/#algolia-docsearch
+[9]: https://larecipe.saleem.dev/docs/2.2/overview
+[10]: https://larecipe.saleem.dev/docs/2.2/search#available-engines
+[11]: https://orchid.run
+[12]: https://orchid.run/plugins/orchidsearch#algolia-docsearch
+[13]: https://next-smooth-doc.vercel.app/
+[14]: https://next-smooth-doc.vercel.app/docs/docsearch/
+[15]: https://www.docsy.dev/
+[16]: https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch
+[19]: https://lotusdocs.dev/docs/
+[20]: https://lotusdocs.dev/docs/guides/features/docsearch/#enabling-the-docsearch-plugin
+[21]: https://vitepress.dev/
+[22]: https://vitepress.dev/reference/default-theme-search#algolia-search
+[23]: /docs/docusaurus-adapter
diff --git a/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
new file mode 100644
index 00000000..3dbf5caa
--- /dev/null
+++ b/packages/website/versioned_docs/version-v4/manage-your-crawls.mdx
@@ -0,0 +1,67 @@
+---
+title: "[Pre-v4] Manage your crawls"
+---
+
+:::caution
+This UI is deprecated and no longer maintained. For the latest instructions, please use the new documentation: [Crawler Configuration Visual UI](./crawler-configuration-visual). You can find the new Crawler UI at [dashboard.algolia.com/crawler](https://dashboard.algolia.com/crawler).
+:::
+
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+
+DocSearch comes with the [Algolia Crawler web interface](https://crawler.algolia.com/) that allows you to configure how and when your Algolia index will be populated.
+
+## Trigger a new crawl
+
+Head over to the `Overview` section to `start`, `restart` or `pause` your crawls and view a real-time summary.
+
+
+
+
+
+
+docsearch-default.js
+
+
+The main blue element will be your `.DocSearch-content` container. More details in the following guidelines.
+
+### Use the right classes as [`recordProps`][2]
+
+You can add some specific static classes to help us find your content role. These classes can not involve any style changes. These dedicated classes will help us to create a great learn-as-you-type experience from your documentation.
+
+- Add a static class `DocSearch-content` to the main container of your textual content. Most of the time, this tag is a `` or `