Skip to content

VitePress Cheatsheet

VitePress - Vite & Vue Powered Static Site Generator

VitePress is a static site generator (SSG) designed to build fast, content-centric websites. Built on top of Vite, it provides a great developer experience with Vue.js-powered theming and customization.

Table of Contents

Installation

Quick Start

# Create new VitePress project
npm create vitepress@latest my-docs

# Navigate to project
cd my-docs

# Install dependencies
npm install

# Start development server
npm run docs:dev

Manual Installation

# Initialize npm project
npm init -y

# Install VitePress
npm install --save-dev vitepress

# Create basic structure
mkdir docs
echo '# Hello VitePress' > docs/index.md

Package.json Scripts

{
  "scripts": {
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs"
  }
}

Getting Started

Basic Setup

# Create docs directory
mkdir docs

# Create index page
echo '# Welcome to My Documentation' > docs/index.md

# Create config file
mkdir docs/.vitepress

Basic Configuration

// docs/.vitepress/config.js
export default {
  title: 'My Documentation',
  description: 'A comprehensive guide',
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' },
      { text: 'API', link: '/api/' }
    ],
    sidebar: [
      {
        text: 'Guide',
        items: [
          { text: 'Introduction', link: '/guide/' },
          { text: 'Getting Started', link: '/guide/getting-started' }
        ]
      }
    ]
  }
}

First Pages

<!-- docs/index.md -->
---
layout: home
hero:
  name: My Project
  text: Amazing documentation
  tagline: Build something awesome
  actions:
    - theme: brand
      text: Get Started
      link: /guide/
    - theme: alt
      text: View on GitHub
      link: https://github.com/user/repo
features:
  - title: Fast
    details: Built with Vite for lightning-fast development
  - title: Flexible
    details: Customize with Vue.js components
  - title: SEO Friendly
    details: Static site generation for better SEO
---
<!-- docs/guide/index.md -->
# Introduction

Welcome to the guide section of our documentation.

## What is this project?

This project helps you build amazing things.

## Quick Start

1. Install the package
2. Configure your settings
3. Start building

Project Structure

Basic Structure

docs/
├── .vitepress/
   ├── config.js          # Configuration file
   ├── theme/             # Custom theme
   └── cache/             # Build cache
├── guide/
   ├── index.md
   ├── getting-started.md
   └── advanced.md
├── api/
   ├── index.md
   └── reference.md
├── public/                # Static assets
   ├── images/
   └── favicon.ico
└── index.md              # Homepage

Advanced Structure

docs/
├── .vitepress/
   ├── config.js
   ├── config/
      ├── nav.js
      ├── sidebar.js
      └── plugins.js
   ├── theme/
      ├── index.js
      ├── components/
      ├── styles/
      └── layouts/
   ├── components/        # Global components
   └── public/           # Theme assets
├── en/                   # English docs
├── zh/                   # Chinese docs
├── guide/
├── api/
├── examples/
└── index.md

Configuration

Basic Configuration

// docs/.vitepress/config.js
export default {
  // Site metadata
  title: 'VitePress',
  description: 'Vite & Vue powered static site generator',
  lang: 'en-US',
  base: '/', // Base URL for deployment

  // Theme configuration
  themeConfig: {
    logo: '/logo.svg',
    siteTitle: 'My Docs',

    // Navigation
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' }
    ],

    // Sidebar
    sidebar: {
      '/guide/': [
        {
          text: 'Getting Started',
          items: [
            { text: 'Introduction', link: '/guide/' },
            { text: 'Installation', link: '/guide/installation' }
          ]
        }
      ]
    },

    // Social links
    socialLinks: [
      { icon: 'github', link: 'https://github.com/vuejs/vitepress' },
      { icon: 'twitter', link: 'https://twitter.com/vuejs' }
    ],

    // Footer
    footer: {
      message: 'Released under the MIT License.',
      copyright: 'Copyright © 2023 Evan You'
    }
  }
}

Advanced Configuration

