VuePress

GitHub Overview

vuejs/vuepress

📝 Minimalistic Vue-powered static site generator

Stars22,801
Watchers261
Forks4,727
Created:April 5, 2018
Language:JavaScript
License:MIT License

Topics

blog-enginedocs-generatorseostatic-site-generatorvuevuepress

Star History

vuejs/vuepress Star History
Data as of: 8/13/2025, 01:43 AM

Documentation Tool

VuePress

Overview

VuePress is a static site generator based on Vue.js. It combines Markdown-based content creation with the power of Vue.js to build fast and beautiful documentation sites.

Details

VuePress was developed by Evan You (creator of Vue.js) in 2018 and was born as the official documentation tool for the Vue.js ecosystem. While based on Markdown files, it can leverage the powerful features of Vue.js components. It achieves fast display speeds through static site generation (SSG) while providing rich user experiences as a Single Page Application (SPA). The plugin system allows you to add diverse functionality such as search, PWA support, blog features, and multi-language support. The theme system allows you to either use the beautiful default theme or create completely custom themes. It's closely integrated with the Vue.js ecosystem, allowing direct use of Vue components within Markdown. As of 2025, it's adopted as the official documentation tool for many Vue.js projects including Vue.js, Element Plus, and Ant Design Vue. VuePress 2 significantly improves the development experience with Vite integration, providing much faster builds and development servers. It comes standard with modern documentation site features including version control, multi-language site building, and SEO optimization. VuePress 2 offers better TypeScript support, improved plugin architecture, and enhanced theme development capabilities.

Advantages and Disadvantages

Advantages

  • Vue.js Integration: Seamless combination of Markdown and Vue components
  • Fast Display: Excellent performance and SEO through static site generation
  • SPA Experience: Rich user experience and navigation during page transitions
  • Rich Plugins: Official plugins for search, PWA, blog, and multi-language support
  • Beautiful Default Theme: Clean and sophisticated design ready to use
  • Vue.js Ecosystem: Integration with existing Vue component libraries
  • Developer Experience: Fast development server and hot reload with Vite integration

Disadvantages

  • Vue.js Dependency: Requires Vue.js knowledge, learning curve exists
  • Node.js Environment: Node.js environment required for development and building
  • Build Time: Increased build time for large-scale sites
  • Plugin Limitations: Limited plugin choices outside the Vue.js ecosystem
  • Customization Complexity: Advanced customization requires understanding of Vue.js and Webpack/Vite
  • Memory Usage: High memory consumption during development for large sites

Key Links

Usage Examples

Project Initialization

# Create VuePress project
yarn create vuepress-site my-docs
# or
npx create-vuepress-site my-docs

# Project structure
my-docs/
├── docs/                 # Documentation directory
│   ├── .vuepress/       # VuePress configuration directory
│   │   ├── config.js    # Site configuration file
│   │   ├── components/  # Custom Vue components
│   │   ├── theme/      # Custom theme
│   │   └── public/     # Static assets
│   ├── guide/          # Guide section
│   └── README.md       # Home page
└── package.json

Basic Configuration File (config.js)

// docs/.vuepress/config.js
module.exports = {
  // Basic site information
  title: 'Project Documentation',
  description: 'Vue.js-based documentation site',
  base: '/',
  lang: 'en-US',

  // Head configuration
  head: [
    ['link', { rel: 'icon', href: '/favicon.ico' }],
    ['meta', { name: 'theme-color', content: '#3eaf7c' }],
    ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
    ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }]
  ],

  // Theme configuration
  themeConfig: {
    // Navigation bar
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' },
      { text: 'API', link: '/api/' },
      { text: 'GitHub', link: 'https://github.com/username/project' }
    ],

    // Sidebar
    sidebar: {
      '/guide/': [
        '',
        'getting-started',
        'installation',
        'configuration',
        'deployment'
      ],
      '/api/': [
        '',
        'components',
        'directives',
        'utilities'
      ]
    },

    // Git repository configuration
    repo: 'username/project',
    repoLabel: 'GitHub',
    docsDir: 'docs',
    docsBranch: 'main',
    editLinks: true,
    editLinkText: 'Edit this page',

    // Last updated timestamp
    lastUpdated: 'Last Updated',

    // Search configuration
    search: true,
    searchMaxSuggestions: 10,

    // Algolia DocSearch configuration
    algolia: {
      apiKey: 'your-api-key',
      indexName: 'your-index-name'
    }
  },

  // Plugin configuration
  plugins: [
    '@vuepress/back-to-top',
    '@vuepress/medium-zoom',
    ['@vuepress/pwa', {
      serviceWorker: true,
      updatePopup: {
        message: "New content is available.",
        buttonText: "Update"
      }
    }],
    ['@vuepress/google-analytics', {
      'ga': 'UA-XXXXXXXXX-X'
    }]
  ],

  // Markdown configuration
  markdown: {
    lineNumbers: true,
    anchor: { permalink: true },
    toc: { includeLevel: [1, 2, 3] },
    plugins: [
      'markdown-it-container',
      'markdown-it-footnote',
      'markdown-it-deflist'
    ]
  },

  // Build configuration
  evergreen: true,
  dest: 'dist',
  
  // Multi-language configuration
  locales: {
    '/': {
      lang: 'en-US',
      title: 'Project Documentation',
      description: 'Vue.js-powered documentation site'
    },
    '/ja/': {
      lang: 'ja-JP',
      title: 'プロジェクトドキュメント',
      description: 'Vue.jsベースのドキュメントサイト'
    }
  }
}

