Pesquisa
Pesquisa Local
VitePress oferece suporte à pesquisa de texto completa usando um índice no navegador graças ao minisearch. Para habilitar esse recurso, basta definir a opção themeConfig.search.provider como 'local' no arquivo .vitepress/config.ts:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local'
}
}
})Exemplo de resultado:

Alternativamente, você pode usar Algolia DocSearch ou alguns plugins da comunidade como https://www.npmjs.com/package/vitepress-plugin-search ou https://www.npmjs.com/package/vitepress-plugin-pagefind.
i18n
Você pode usar uma configuração como esta para usar a pesquisa multilínguas:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
pt: { // torne isto `root` se quiser traduzir a localidade padrão
translations: {
button: {
buttonText: 'Pesquisar',
buttonAriaLabel: 'Pesquisar'
},
modal: {
displayDetails: 'Mostrar lista detalhada',
resetButtonTitle: 'Redefinir pesquisa',
backButtonTitle: 'Fechar pesquisa',
noResultsText: 'Nenhum resultado',
footer: {
selectText: 'Selecionar',
selectKeyAriaLabel: 'Enter',
navigateText: 'Navegar',
navigateUpKeyAriaLabel: 'Seta para cima',
navigateDownKeyAriaLabel: 'Seta para baixo',
closeText: 'Fechar',
closeKeyAriaLabel: 'Esc'
}
}
}
}
}
}
}
}
})Opções MiniSearch
Você pode configurar o MiniSearch assim:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
miniSearch: {
/**
* @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
*/
options: {
/* ... */
},
/**
* @type {import('minisearch').SearchOptions}
* @default
* { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
*/
searchOptions: {
/* ... */
}
}
}
}
}
})Saiba mais na documentação do MiniSearch.
Apresentador de Conteúdo Personalizado
Você pode personalizar a função usada para apresentar o conteúdo markdown antes de indexá-lo:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
/**
* @param {string} src
* @param {import('vitepress').MarkdownEnv} env
* @param {import('markdown-it-async')} md
*/
async _render(src, env, md) {
// retorna uma string HTML
}
}
}
}
})Essa função será removida dos dados do site no lado do cliente, então você pode usar APIs do Node.js nela.
Exemplo: Excluindo páginas da pesquisa
Você pode excluir páginas da pesquisa adicionando search: false ao frontmatter da página. Alternativamente:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
}
}
})Nota
No caso uma função _render personalizada ser fornecida, você precisa manipular o search: false do frontmatter por conta própria. Além disso, o objeto env não estará completamente populado antes que md.renderAsync seja chamado, então verificações em propriedades opcionais env, como frontmatter, devem ser feitas após isso.
Exemplo: Transformando conteúdo - adicionando âncoras
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.title)
return await md.renderAsync(`# ${env.frontmatter.title}`) + html
return html
}
}
}
}
})Pesquisa Algolia
VitePress oferece suporte à pesquisa em seu site de documentação usando Algolia DocSearch. Consulte o guia de início deles. Em seu arquivo .vitepress/config.ts, você precisará fornecer pelo menos o seguinte para que funcione:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...'
}
}
}
})i18n
Você pode usar uma configuração como esta para usar a pesquisa multilínguas:
Clique para expandir
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索'
},
modal: {
searchBox: {
clearButtonTitle: '清除',
clearButtonAriaLabel: '清除查询',
closeButtonText: '关闭',
closeButtonAriaLabel: '关闭',
placeholderText: '搜索文档或向 AI 提问',
placeholderTextAskAi: '再问一个问题...',
placeholderTextAskAiStreaming: '正在回答...',
searchInputLabel: '搜索',
backToKeywordSearchButtonText: '返回关键词搜索',
backToKeywordSearchButtonAriaLabel: '返回关键词搜索',
newConversationPlaceholder: '提问',
conversationHistoryTitle: '我的对话历史',
startNewConversationText: '开始新的对话',
viewConversationHistoryText: '对话历史',
threadDepthErrorPlaceholder: '对话已达上限'
},
newConversation: {
newConversationTitle: '我今天能帮你什么?',
newConversationDescription:
'我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
footer: {
selectText: '选择',
submitQuestionText: '提交问题',
selectKeyAriaLabel: '回车键',
navigateText: '导航',
navigateUpKeyAriaLabel: '向上箭头',
navigateDownKeyAriaLabel: '向下箭头',
closeText: '关闭',
backToSearchText: '返回搜索',
closeKeyAriaLabel: 'Esc 键',
poweredByText: '由…提供支持'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查网络连接。'
},
startScreen: {
recentSearchesTitle: '最近',
noRecentSearchesText: '暂无最近搜索',
saveRecentSearchButtonTitle: '保存此搜索',
removeRecentSearchButtonTitle: '从历史记录中移除此搜索',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除此搜索',
recentConversationsTitle: '最近对话',
removeRecentConversationButtonTitle: '从历史记录中移除此对话'
},
noResultsScreen: {
noResultsText: '未找到相关结果',
suggestedQueryText: '尝试搜索',
reportMissingResultsText: '认为此查询应该有结果?',
reportMissingResultsLinkText: '告诉我们。'
},
resultsScreen: {
askAiPlaceholder: '询问 AI:',
noResultsAskAiPlaceholder: '文档里没找到?让 Ask AI 帮忙:'
},
askAiScreen: {
disclaimerText: '回答由 AI 生成,可能会出错。请核实。',
relatedSourcesText: '相关来源',
thinkingText: '思考中...',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
copyButtonTitle: '复制',
likeButtonTitle: '喜欢',
dislikeButtonTitle: '不喜欢',
thanksForFeedbackText: '感谢你的反馈!',
preToolCallText: '搜索中...',
duringToolCallText: '搜索中...',
afterToolCallText: '已搜索',
stoppedStreamingText: '你已停止此回复',
errorTitleText: '聊天错误',
threadDepthExceededMessage: '为保持回答准确,此对话已关闭。',
startNewConversationButtonText: '开始新的对话'
}
}
},
askAi: {
sidePanel: {
button: {
translations: {
buttonText: '询问 AI',
buttonAriaLabel: '询问 AI'
}
},
panel: {
translations: {
header: {
title: '询问 AI',
conversationHistoryTitle: '我的对话历史',
newConversationText: '开始新的对话',
viewConversationHistoryText: '对话历史'
},
promptForm: {
promptPlaceholderText: '提问',
promptAnsweringText: '正在回答...',
promptAskAnotherQuestionText: '再问一个问题',
promptDisclaimerText: '回答由 AI 生成,可能会出错。',
promptLabelText: '按回车发送,Shift+回车换行。',
promptAriaLabelText: '问题输入'
},
conversationScreen: {
preToolCallText: '搜索中...',
searchingText: '搜索中...',
toolCallResultText: '已搜索',
conversationDisclaimer:
'回答由 AI 生成,可能会出错。请核实。',
reasoningText: '推理中...',
thinkingText: '思考中...',
relatedSourcesText: '相关来源',
stoppedStreamingText: '你已停止此回复',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
likeButtonTitle: '喜欢',
dislikeButtonTitle: '不喜欢',
thanksForFeedbackText: '感谢你的反馈!',
errorTitleText: '聊天错误'
},
newConversationScreen: {
titleText: '我今天能帮你什么?',
introductionText:
'我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
logo: {
poweredByText: '由…提供支持'
}
}
}
}
}
}
}
}
}
}
})Consulte a documentação oficial da Algolia para saber mais. Para começar rapidamente, você também pode copiar as traduções usadas por este site do nosso repositório no GitHub.
Suporte ao Algolia Ask AI
Se quiser incluir o Ask AI, adicione askAi em options:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
// askAi: "SEU-ID-DO-ASSISTENTE"
// OU
askAi: {
// no mínimo, você deve fornecer o assistantId recebido da Algolia
assistantId: 'XXXYYY',
// substituições opcionais — se omitidas, os valores appId/apiKey/indexName de nível superior são reutilizados
// apiKey: '...',
// appId: '...',
// indexName: '...'
}
}
}
}
})Nota
Caso queira apenas a pesquisa por palavra-chave, omita askAi.
Painel Lateral do Ask AI
O DocSearch v4.5+ suporta um painel lateral do Ask AI opcional. Quando habilitado, pode ser aberto com Ctrl/Cmd+I por padrão. A Referência da API do Painel Lateral contém a lista completa de opções.
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
// Espelha a API do @docsearch/sidepanel-js SidepanelProps
panel: {
variant: 'floating', // ou 'inline'
side: 'right',
width: '360px',
expandedWidth: '580px',
suggestedQuestions: true
}
}
}
}
}
}
})Se precisar desabilitar o atalho de teclado, use a opção keyboardShortcuts do painel lateral:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
keyboardShortcuts: {
'Ctrl/Cmd+I': false
}
}
}
}
}
}
})Modo (auto / sidePanel / hybrid / modal)
Você pode controlar opcionalmente como o VitePress integra a pesquisa por palavra-chave e o Ask AI:
mode: 'auto'(padrão): inferehybridquando a pesquisa por palavra-chave está configurada, caso contráriosidePanelquando o painel lateral do Ask AI está configurado.mode: 'sidePanel': força apenas o painel lateral (oculta o botão de pesquisa por palavra-chave).mode: 'hybrid': habilita o modal de pesquisa por palavra-chave + painel lateral do Ask AI (requer configuração de pesquisa por palavra-chave).mode: 'modal': mantém o Ask AI dentro do modal do DocSearch (mesmo se você configurou o painel lateral).
Apenas Ask AI (sem pesquisa por palavra-chave)
Se quiser usar apenas o painel lateral do Ask AI, você pode omitir a configuração de pesquisa por palavra-chave de nível superior e fornecer as credenciais em askAi:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
mode: 'sidePanel',
askAi: {
assistantId: 'XXXYYY',
appId: '...',
apiKey: '...',
indexName: '...',
sidePanel: true
}
}
}
}
})Configuração Crawler
Aqui está um exemplo de configuração baseado na qual este site usa:
new Crawler({
appId: '...',
apiKey: '...',
rateLimit: 8,
startUrls: ['https://vitepress.dev/'],
renderJavaScript: false,
sitemaps: [],
exclusionPatterns: [],
ignoreCanonicalTo: false,
discoveryPatterns: ['https://vitepress.dev/**'],
schedule: 'at 05:10 on Saturday',
actions: [
{
indexName: 'vitepress',
pathsToMatch: ['https://vitepress.dev/**'],
recordExtractor: ({ $, helpers }) => {
return helpers.docsearch({
recordProps: {
lvl1: '.content h1',
content: '.content p, .content li',
lvl0: {
selectors: 'section.has-active div h2',
defaultValue: 'Documentation'
},
lvl2: '.content h2',
lvl3: '.content h3',
lvl4: '.content h4',
lvl5: '.content h5'
},
indexHeadings: true
})
}
}
],
initialIndexSettings: {
vitepress: {
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: '<span class="algolia-docsearch-suggestion--highlight">',
highlightPostTag: '</span>',
minWordSizefor1Typo: 3,
minWordSizefor2Typos: 7,
allowTyposOnNumericTokens: false,
minProximity: 1,
ignorePlurals: true,
advancedSyntax: true,
attributeCriteriaComputedByMinProximity: true,
removeWordsIfNoResults: 'allOptional'
}
}
})