// docs/.vitepress/config.js
import { defineConfig } from 'vitepress'

export default defineConfig({
  title: 'My Documentation',
  description: 'Comprehensive documentation',

  // Head tags
  head: [
    ['link', { rel: 'icon', href: '/favicon.ico' }],
    ['meta', { name: 'theme-color', content: '#3c8772' }],
    ['meta', { property: 'og:type', content: 'website' }],
    ['meta', { property: 'og:locale', content: 'en' }],
    ['script', { src: 'https://cdn.usefathom.com/script.js' }]
  ],

  // Build options
  srcDir: 'src',
  outDir: 'dist',
  cacheDir: '.vitepress/cache',

  // Markdown configuration
  markdown: {
    theme: 'material-theme-palenight',
    lineNumbers: true,
    config: (md) => {
      // Add markdown plugins
      md.use(require('markdown-it-footnote'))
    }
  },

  // Vite configuration
  vite: {
    plugins: [],
    server: {
      port: 3000
    }
  },

  // Build hooks
  buildEnd: (siteConfig) => {
    console.log('Build completed!')
  }
})

TypeScript Configuration

// docs/.vitepress/config.ts
import { defineConfig } from 'vitepress'

export default defineConfig({
  title: 'My Docs',
  description: 'TypeScript powered documentation',

  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' }
    ]
  }
})

Markdown Features

Basic Markdown

# Heading 1
## Heading 2
### Heading 3

**Bold text**
*Italic text*
~~Strikethrough~~

- Unordered list
- Item 2
  - Nested item

1. Ordered list
2. Item 2