Markdown and Vue.js Component Integration

# VuePress Usage Guide

## Basic Markdown

VuePress extends Markdown to provide various features.

### Custom Containers
::: tip Tip
This is a helpful tip.
:::

::: warning Warning
This requires attention.
:::

::: danger Danger
This is a warning about dangerous operations.
:::

::: details Click to see details
Detailed explanation appears here.
:::

### Code Blocks
```javascript{2-4}
function example() {
  // These lines will be highlighted
  const message = 'Hello VuePress!'
  console.log(message)
  return message
}

Using Vue.js Components

<CustomComponent :prop="value" @event="handler">

Dynamic Content

Current time: {{ new Date().toLocaleString() }}

Counter: {{ counter }} <button @click="increment">Click


### Creating Custom Vue Components
```vue
<!-- docs/.vuepress/components/FeatureCard.vue -->
<template>
  <div class="feature-card">
    <div class="feature-icon">
      <slot name="icon"></slot>
    </div>
    <h3 class="feature-title">{{ title }}</h3>
    <p class="feature-description">{{ description }}</p>
    <div class="feature-actions">
      <slot name="actions"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: 'FeatureCard',
  props: {
    title: {
      type: String,
      required: true
    },
    description: {
      type: String,
      required: true
    }
  }
}
</script>

<style scoped>
.feature-card {
  border: 1px solid #e0e6ed;
  border-radius: 8px;
  padding: 24px;
  margin: 16px 0;
  background: #ffffff;
  transition: box-shadow 0.3s ease;
}

.feature-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.feature-icon {
  font-size: 2em;
  margin-bottom: 16px;
  color: #3eaf7c;
}

.feature-title {
  margin: 0 0 12px 0;
  font-size: 1.4em;
  color: #2c3e50;
}

.feature-description {
  margin: 0 0 16px 0;
  color: #5e6d82;
  line-height: 1.6;
}

.feature-actions {
  display: flex;
  gap: 12px;
}
</style>

Plugin Development Example

// plugins/custom-plugin.js
module.exports = (options = {}, context) => ({
  name: 'custom-plugin',
  
  // Plugin configuration
  async ready() {
    // Plugin initialization process
    console.log('Custom plugin is ready!')
  },

  // Markdown extension
  extendMarkdown(md) {
    md.use(require('markdown-it-container'), 'custom', {
      validate: function(params) {
        return params.trim().match(/^custom\s+(.*)$/)
      },
      render: function(tokens, idx) {
        const m = tokens[idx].info.trim().match(/^custom\s+(.*)$/)
        if (tokens[idx].nesting === 1) {
          return `<div class="custom-container">
                    <div class="custom-title">${m[1]}</div>
                    <div class="custom-content">`
        } else {
          return '</div></div>'
        }
      }
    })
  },

  // Page extension
  async additionalPages() {
    return [
      {
        path: '/custom-page/',
        frontmatter: {
          title: 'Custom Page',
          layout: 'CustomLayout'
        }
      }
    ]
  },

  // Client-side extension
  enhanceAppFiles: [
    path.resolve(__dirname, 'enhanceApp.js')
  ],

  // Build-time processing
  async generated(pagePaths) {
    // Post-processing of generated pages
    console.log('Generated pages:', pagePaths.length)
  }
})

Theme Customization

// docs/.vuepress/theme/index.js
const path = require('path')

module.exports = {
  // Inherit parent theme
  extend: '@vuepress/theme-default',
  
  // Layout overrides
  layouts: {
    Layout: path.resolve(__dirname, 'layouts/Layout.vue'),
    404: path.resolve(__dirname, 'layouts/404.vue')
  },

  // Global components
  globalLayout: path.resolve(__dirname, 'layouts/GlobalLayout.vue'),

  // Plugin additions
  plugins: [
    '@vuepress/back-to-top',
    '@vuepress/nprogress',
    ['@vuepress/search', {
      searchMaxSuggestions: 10
    }]
  ]
}

