Generated banner for Vitepress
Generated logo for Vitepress

Vitepress

Anthony FuCommunityCreated by Anthony Fu

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

VitePress static site generator powered by Vite and Vue. Use when building documentation sites, configuring themes, or writing Markdown with Vue components.
— the description by Anthony Fu

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

VitePress is a static site generator that transforms Markdown content into a single-page application. It leverages Vite for build processes and Vue 3 for component-based content, allowing developers to integrate Vue components directly into Markdown files. The tool supports file-based routing, theme customization, and provides built-in features for search, internationalization, and server-side rendering compatibility.

What it does

  • Generates static HTML from Markdown files
  • Enables the use of Vue components within Markdown
  • Supports file-based routing and site configuration
  • Provides tools for internationalization and multi-language sites
  • Offers mechanisms for SSR-compatible code and browser-only component handling
  • Includes built-in search and theme customization options

When to use it

  • When building documentation sites or technical guides
  • When creating blogs or marketing sites using Markdown
  • When you need to embed interactive Vue components in static content
  • When you require a site with multi-language support

Advantages

  • Direct integration of Vue components in Markdown
  • File-based routing simplifies site structure
  • Built-in support for internationalization and RTL layouts
  • Tools for managing browser-only code in an SSR environment

Usage examples

“How do I configure multiple languages in VitePress?”
You can define a locales object in your .vitepress/config.ts file to map language codes to specific site configurations and directory structures.
“How can I use a component that requires the window object?”
You should wrap the component in a ClientOnly tag or use defineClientComponent to ensure it only loads on the client side, avoiding SSR errors.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/antfu/vitepress/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip vitepress.zip -d .agents/skills

Documentation by Anthony Fu

VitePress is a Static Site Generator (SSG) built on Vite and Vue 3. It takes Markdown content, applies a theme, and generates static HTML that becomes an SPA for fast navigation. Perfect for documentation, blogs, and marketing sites.

Key Characteristics:

  • File-based routing with .md files

  • Vue components work directly in Markdown

  • Fast HMR with instant updates (<100ms)

  • Default theme optimized for documentation

  • Built-in search (local or Algolia)

Before working with VitePress projects:

  • Check .vitepress/config.ts for site configuration

  • Look at .vitepress/theme/ for custom theme extensions

  • The public/ directory contains static assets served as-is

The skill is based on VitePress 2.0.0-alpha.20, generated at 2026-09-25.

VitePress 2 notes (v1 → v2): install with vitepress@next; requires Node.js 22+. defineConfigWithTheme is deprecated — use defineConfig<ThemeConfig>. Native RTL support (dir option, CSS logical properties) replaces the old PostCSS-plugin approach. Built-in iconify pipeline (icons config, useIcon/VPIcon, collection:name social icons). New assetsBase (CDN) and assetsShards build options; metaChunk removed. Markdown image.lazyLoading renamed to image.lazyLoad.

Core

TopicDescriptionReference
ConfigurationConfig file setup, defineConfig, site metadatacore-config
CLICommand-line interface: dev, build, preview, initcore-cli
RoutingFile-based routing, source directory, rewritescore-routing
MarkdownFrontmatter, containers, tables, anchors, includescore-markdown

Features

Code & Content
TopicDescriptionReference
Code BlocksSyntax highlighting, line highlighting, diffs, focusfeatures-code-blocks
Vue in MarkdownComponents, script setup, directives, templatingfeatures-vue
Data LoadingBuild-time data loaders, createContentLoaderfeatures-data-loading
Dynamic RoutesGenerate pages from data, paths loader filesfeatures-dynamic-routes

Theme

TopicDescriptionReference
Theme ConfigNav, sidebar, search, social links, footertheme-config
CustomizationCSS variables, slots, fonts, global componentstheme-customization
Custom ThemeBuilding themes from scratch, theme interfacetheme-custom

Advanced

TopicDescriptionReference
InternationalizationMulti-language sites, locale configurationadvanced-i18n
SSR CompatibilityServer-side rendering, ClientOnly, dynamic importsadvanced-ssr

Recipes

TopicDescriptionReference
DeploymentGitHub Pages, Netlify, Vercel, Cloudflare, Nginxrecipes-deploy

Files

references/features-dynamic-routes.md


name: vitepress-dynamic-routes description: Generate multiple pages from a single markdown template using paths loader files

Dynamic Routes

Generate many pages from a single markdown file and dynamic data. Useful for blogs, package docs, or any data-driven pages.

Basic Setup

Create a template file with parameter in brackets and a paths loader:

.
└─ packages/
   ├─ [pkg].md           # Route template
   └─ [pkg].paths.js     # Paths loader

The paths loader exports a paths method returning route parameters:

// packages/[pkg].paths.js
export default {
  paths() {
    return [
      { params: { pkg: 'foo' }},
      { params: { pkg: 'bar' }},
      { params: { pkg: 'baz' }}
    ]
  }
}

Generated pages:

  • /packages/foo.html

  • /packages/bar.html

  • /packages/baz.html

Type-safe Loader with defineRoutes (v2)

In TypeScript, wrap the loader with defineRoutes for type hints on paths, watch, and transformPageData:

// packages/[pkg].paths.ts
import { defineRoutes } from 'vitepress'

export default defineRoutes({
  watch: ['../data/**/*.json'],
  async paths() {
    return [{ params: { pkg: 'foo' } }, { params: { pkg: 'bar' } }]
  },
  async transformPageData(pageData) {
    pageData.title = `${pageData.title} · Packages`
  }
})

defineRoutes is optional but recommended when authoring .paths.ts files.

Multiple Parameters

.
└─ packages/
   ├─ [pkg]-[version].md
   └─ [pkg]-[version].paths.js
// packages/[pkg]-[version].paths.js
export default {
  paths() {
    return [
      { params: { pkg: 'foo', version: '1.0.0' }},
      { params: { pkg: 'foo', version: '2.0.0' }},
      { params: { pkg: 'bar', version: '1.0.0' }}
    ]
  }
}

Dynamic Path Generation

From local files:

// packages/[pkg].paths.js
import fs from 'node:fs'

export default {
  paths() {
    return fs.readdirSync('packages').map(pkg => ({
      params: { pkg }
    }))
  }
}

From remote API:

// packages/[pkg].paths.js
export default {
  async paths() {
    const packages = await fetch('https://api.example.com/packages').then(r => r.json())
    
    return packages.map(pkg => ({
      params: {
        pkg: pkg.name,
        version: pkg.version
      }
    }))
  }
}

Accessing Params in Page

Template globals:

<!-- packages/[pkg].md -->
# Package: {{ $params.pkg }}

Version: {{ $params.version }}

In script:

<script setup>
import { useData } from 'vitepress'
const { params } = useData()
</script>

<template>
  <h1>{{ params.pkg }}</h1>
</template>

Passing Content

For heavy content (raw markdown/HTML from CMS), use content instead of params to avoid bloating the client bundle:

// posts/[slug].paths.js
export default {
  async paths() {
    const posts = await fetch('https://cms.example.com/posts').then(r => r.json())
    
    return posts.map(post => ({
      params: { slug: post.slug },
      content: post.content  // Raw markdown or HTML
    }))
  }
}

Render content in template:

<!-- posts/[slug].md -->
---
title: {{ $params.title }}
---

<!-- @content -->

The <!-- @content --> placeholder is replaced with the content from the paths loader.

Watch Option

Auto-rebuild when template or data files change:

// posts/[slug].paths.js
export default {
  watch: [
    './templates/**/*.njk',
    '../data/**/*.json'
  ],
  
  paths(watchedFiles) {
    const dataFiles = watchedFiles.filter(f => f.endsWith('.json'))
    
    return dataFiles.map(file => {
      const data = JSON.parse(fs.readFileSync(file, 'utf-8'))
      return {
        params: { slug: data.slug },
        content: renderTemplate(data)
      }
    })
  }
}

Complete Example: Blog

// posts/[slug].paths.js
import fs from 'node:fs'
import matter from 'gray-matter'

export default {
  watch: ['./posts/*.md'],
  
  paths(files) {
    return files
      .filter(f => !f.includes('[slug]'))
      .map(file => {
        const content = fs.readFileSync(file, 'utf-8')
        const { data, content: body } = matter(content)
        const slug = file.match(/([^/]+)\.md$/)[1]
        
        return {
          params: { 
            slug,
            title: data.title,
            date: data.date
          },
          content: body
        }
      })
  }
}
<!-- posts/[slug].md -->
---
layout: doc
---

# {{ $params.title }}

<time>{{ $params.date }}</time>

<!-- @content -->

Key Points

  • Template file uses [param] syntax in filename

  • Paths loader file must be named [param].paths.js or .ts

  • paths() returns array of { params: {...}, content?: string }

  • Use $params in templates or useData().params in scripts

  • Use content for heavy data to avoid client bundle bloat

  • watch enables HMR for template/data file changes

  • v2: wrap .paths.ts loaders with defineRoutes for type hints

<!-- Source references: - https://vitepress.dev/guide/routing#dynamic-routes -->

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Anthony Fu
Publisher
Anthony Fu (Community)
Source
antfu/skills · skills/vitepress · commit f63e9ec
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE.md)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Anthony Fu.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download vitepress.zip