[Link text](https://example.com)

![Image alt](./image.png)

`Inline code`

> Blockquote

Code Blocks

```javascript
function hello() {
  console.log('Hello, VitePress!')
}
```

```javascript{1,3-5}
// Line highlighting
function hello() {
  console.log('Hello, VitePress!')
  const name = 'VitePress'
  return `Hello, ${name}!`
}
```

```javascript
// Line numbers
function hello() {
  console.log('Hello, VitePress!')
}
```

Custom Containers

::: info
This is an info box.
:::

::: tip
This is a tip.
:::

::: warning
This is a warning.
:::

::: danger
This is a dangerous warning.
:::

::: details Click me to view the code
```javascript
console.log('Hello, VitePress!')
:::

::: code-group ```javascript [config.js] export default { name: 'config' }

```typescript [config.ts]
export default {
  name: 'config'
} as const
:::
### Tables
```markdown
| Feature | VitePress | Other SSG |
|---------|-----------|-----------|
| Speed   | ⚡ Fast   | 🐌 Slow   |
| Vue     | ✅ Yes    | ❌ No     |
| Vite    | ✅ Yes    | ❌ No     |

Math Expressions

<!-- Inline math -->
The formula is $E = mc^2$.

<!-- Block math -->
$$
\frac{1}{2} \times \frac{3}{4} = \frac{3}{8}
$$

Emoji

:tada: :rocket: :heart:

VitePress is :fire:!

Frontmatter

Basic Frontmatter

---
title: Page Title
description: Page description
layout: doc
---

# Page Content

This page has custom metadata.

Advanced Frontmatter

---
title: Advanced Guide
description: Learn advanced VitePress features
layout: doc
sidebar: true
prev:
  text: 'Getting Started'
  link: '/guide/getting-started'
next:
  text: 'Configuration'
  link: '/guide/configuration'
editLink: true
lastUpdated: true
---

# Advanced Guide

Content goes here.

Home Layout

---
layout: home
hero:
  name: VitePress
  text: Vite & Vue powered static site generator
  tagline: Simple, powerful, and performant
  image:
    src: /logo-with-shadow.png
    alt: VitePress
  actions:
    - theme: brand
      text: Get Started
      link: /guide/what-is-vitepress
    - theme: alt
      text: View on GitHub
      link: https://github.com/vuejs/vitepress

features:
  - icon: ⚡️
    title: Vite, The DX that can't be beat
    details: Feel the speed of Vite. Instant server start and lightning fast HMR.
  - icon: 💡
    title: Designed to be simplicity first
    details: With Markdown-centered content, it's built to help you focus on writing.
  - icon: 🛠️
    title: Power of Vue meets Markdown
    details: Enhance your content with all the features of Vue in Markdown.
---

Custom Layout

---
layout: custom
customData:
  foo: bar
  items:
    - name: Item 1
    - name: Item 2
---

# Custom Layout Page

This page uses a custom layout.

Routing

File-based Routing

# File structure determines routes
docs/
├── index.md          # -> /
├── guide/
   ├── index.md      # -> /guide/
   ├── setup.md      # -> /guide/setup
   └── advanced.md   # -> /guide/advanced
└── api/
    ├── index.md      # -> /api/
    └── reference.md  # -> /api/reference

Dynamic Routes

// docs/.vitepress/config.js
export default {
  async paths() {
    const posts = await getPosts()
    return posts.map(post => ({
      params: { id: post.id },
      content: post.content
    }))
  }
}

Route Metadata

---
title: Custom Title
description: Custom description
head:
  - - meta
    - property: og:title
      content: Custom OG Title
  - - meta
    - property: og:description
      content: Custom OG Description
---

# Page Content

Programmatic Navigation

<template>
  <button @click="navigate">Go to Guide</button>
</template>

<script setup>
import { useRouter } from 'vitepress'

const router = useRouter()

function navigate() {
  router.go('/guide/')
}
</script>

Theming

Default Theme Customization

// docs/.vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import './custom.css'

export default {
  extends: DefaultTheme,
  enhanceApp({ app, router, siteData }) {
    // App-level enhancements
    app.component('MyComponent', MyComponent)
  }
}

Custom CSS

/* docs/.vitepress/theme/custom.css */
:root {
  --vp-c-brand-1: #646cff;
  --vp-c-brand-2: #747bff;
  --vp-c-brand-3: #9499ff;
}

.VPHero .name {
  background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* Dark mode */
.dark {
  --vp-c-brand-1: #747bff;
  --vp-c-brand-2: #9499ff;
}

Custom Layout

<!-- docs/.vitepress/theme/Layout.vue -->
<template>
  <div class="custom-layout">
    <header>
      <nav><!-- Custom navigation --></nav>
    </header>

    <main>
      <Content />
    </main>

    <footer>
      <!-- Custom footer -->
    </footer>
  </div>
</template>

<script setup>
import { Content } from 'vitepress'
</script>

<style scoped>
.custom-layout {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
</style>

Theme Configuration

// docs/.vitepress/config.js
export default {
  themeConfig: {
    // Appearance
    appearance: 'dark', // 'dark' | false

    // Logo
    logo: '/logo.svg',
    siteTitle: 'My Docs',

    // Navigation
    nav: [...],
    sidebar: {...},

    // Edit link
    editLink: {
      pattern: 'https://github.com/user/repo/edit/main/docs/:path',
      text: 'Edit this page on GitHub'
    },

    // Last updated
    lastUpdated: {
      text: 'Updated at',
      formatOptions: {
        dateStyle: 'full',
        timeStyle: 'medium'
      }
    },

    // Search
    search: {
      provider: 'local'
    }
  }
}

Custom Components

Global Components

<!-- docs/.vitepress/components/Badge.vue -->
<template>
  <span class="badge" :class="type">
    <slot />
  </span>
</template>

<script setup>
defineProps({
  type: {
    type: String,
    default: 'info'
  }
})
</script>

<style scoped>
.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
}

.badge.info {
  background: #e1f5fe;
  color: #01579b;
}

.badge.warning {
  background: #fff3e0;
  color: #e65100;
}
</style>

Register Components

// docs/.vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import Badge from '../components/Badge.vue'
import CodeGroup from '../components/CodeGroup.vue'

export default {
  extends: DefaultTheme,
  enhanceApp({ app }) {
    app.component('Badge', Badge)
    app.component('CodeGroup', CodeGroup)
  }
}

Use in Markdown

# API Reference

## Methods

### getData() <Badge type="info">v1.0+</Badge>

Fetches data from the API.

<CodeGroup>
  <CodeGroupItem title="JavaScript">

  ```javascript
  const data = await api.getData()
  ```

  </CodeGroupItem>
  <CodeGroupItem title="TypeScript">

  ```typescript
  const data: ApiResponse = await api.getData()
  ```

  </CodeGroupItem>
</CodeGroup>

Interactive Components

<!-- docs/.vitepress/components/Counter.vue -->
<template>
  <div class="counter">
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button @click="count++">+</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<style scoped>
.counter {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  border: 1px solid var(--vp-c-border);
  border-radius: 8px;
}

button {
  padding: 0.5rem 1rem;
  border: none;
  background: var(--vp-c-brand-1);
  color: white;
  border-radius: 4px;
  cursor: pointer;
}
</style>

Basic Navigation

// docs/.vitepress/config.js
export default {
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' },
      { text: 'API', link: '/api/' },
      { text: 'Changelog', link: '/changelog' }
    ]
  }
}
export default {
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      {
        text: 'Guide',
        items: [
          { text: 'Getting Started', link: '/guide/' },
          { text: 'Configuration', link: '/guide/configuration' },
          { text: 'Deployment', link: '/guide/deployment' }
        ]
      },
      {
        text: 'Reference',
        items: [
          {
            text: 'API',
            items: [
              { text: 'Runtime API', link: '/api/runtime' },
              { text: 'Build API', link: '/api/build' }
            ]
          },
          {
            text: 'Config',
            items: [
              { text: 'Site Config', link: '/config/site' },
              { text: 'Theme Config', link: '/config/theme' }
            ]
          }
        ]
      }
    ]
  }
}
export default {
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'GitHub', link: 'https://github.com/user/repo' },
      { 
        text: 'Resources',
        items: [
          { text: 'Documentation', link: '/docs/' },
          { text: 'GitHub', link: 'https://github.com/user/repo' },
          { text: 'Discord', link: 'https://discord.gg/invite' }
        ]
      }
    ]
  }
}
export default {
  themeConfig: {
    nav: [
      { 
        text: 'Guide', 
        link: '/guide/',
        activeMatch: '/guide/' // Matches /guide/* paths
      },
      { 
        text: 'API', 
        link: '/api/',
        activeMatch: '^/api/' // Regex pattern
      }
    ]
  }
}