Custom Layout Component

<!-- docs/.vuepress/theme/layouts/Layout.vue -->
<template>
  <div class="custom-layout">
    <!-- Header -->
    <header class="custom-header">
      <nav class="custom-nav">
        <router-link to="/" class="custom-logo">
          <img src="/logo.png" alt="Logo">
        </router-link>
        <ul class="custom-nav-links">
          <li v-for="item in $themeConfig.nav" :key="item.text">
            <NavLink :item="item"/>
          </li>
        </ul>
      </nav>
    </header>

    <!-- Main content -->
    <main class="custom-main">
      <aside class="custom-sidebar" v-if="shouldShowSidebar">
        <Sidebar :items="sidebarItems"/>
      </aside>
      
      <div class="custom-content">
        <div class="content-wrapper">
          <!-- Page content -->
          <Content/>
          
          <!-- Page navigation -->
          <PageNav v-bind="{ sidebarItems }"/>
          
          <!-- Edit link -->
          <PageEdit/>
        </div>
      </div>
    </main>

    <!-- Footer -->
    <footer class="custom-footer">
      <p>&copy; {{ new Date().getFullYear() }} Project Name</p>
    </footer>
  </div>
</template>

<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems } from '@theme/util'

export default {
  name: 'Layout',
  components: {
    Home,
    Page,
    Sidebar,
    Navbar
  },
  computed: {
    shouldShowSidebar() {
      const { frontmatter } = this.$page
      return !frontmatter.home && 
             frontmatter.sidebar !== false && 
             this.sidebarItems.length
    },
    sidebarItems() {
      return resolveSidebarItems(
        this.$page,
        this.$page.regularPath,
        this.$site,
        this.$localePath
      )
    }
  }
}
</script>

<style lang="stylus">
.custom-layout
  min-height 100vh
  display flex
  flex-direction column

.custom-header
  background #ffffff
  border-bottom 1px solid #eaecef
  position sticky
  top 0
  z-index 20

.custom-nav
  max-width 1200px
  margin 0 auto
  padding 0 2rem
  display flex
  align-items center
  justify-content space-between
  height 3.5rem

.custom-logo img
  height 2rem

.custom-nav-links
  display flex
  list-style none
  margin 0
  padding 0
  gap 2rem

.custom-main
  flex 1
  display flex
  max-width 1200px
  margin 0 auto
  width 100%

.custom-sidebar
  width 20rem
  flex-shrink 0

.custom-content
  flex 1
  min-width 0

.content-wrapper
  padding 2rem
  max-width 740px

.custom-footer
  background #f8f9fa
  text-align center
  padding 2rem
  border-top 1px solid #eaecef
</style>

Build and Auto-deploy Configuration

# .github/workflows/deploy.yml
name: Build and Deploy VuePress

on:
  push:
    branches: [ main ]

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

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 18
          cache: yarn

      - name: Install dependencies
        run: yarn install --frozen-lockfile

      - name: Build VuePress
        run: yarn docs:build

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: docs/.vuepress/dist
          cname: docs.example.com

Advanced Features and Workflow

// docs/.vuepress/enhanceApp.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

export default ({
  Vue, // Vue constructor used by VuePress app
  options, // Root instance options
  router, // Current app router instance
  siteData // Site metadata
}) => {
  // Register Element UI globally
  Vue.use(ElementUI)
  
  // Register global components
  Vue.component('demo-component', {
    template: '<div class="demo">{{ message }}</div>',
    data() {
      return {
        message: 'Hello from global component!'
      }
    }
  })

  // Add global mixin
  Vue.mixin({
    computed: {
      $title() {
        return this.$page.title || this.$site.title
      }
    }
  })

  // Add router guards
  router.beforeEach((to, from, next) => {
    console.log('Navigating to:', to.path)
    next()
  })

  // Hot reload settings for development environment
  if (process.env.NODE_ENV === 'development' && module.hot) {
    module.hot.accept()
  }
}

Development and Build Commands

# Start development server
yarn docs:dev
# or
npm run docs:dev

# Production build
yarn docs:build
# or
npm run docs:build

# Start with specific port
vuepress dev docs --port 8080

# Start in debug mode
DEBUG=vuepress:* vuepress dev docs

# Check plugin details
vuepress info

# Clear cache
rm -rf docs/.vuepress/.cache docs/.vuepress/dist

# Custom theme ejection (not recommended)
vuepress eject docs