#@rspress/plugin-algolia
This plugin replaces Rspress's built-in search with Algolia through DocSearch.
#Installation
npm add @rspress/plugin-algolia -Dyarn add @rspress/plugin-algolia -Dpnpm add @rspress/plugin-algolia -Dbun add @rspress/plugin-algolia -Ddeno add npm:@rspress/plugin-algolia -D#Usage
First, add the following configuration to rspress.config.ts:
// rspress.config.ts
import path from 'path';
import { defineConfig } from '@rspress/core';
import { pluginAlgolia } from '@rspress/plugin-algolia';
export default defineConfig({
plugins: [pluginAlgolia()],
});Then override the Search component with an Algolia-powered search box through Custom Theme.
// theme/index.tsx
import { Search as PluginAlgoliaSearch } from '@rspress/plugin-algolia/runtime';
const Search = () => {
return (
<PluginAlgoliaSearch
docSearchProps={{
appId: 'R2IYF7ETH7', // Replace with your own Algolia appId
apiKey: '599cec31baffa4868cae4e79f180729b', // Replace with your own Algolia apiKey
indexName: 'docsearch', // Replace with your own Algolia indexName
}}
/>
);
};
export { Search };
export * from '@rspress/core/theme-original';#Configuration
The plugin accepts an options object with the following type:
interface Options {
verificationContent?: string;
}#verificationContent
- Type:
string | undefined - Default:
undefined
Used for meta tag verification when creating an Algolia crawler. Format: <meta name="algolia-site-verification" content="YOUR_VERIFICATION_CONTENT" />. See Create a new crawler - Algolia.
#SearchProps
The SearchProps type from @rspress/plugin-algolia/runtime is as follows:
import type { DocSearchProps } from '@docsearch/react';
type Locales = Record<
string,
{ translations: DocSearchProps['translations']; placeholder: string }
>;
type SearchProps = {
/**
* @link https://docsearch.algolia.com/docs/api
*/
docSearchProps?: DocSearchProps;
locales?: Locales;
};#docSearchProps
- Type:
import('@docsearch/react').DocSearchProps - Default:
undefined
docSearchProps is passed directly to the <DocSearch /> component from @docsearch/react. For specific types, see the DocSearch documentation.
#locales
- Type:
type Locales = Record<
string,
{ translations: DocSearchProps['translations']; placeholder: string }
>;- Default:
{}
For customizing translated text in different languages, Rspress provides the following translated text for import.
import type { DocSearchProps } from '@docsearch/react';
export type Locales = Record<
string,
{ translations: DocSearchProps['translations']; placeholder: string }
>;
// cspell:disable
export const ZH_LOCALES: Locales = {
zh: {
placeholder: '搜索文档',
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索',
},
modal: {
searchBox: {
clearButtonTitle: '清除查询条件',
clearButtonAriaLabel: '清除查询条件',
closeButtonText: '取消',
closeButtonAriaLabel: '取消',
},
startScreen: {
recentSearchesTitle: '搜索历史',
noRecentSearchesText: '没有搜索历史',
saveRecentSearchButtonTitle: '保存至搜索历史',
removeRecentSearchButtonTitle: '从搜索历史中移除',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除',
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查你的网络连接',
},
footer: {
selectText: '选择',
navigateText: '切换',
closeText: '关闭',
poweredByText: '搜索提供者',
},
noResultsScreen: {
noResultsText: '无法找到相关结果',
suggestedQueryText: '你可以尝试查询',
reportMissingResultsText: '你认为该查询应该有结果?',
reportMissingResultsLinkText: '点击反馈',
},
},
},
},
} as const;
export const RU_LOCALES: Locales = {
ru: {
placeholder: 'Поиск в документации',
translations: {
button: {
buttonText: 'Поиск',
buttonAriaLabel: 'Поиск',
},
modal: {
searchBox: {
clearButtonTitle: 'Очистить поиск',
clearButtonAriaLabel: 'Очистить поиск',
closeButtonText: 'Закрыть',
closeButtonAriaLabel: 'Закрыть',
},
startScreen: {
recentSearchesTitle: 'История поиска',
noRecentSearchesText: 'Нет истории поиска',
saveRecentSearchButtonTitle: 'Сохранить в истории поиска',
removeRecentSearchButtonTitle: 'Удалить из истории поиска',
favoriteSearchesTitle: 'Избранное',
removeFavoriteSearchButtonTitle: 'Удалить из избранного',
},
errorScreen: {
titleText: 'Невозможно получить результаты',
helpText: 'Проверьте подключение к Интернету',
},
footer: {
selectText: 'выбрать',
navigateText: 'перейти',
closeText: 'закрыть',
poweredByText: 'поиск от',
},
noResultsScreen: {
noResultsText: 'Ничего не найдено',
suggestedQueryText: 'Попробуйте изменить запрос',
reportMissingResultsText: 'Считаете, что результаты должны быть?',
reportMissingResultsLinkText: 'Сообщите об этом',
},
},
},
},
} as const;
export const TA_LOCALES: Locales = {
ta: {
placeholder: 'ஆவணங்களைத் தேடுக...',
translations: {
button: {
buttonText: 'தேடுக',
buttonAriaLabel: 'தேடுக',
},
modal: {
searchBox: {
clearButtonTitle: 'தேடலை நீக்கவும்',
clearButtonAriaLabel: 'தேடலை நீக்கவும்',
closeButtonText: 'இரத்து செய்',
closeButtonAriaLabel: 'இரத்து செய்',
},
startScreen: {
recentSearchesTitle: 'சமீபத்திய தேடல்கள்',
noRecentSearchesText: 'சமீபத்திய தேடல்கள் எதுவும் இல்லை',
saveRecentSearchButtonTitle: 'தேடல் வரலாற்றில் சேர்க்கவும்',
removeRecentSearchButtonTitle: 'தேடல் வரலாற்றிலிருந்து நீக்கவும்',
favoriteSearchesTitle: 'பிடித்தவை',
removeFavoriteSearchButtonTitle: 'பிடித்தவையிலிருந்து நீக்கவும்',
},
errorScreen: {
titleText: 'முடிவுகளைப் பெற முடியவில்லை',
helpText: 'உங்கள் இணைய இணைப்பைச் சரிபார்க்கவும்',
},
footer: {
selectText: 'தேர்ந்தெடுக்க',
navigateText: 'நகர்த்த',
closeText: 'மூட',
poweredByText: 'வழங்குபவர்',
},
noResultsScreen: {
noResultsText: 'முடிவுகள் கிடைக்கவில்லை',
suggestedQueryText: 'இவற்றைத் தேட முயற்சிக்கவும்',
reportMissingResultsText:
'இதற்கு முடிவுகள் கிடைத்திருக்க வேண்டும் என நினைக்கிறீர்களா?',
reportMissingResultsLinkText: 'எங்களுக்குத் தெரியப்படுத்துங்கள்',
},
},
},
},
} as const;
// cspell:enable
Rspress provides Chinese translations by default, and you can customize translated text for different languages through locales.
- Example:
import { Search as PluginAlgoliaSearch, ZH_LOCALES } from '@rspress/plugin-algolia/runtime';
<PluginAlgoliaSearch locales={ZH_LOCALES} />
// or
<PluginAlgoliaSearch
locales={{
en: {
placeholder: 'Search Documentation',
translations: {
button: {
buttonText: 'Search',
buttonAriaLabel: 'Search',
}
}
},
...ZH_LOCALES,
}}
/>#Algolia crawler config
Here is an example config based on what this site uses:
new Crawler({
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
rateLimit: 8,
maxDepth: 10,
startUrls: ['https://rspress.rs'],
sitemaps: ['https://rspress.rs/sitemap.xml'],
discoveryPatterns: ['https://rspress.rs/**'],
actions: [
{
indexName: 'doc_search_rspress_v2_pages',
pathsToMatch: ['https://rspress.rs/**'],
recordExtractor: ({ $, helpers }) => {
// Remove badge elements to prevent their text from being indexed
$('.rp-badge').remove();
// Remove non-doc elements (e.g. version switcher) from h1 to keep title text clean
$('.rspress-doc h1 .rp-not-doc').remove();
const $activeNavItem = $('.rp-nav-menu__item.rp-nav-menu__item--active')
.first()
.clone();
const lvl0 = $activeNavItem.text().trim() || '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: {
doc_search_rspress_v2_pages: {
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',
],
minWordSizefor1Typo: 3,
minWordSizefor2Typos: 7,
allowTyposOnNumericTokens: false,
minProximity: 1,
ignorePlurals: true,
advancedSyntax: true,
attributeCriteriaComputedByMinProximity: true,
removeWordsIfNoResults: 'allOptional',
},
},
schedule: 'on tuesday',
indexPrefix: 'rspress-v2-crawler-',
});#Distinguish search results based on i18n
You can achieve internationalized search results by combining Runtime API with docSearchProps.
Here's an example using docSearchProps.searchParameters:
// theme/index.tsx
import { useLang } from '@rspress/core/runtime';
import { Search as PluginAlgoliaSearch } from '@rspress/plugin-algolia/runtime';
const Search = () => {
const lang = useLang();
return (
<PluginAlgoliaSearch
docSearchProps={{
appId: 'R2IYF7ETH7',
apiKey: '599cec31baffa4868cae4e79f180729b',
indexName: 'docsearch',
searchParameters: {
facetFilters: [`lang:${lang}`],
},
}}
/>
);
};
export { Search };
export * from '@rspress/core/theme-original';