Basic Sidebar

// docs/.vitepress/config.js
export default {
  themeConfig: {
    sidebar: [
      {
        text: 'Getting Started',
        items: [
          { text: 'Introduction', link: '/guide/' },
          { text: 'Installation', link: '/guide/installation' },
          { text: 'Quick Start', link: '/guide/quick-start' }
        ]
      },
      {
        text: 'Advanced',
        items: [
          { text: 'Configuration', link: '/guide/configuration' },
          { text: 'Theming', link: '/guide/theming' },
          { text: 'Deployment', link: '/guide/deployment' }
        ]
      }
    ]
  }
}

Multiple Sidebars

export default {
  themeConfig: {
    sidebar: {
      '/guide/': [
        {
          text: 'Guide',
          items: [
            { text: 'Introduction', link: '/guide/' },
            { text: 'Getting Started', link: '/guide/getting-started' }
          ]
        }
      ],
      '/api/': [
        {
          text: 'API Reference',
          items: [
            { text: 'Overview', link: '/api/' },
            { text: 'Methods', link: '/api/methods' }
          ]
        }
      ]
    }
  }
}

Collapsible Sidebar

export default {
  themeConfig: {
    sidebar: [
      {
        text: 'Getting Started',
        collapsed: false, // Expanded by default
        items: [
          { text: 'Introduction', link: '/guide/' },
          { text: 'Installation', link: '/guide/installation' }
        ]
      },
      {
        text: 'Advanced Topics',
        collapsed: true, // Collapsed by default
        items: [
          { text: 'Custom Themes', link: '/advanced/themes' },
          { text: 'Plugins', link: '/advanced/plugins' }
        ]
      }
    ]
  }
}

