Plugins
Discover and learn how to use VitePress plugins to extend functionality and enhance your documentation site.
Overview
VitePress plugins extend the core functionality by adding new features, integrations, and customizations. They can be official plugins maintained by the VitePress team or community-created plugins.
Official Plugins
Search Plugins
Local Search
Built-in local search functionality that indexes your content.
// .vitepress/config.js
export default {
themeConfig: {
search: {
provider: 'local',
options: {
translations: {
button: {
buttonText: 'Search',
buttonAriaLabel: 'Search'
},
modal: {
noResultsText: 'No results found',
resetButtonTitle: 'Reset search',
footer: {
selectText: 'to select',
navigateText: 'to navigate',
closeText: 'to close'
}
}
}
}
}
}
}
Algolia Search
Powerful search integration with Algolia DocSearch.
export default {
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
indexName: 'YOUR_INDEX_NAME',
locales: {
zh: {
placeholder: '搜索文档',
translations: {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档'
}
}
}
}
}
}
}
}
PWA Plugin
Enable Progressive Web App features for your VitePress site.
// .vitepress/config.js
export default {
pwa: {
mode: 'development',
base: '/',
scope: '/',
includeAssets: ['favicon.ico'],
manifest: {
name: 'VitePress PWA',
short_name: 'VitePressPWA',
theme_color: '#ffffff',
background_color: '#ffffff',
display: 'standalone',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
},
workbox: {
globPatterns: ['**/*.{js,css,html,png,jpg,jpeg,gif,svg,woff2}']
}
}
}
Sitemap Plugin
Automatically generate XML sitemaps for better SEO.
export default {
sitemap: {
hostname: 'https://your-domain.com',
transformItems: (items) => {
// Filter out private pages
return items.filter(item => !item.url.includes('/private/'))
}
}
}
Community Plugins
Content Plugins
VitePress Plugin Auto Sidebar
Automatically generate sidebar configuration from your file structure.
npm install vitepress-plugin-auto-sidebar
// .vitepress/config.js
import { generateSidebar } from 'vitepress-plugin-auto-sidebar'
export default {
themeConfig: {
sidebar: generateSidebar({
documentRootPath: 'docs',
scanStartPath: null,
basePath: null,
resolvePath: '/guide/',
useTitleFromFileHeading: true,
useTitleFromFrontmatter: true,
collapsed: true,
collapseDepth: 2,
excludeFiles: ['first.md', 'secret.md'],
excludeFolders: ['secret-folder']
})
}
}
VitePress Plugin Mermaid
Add Mermaid diagram support to your documentation.
npm install vitepress-plugin-mermaid mermaid
// .vitepress/config.js
import { withMermaid } from 'vitepress-plugin-mermaid'
export default withMermaid({
title: 'My Documentation',
description: 'Documentation with Mermaid diagrams',
mermaid: {
theme: 'default'
}
})
Usage in Markdown:
```mermaid
graph TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Debug]
D --> B
#### VitePress Plugin Code Copy
Add copy-to-clipboard functionality to code blocks.
```bash
npm install vitepress-plugin-code-copy
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import { enhanceAppWithTabs } from 'vitepress-plugin-code-copy'
export default {
extends: DefaultTheme,
enhanceApp(ctx) {
enhanceAppWithTabs(ctx)
}
}
Analytics Plugins
VitePress Plugin Google Analytics
Easy Google Analytics integration.
npm install vitepress-plugin-google-analytics
// .vitepress/config.js
import { googleAnalytics } from 'vitepress-plugin-google-analytics'
export default {
plugins: [
googleAnalytics({
id: 'GA_MEASUREMENT_ID'
})
]
}
VitePress Plugin Umami
Privacy-focused analytics with Umami.
npm install vitepress-plugin-umami
import { umami } from 'vitepress-plugin-umami'
export default {
plugins: [
umami({
src: 'https://analytics.umami.is/script.js',
id: 'your-website-id'
})
]
}
UI Enhancement Plugins
VitePress Plugin Tabs
Add tabbed content support.
npm install vitepress-plugin-tabs
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import { enhanceAppWithTabs } from 'vitepress-plugin-tabs'
export default {
extends: DefaultTheme,
enhanceApp(ctx) {
enhanceAppWithTabs(ctx)
}
}
Usage:
::: tabs
== Tab 1
Content for tab 1
== Tab 2
Content for tab 2
:::
VitePress Plugin Demo Block
Create live code demonstrations.
npm install vitepress-plugin-demoblock
// .vitepress/config.js
import { demoblock } from 'vitepress-plugin-demoblock'
export default {
plugins: [demoblock()]
}
Usage:
::: demo
```vue
<template>
<div class="demo-component">
<button @click="count++">Count: {{ count }}</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<style scoped>
.demo-component {
padding: 20px;
border: 1px solid #ccc;
border-radius: 4px;
}
</style>
:::
## Creating Custom Plugins
### Plugin Structure
```js
// plugins/my-plugin.js
export function myPlugin(options = {}) {
return {
name: 'my-plugin',
configResolved(config) {
// Access to final config
},
buildStart() {
// Build start hook
},
transform(code, id) {
// Transform code
if (id.endsWith('.md')) {
// Process markdown files
return transformMarkdown(code, options)
}
},
generateBundle() {
// Generate additional files
}
}
}
function transformMarkdown(code, options) {
// Custom markdown transformation
return code.replace(/\[custom\]/g, options.replacement || 'Custom Content')
}
Using Custom Plugins
// .vitepress/config.js
import { myPlugin } from './plugins/my-plugin.js'
export default {
vite: {
plugins: [
myPlugin({
replacement: 'My Custom Replacement'
})
]
}
}
Advanced Plugin Example
// plugins/code-group-plugin.js
export function codeGroupPlugin() {
return {
name: 'code-group-plugin',
transform(code, id) {
if (!id.endsWith('.md')) return
// Transform custom code group syntax
return code.replace(
/:::\s*code-group\s*\n([\s\S]*?)\n:::/g,
(match, content) => {
const tabs = content.split(/^```(\w+)\s*\[([^\]]+)\]\s*$/gm)
let result = '<div class="code-group">\n'
// Generate tab buttons
result += '<div class="code-group-tabs">\n'
for (let i = 1; i < tabs.length; i += 3) {
const lang = tabs[i]
const title = tabs[i + 1]
result += `<button class="code-group-tab" data-lang="${lang}">${title}</button>\n`
}
result += '</div>\n'
// Generate tab content
for (let i = 1; i < tabs.length; i += 3) {
const lang = tabs[i]
const code = tabs[i + 2].trim()
result += `<div class="code-group-content" data-lang="${lang}">\n`
result += `\`\`\`${lang}\n${code}\n\`\`\`\n`
result += '</div>\n'
}
result += '</div>'
return result
}
)
}
}
}
Plugin Development Best Practices
Error Handling
export function safePlugin(options = {}) {
return {
name: 'safe-plugin',
transform(code, id) {
try {
return processCode(code, id, options)
} catch (error) {
console.error(`Plugin error in ${id}:`, error)
return code // Return original code on error
}
}
}
}
Configuration Validation
import { z } from 'zod'
const optionsSchema = z.object({
enabled: z.boolean().default(true),
pattern: z.string().regex(/^\/.*\/$/).optional(),
replacement: z.string().default('')
})
export function validatedPlugin(userOptions = {}) {
const options = optionsSchema.parse(userOptions)
return {
name: 'validated-plugin',
// Plugin implementation
}
}
Performance Optimization
export function optimizedPlugin() {
const cache = new Map()
return {
name: 'optimized-plugin',
transform(code, id) {
// Use caching for expensive operations
if (cache.has(id)) {
return cache.get(id)
}
const result = expensiveTransform(code)
cache.set(id, result)
return result
},
buildEnd() {
// Clean up cache
cache.clear()
}
}
}
Plugin Testing
Unit Testing
// tests/plugin.test.js
import { describe, it, expect } from 'vitest'
import { myPlugin } from '../plugins/my-plugin.js'
describe('myPlugin', () => {
it('should transform custom syntax', () => {
const plugin = myPlugin({ replacement: 'Test' })
const code = 'This is [custom] content'
const result = plugin.transform(code, 'test.md')
expect(result).toBe('This is Test content')
})
it('should handle empty options', () => {
const plugin = myPlugin()
const code = 'This is [custom] content'
const result = plugin.transform(code, 'test.md')
expect(result).toBe('This is Custom Content content')
})
})
Integration Testing
// tests/integration.test.js
import { createVitePress } from 'vitepress'
import { myPlugin } from '../plugins/my-plugin.js'
describe('Plugin Integration', () => {
it('should work with VitePress build', async () => {
const config = {
vite: {
plugins: [myPlugin()]
}
}
const vitepress = await createVitePress(config)
const result = await vitepress.build()
expect(result.success).toBe(true)
})
})
Popular Plugin Collections
VitePress Ecosystem
- @vitepress/plugin-search - Enhanced search functionality
- @vitepress/plugin-pwa - Progressive Web App features
- @vitepress/plugin-sitemap - XML sitemap generation
Community Collections
- vitepress-plugins - Collection of useful plugins
- awesome-vitepress - Curated list of VitePress resources
- vitepress-community - Community-maintained plugins
Plugin Configuration Examples
Multi-plugin Setup
// .vitepress/config.js
import { defineConfig } from 'vitepress'
import { searchPlugin } from '@vitepress/plugin-search'
import { pwaPlugin } from '@vitepress/plugin-pwa'
import { analyticsPlugin } from 'vitepress-plugin-analytics'
export default defineConfig({
vite: {
plugins: [
searchPlugin({
previewLength: 62,
buttonLabel: 'Search',
placeholder: 'Search docs'
}),
pwaPlugin({
outDir: '.vitepress/dist',
registerType: 'autoUpdate'
}),
analyticsPlugin({
gtag: 'GA_MEASUREMENT_ID'
})
]
}
})
Environment-specific Plugins
const isDev = process.env.NODE_ENV === 'development'
const isProd = process.env.NODE_ENV === 'production'
export default defineConfig({
vite: {
plugins: [
// Always enabled
searchPlugin(),
// Development only
...(isDev ? [
debugPlugin(),
hotReloadPlugin()
] : []),
// Production only
...(isProd ? [
analyticsPlugin(),
compressionPlugin(),
sitemapPlugin()
] : [])
]
}
})
Troubleshooting
Common Issues
Plugin Not Loading
- Check plugin installation:
npm list plugin-name
- Verify import path and syntax
- Check for TypeScript compatibility
Build Errors
- Review plugin configuration
- Check for conflicting plugins
- Verify plugin compatibility with VitePress version
Performance Issues
- Profile plugin execution time
- Check for memory leaks
- Optimize expensive operations
Debug Mode
export function debugPlugin() {
return {
name: 'debug-plugin',
configResolved(config) {
console.log('Plugin config:', config)
},
buildStart() {
console.log('Build started')
},
transform(code, id) {
console.log(`Transforming: ${id}`)
return code
}
}
}
Resources
Official Documentation
Community Resources
Tools
The VitePress plugin ecosystem is constantly growing. Contribute your own plugins and help make VitePress even better!