Auto-generated Sidebar

// docs/.vitepress/config.js
import { generateSidebar } from './utils/sidebar'

export default {
  themeConfig: {
    sidebar: generateSidebar('docs')
  }
}

// utils/sidebar.js
import fs from 'fs'
import path from 'path'

export function generateSidebar(dir) {
  const files = fs.readdirSync(dir)
  return files
    .filter(file => file.endsWith('.md'))
    .map(file => ({
      text: file.replace('.md', ''),
      link: `/${file.replace('.md', '')}`
    }))
}
// docs/.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'
            }
          }
        }
      }
    }
  }
}
export default {
  themeConfig: {
    search: {
      provider: 'algolia',
      options: {
        appId: 'YOUR_APP_ID',
        apiKey: 'YOUR_API_KEY',
        indexName: 'YOUR_INDEX_NAME',
        placeholder: 'Search docs',
        translations: {
          button: {
            buttonText: 'Search',
            buttonAriaLabel: 'Search'
          }
        }
      }
    }
  }
}
<!-- docs/.vitepress/theme/components/CustomSearch.vue -->
<template>
  <div class="search">
    <input 
      v-model="query" 
      placeholder="Search..."
      @input="search"
    />
    <div v-if="results.length" class="results">
      <div 
        v-for="result in results" 
        :key="result.id"
        class="result"
        @click="navigate(result.path)"
      >
        {{ result.title }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vitepress'

const query = ref('')
const results = ref([])
const router = useRouter()

function search() {
  // Implement search logic
  results.value = performSearch(query.value)
}

function navigate(path) {
  router.go(path)
}
</script>

Internationalization

Multi-language Configuration

// docs/.vitepress/config.js
export default {
  locales: {
    root: {
      label: 'English',
      lang: 'en',
      title: 'VitePress',
      description: 'Vite & Vue powered static site generator'
    },
    zh: {
      label: '简体中文',
      lang: 'zh-CN',
      title: 'VitePress',
      description: 'Vite & Vue 驱动的静态站点生成器',
      themeConfig: {
        nav: [
          { text: '首页', link: '/zh/' },
          { text: '指南', link: '/zh/guide/' }
        ],
        sidebar: {
          '/zh/guide/': [
            {
              text: '指南',
              items: [
                { text: '介绍', link: '/zh/guide/' },
                { text: '快速开始', link: '/zh/guide/getting-started' }
              ]
            }
          ]
        }
      }
    }
  },

  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' }
    ],
    sidebar: {
      '/guide/': [
        {
          text: 'Guide',
          items: [
            { text: 'Introduction', link: '/guide/' },
            { text: 'Getting Started', link: '/guide/getting-started' }
          ]
        }
      ]
    }
  }
}

Directory Structure for i18n

docs/
├── .vitepress/
   └── config.js
├── index.md              # English homepage
├── guide/
   ├── index.md
   └── getting-started.md
└── zh/
    ├── index.md          # Chinese homepage
    └── guide/
        ├── index.md
        └── getting-started.md

Language Switching

<!-- Custom language switcher -->
<template>
  <select @change="switchLanguage">
    <option value="/">English</option>
    <option value="/zh/">简体中文</option>
  </select>
</template>

<script setup>
import { useRouter } from 'vitepress'

const router = useRouter()

function switchLanguage(event) {
  const locale = event.target.value
  router.go(locale)
}
</script>

Deployment

Static Hosting

# Build for production
npm run docs:build

# Output directory: docs/.vitepress/dist
# Deploy this directory to your hosting provider

GitHub Pages

# .github/workflows/deploy.yml
name: Deploy VitePress site to Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: npm

      - name: Setup Pages
        uses: actions/configure-pages@v3

      - name: Install dependencies
        run: npm ci

      - name: Build with VitePress
        run: npm run docs:build

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          path: docs/.vitepress/dist

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2

Netlify

# netlify.toml
[build]
  command = "npm run docs:build"
  publish = "docs/.vitepress/dist"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Vercel

{
  "buildCommand": "npm run docs:build",
  "outputDirectory": "docs/.vitepress/dist"
}

Custom Domain

// docs/.vitepress/config.js
export default {
  base: '/my-project/', // For GitHub Pages subdirectory
  // base: '/', // For custom domain

  head: [
    ['link', { rel: 'canonical', href: 'https://mydomain.com' }]
  ]
}

API Reference

Site Data

<template>
  <div>
    <h1>{{ site.title }}</h1>
    <p>{{ site.description }}</p>
    <p>Base URL: {{ site.base }}</p>
  </div>
</template>

<script setup>
import { useData } from 'vitepress'

const { site } = useData()
</script>

Page Data

<template>
  <div>
    <h1>{{ page.title }}</h1>
    <p>Last updated: {{ page.lastUpdated }}</p>
    <p>Edit link: {{ page.editLink }}</p>
  </div>
</template>

<script setup>
import { useData } from 'vitepress'

const { page } = useData()
</script>

Theme Data

<template>
  <nav>
    <a 
      v-for="item in theme.nav" 
      :key="item.text"
      :href="item.link"
    >
      {{ item.text }}
    </a>
  </nav>
</template>

<script setup>
import { useData } from 'vitepress'

const { theme } = useData()
</script>

Router

<template>
  <div>
    <p>Current route: {{ route.path }}</p>
    <button @click="navigate">Go to Guide</button>
  </div>
</template>

<script setup>
import { useRouter, useRoute } from 'vitepress'

const router = useRouter()
const route = useRoute()

function navigate() {
  router.go('/guide/')
}
</script>

Plugins

Markdown Plugins

// docs/.vitepress/config.js
export default {
  markdown: {
    config: (md) => {
      // Add markdown-it plugins
      md.use(require('markdown-it-footnote'))
      md.use(require('markdown-it-deflist'))
      md.use(require('markdown-it-abbr'))
      md.use(require('markdown-it-emoji'))
      md.use(require('markdown-it-container'), 'custom')
    }
  }
}

Vite Plugins

// docs/.vitepress/config.js
import { defineConfig } from 'vitepress'

export default defineConfig({
  vite: {
    plugins: [
      // Add Vite plugins
      {
        name: 'custom-plugin',
        configResolved(config) {
          // Plugin logic
        }
      }
    ]
  }
})

Custom Plugin Example

// plugins/reading-time.js
export function readingTimePlugin(md) {
  md.core.ruler.push('reading-time', (state) => {
    const content = state.src
    const wordsPerMinute = 200
    const words = content.split(/\s+/).length
    const readingTime = Math.ceil(words / wordsPerMinute)

    // Add to env for use in templates
    state.env.readingTime = readingTime
  })
}

// docs/.vitepress/config.js
import { readingTimePlugin } from './plugins/reading-time.js'

export default {
  markdown: {
    config: (md) => {
      md.use(readingTimePlugin)
    }
  }
}

Advanced Configuration

Build Optimization

// docs/.vitepress/config.js
export default {
  vite: {
    build: {
      minify: 'terser',
      rollupOptions: {
        output: {
          manualChunks: {
            vue: ['vue'],
            vendor: ['lodash', 'axios']
          }
        }
      }
    }
  }
}

Custom Head Tags

export default {
  head: [
    ['meta', { name: 'author', content: 'Your Name' }],
    ['meta', { name: 'keywords', content: 'vitepress, vue, documentation' }],
    ['link', { rel: 'icon', href: '/favicon.ico' }],
    ['link', { rel: 'manifest', href: '/manifest.json' }],
    ['script', { src: 'https://analytics.example.com/script.js' }]
  ]
}

Environment Variables

// docs/.vitepress/config.js
export default {
  define: {
    __VERSION__: JSON.stringify(process.env.npm_package_version),
    __BUILD_TIME__: JSON.stringify(new Date().toISOString())
  }
}

Build Hooks

export default {
  buildStart() {
    console.log('Build started')
  },

  buildEnd(siteConfig) {
    console.log('Build completed')
    // Generate sitemap, RSS feed, etc.
  },

  postRender(context) {
    // Post-render processing
  }
}

Performance

Bundle Analysis

# Install bundle analyzer
npm install --save-dev rollup-plugin-analyzer

# Add to vite config
# docs/.vitepress/config.js
export default {
  vite: {
    build: {
      rollupOptions: {
        plugins: [
          require('rollup-plugin-analyzer')()
        ]
      }
    }
  }
}

Lazy Loading

<!-- Lazy load components -->
<template>
  <div>
    <Suspense>
      <template #default>
        <HeavyComponent />
      </template>
      <template #fallback>
        <div>Loading...</div>
      </template>
    </Suspense>
  </div>
</template>

<script setup>
import { defineAsyncComponent } from 'vue'

const HeavyComponent = defineAsyncComponent(() => 
  import('./HeavyComponent.vue')
)
</script>

Image Optimization

<!-- Use responsive images -->
![Hero Image](./hero.jpg)

<!-- Or with HTML for more control -->
<picture>
  <source srcset="./hero.webp" type="image/webp">
  <source srcset="./hero.jpg" type="image/jpeg">
  <img src="./hero.jpg" alt="Hero Image" loading="lazy">
</picture>

Caching Strategy

// docs/.vitepress/config.js
export default {
  vite: {
    build: {
      rollupOptions: {
        output: {
          entryFileNames: 'assets/[name].[hash].js',
          chunkFileNames: 'assets/[name].[hash].js',
          assetFileNames: 'assets/[name].[hash].[ext]'
        }
      }
    }
  }
}

Best Practices

Content Organization

# Recommended structure
docs/
├── .vitepress/
├── guide/
   ├── index.md          # Overview
   ├── getting-started.md
   ├── configuration.md
   └── advanced.md
├── api/
   ├── index.md
   ├── methods.md
   └── types.md
├── examples/
├── changelog.md
└── index.md

SEO Optimization

// docs/.vitepress/config.js
export default {
  head: [
    ['meta', { name: 'description', content: 'Your site description' }],
    ['meta', { property: 'og:title', content: 'Your Site Title' }],
    ['meta', { property: 'og:description', content: 'Your site description' }],
    ['meta', { property: 'og:image', content: '/og-image.jpg' }],
    ['meta', { name: 'twitter:card', content: 'summary_large_image' }],
    ['link', { rel: 'canonical', href: 'https://yoursite.com' }]
  ],

  // Generate sitemap
  sitemap: {
    hostname: 'https://yoursite.com'
  }
}

Performance Best Practices

  • Optimize images with appropriate formats and sizes
  • Use lazy loading for heavy components
  • Minimize bundle size with tree shaking
  • Enable caching with proper headers
  • Use CDN for static assets

Content Best Practices

  • Write clear headings for better navigation
  • Use consistent formatting across pages
  • Include code examples with proper syntax highlighting
  • Add search functionality for better discoverability
  • Maintain consistent navigation structure

Summary

VitePress is a powerful static site generator that combines the speed of Vite with the flexibility of Vue.js. Key features include:

  • Fast Development: Lightning-fast HMR powered by Vite
  • Vue-Powered: Full Vue.js support for interactive components
  • Markdown-Centered: Focus on content with enhanced Markdown features
  • Customizable: Flexible theming and component system
  • SEO-Friendly: Static site generation with proper meta tags
  • TypeScript Support: First-class TypeScript integration
  • Internationalization: Built-in multi-language support

By leveraging VitePress's capabilities and following best practices, you can create fast, beautiful, and maintainable documentation sites that provide an excellent user experience.