All skills
antfu avatar

/vitepress

@d02c484 official
by Anthony Fuantfu/skills5.9k stars
335

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

Use this Skill: https://skilld.dev/gh/antfu/skills/vitepress

This session only. Nothing lands on disk.

referencestheme-custom.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Custom Themes

Build a theme from scratch when the default theme doesn't fit your needs.

Theme Entry

Create .vitepress/theme/index.ts:

// .vitepress/theme/index.ts
import Layout from './Layout.vue'

export default {
  Layout,
  enhanceApp({ app, router, siteData }) {
    // Register global components, plugins, etc.
  }
}

Theme Interface

interface Theme {
  // Required: Root layout component
  Layout: Component
  
  // Optional: Enhance Vue app instance
  enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
  
  // Optional (v2): runs inside the root component's setup()
  setup?: () => void
  
  // Optional: Extend another theme (its enhanceApp & setup run first)
  extends?: Theme
}

interface EnhanceAppContext {
  app: App              // Vue app instance
  router: Router        // VitePress router
  siteData: Ref<SiteData>  // Site-level metadata
}

Basic Layout

The Layout component must render <Content /> for markdown:

<!-- .vitepress/theme/Layout.vue -->
<script setup>
import { useData } from 'vitepress'
const { page, frontmatter } = useData()
</script>

<template>
  <div class="layout">
    <header>
      <nav>My Site</nav>
    </header>
    
    <main>
      <div v-if="page.isNotFound">
        <h1>404 - Page Not Found</h1>
      </div>
      
      <div v-else-if="frontmatter.layout === 'home'">
        <h1>Welcome!</h1>
      </div>
      
      <article v-else>
        <Content />
      </article>
    </main>
    
    <footer>
      <p>© 2024 My Site</p>
    </footer>
  </div>
</template>

Runtime API

Access VitePress data in your theme:

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

// Page and site data
const { 
  site,        // Site config (title, description, etc.)
  theme,       // Theme config
  page,        // Current page data
  frontmatter, // Current page frontmatter
  title,       // Page title
  description, // Page description
  lang,        // Current language
  isDark,      // Dark mode state
  params       // Dynamic route params
} = useData()

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

// Navigate programmatically
const goToGuide = () => router.go('/guide/')
</script>

Route Change Hooks (v2)

Assign handlers on the router instance (also available via enhanceApp's router). Return false from onBeforeRouteChange/onBeforePageLoad to cancel:

const router = useRouter()
router.onBeforeRouteChange = (to) => { /* return false to cancel */ }
router.onAfterRouteChange = (to) => console.log('navigated to', to)

Built-in Components

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

<template>
  <!-- Renders markdown content -->
  <Content />
  
  <!-- Renders slot only on client (SSR-safe) -->
  <ClientOnly>
    <NonSSRComponent />
  </ClientOnly>
</template>

Extend Another Theme

Build on top of default theme or any other:

// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'

export default {
  extends: DefaultTheme,
  enhanceApp({ app }) {
    // Your customizations
  }
}

Register Plugins and Components

// .vitepress/theme/index.ts
import Layout from './Layout.vue'
import GlobalComponent from './GlobalComponent.vue'

export default {
  Layout,
  enhanceApp({ app }) {
    // Register global component
    app.component('GlobalComponent', GlobalComponent)
    
    // Register plugin
    app.use(MyPlugin)
    
    // Provide/inject
    app.provide('key', value)
  }
}

Async enhanceApp

For plugins that need async initialization:

export default {
  Layout,
  async enhanceApp({ app }) {
    if (!import.meta.env.SSR) {
      // Client-only plugin
      const plugin = await import('browser-only-plugin')
      app.use(plugin.default)
    }
  }
}

Theme-Aware Layout

Handle different page layouts:

<script setup>
import { useData } from 'vitepress'
import Home from './Home.vue'
import Doc from './Doc.vue'
import Page from './Page.vue'
import NotFound from './NotFound.vue'

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

<template>
  <NotFound v-if="page.isNotFound" />
  <Home v-else-if="frontmatter.layout === 'home'" />
  <Page v-else-if="frontmatter.layout === 'page'" />
  <Doc v-else />
</template>

Distributing a Theme

As npm package:

// my-theme/index.ts
import Layout from './Layout.vue'
export default { Layout }

// Export types for config
export type { ThemeConfig } from './types'

Consumer usage:

// .vitepress/theme/index.ts
import Theme from 'my-vitepress-theme'

export default Theme

// Or extend it
export default {
  extends: Theme,
  enhanceApp({ app }) {
    // Additional customization
  }
}

Theme Config Types

For custom theme config types, pass the type to defineConfig (v2 — defineConfigWithTheme is deprecated):

// .vitepress/config.ts
import { defineConfig } from 'vitepress'
import type { ThemeConfig } from 'my-theme'

export default defineConfig<ThemeConfig>({
  themeConfig: {
    // Type-checked theme config
  }
})

Key Points

  • Theme must export Layout component
  • <Content /> renders the markdown content
  • Use useData() to access page/site data
  • enhanceApp runs on both server and client
  • Check import.meta.env.SSR for client-only code
  • Use extends to build on existing themes
  • v2: theme setup hook runs inside root setup(); router onBeforeRouteChange/onAfterRouteChange for navigation hooks; use defineConfig<ThemeConfig> (not defineConfigWithTheme)
<!-- Source references: - https://vitepress.dev/guide/custom-theme -->

Source: SKILL.md on GitHub

No alerts3d5 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill provides comprehensive documentation and configuration examples for VitePress, a static site generator. No malicious patterns or intent were detected. A minor surface for indirect prompt injection was identified due to the documented features for ingesting external data during the site build process, which is inherent to the framework's functionality.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

  • Runlayer7mo

    2/16 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at d02c484. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 4 days ago
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.9.25",
  "source": "Generated from https://github.com/vuejs/vitepress, scripts located at https://github.com/antfu/skills"
}

README badge

README badge for antfu/skills/vitepress

VitePress is a static site generator built on Vite and Vue 3 that converts Markdown files into a fast single-page application, with file-based routing and built-in support for Vue components directly in Markdown. Use it for documentation sites, blogs, and marketing pages where you need configurable themes, syntax-highlighted code blocks, and instant hot-reload during development.

Generated from the current SKILL.md.

Does VitePress work with Vue components embedded in Markdown?
Yes. Vue components work directly in Markdown files, and you can use script setup and directives within Markdown content.
Can I build a multi-language documentation site with VitePress?
Yes. VitePress includes internationalization support with locale configuration for building multi-language sites.
What search options does VitePress provide?
VitePress includes built-in local search or integration with Algolia for full-text search across documentation.
Can I customize the default theme or build a custom one from scratch?
Yes. You can extend the default theme via CSS variables and slots, or build a completely custom theme by implementing the theme interface.
Does VitePress support dynamic route generation?
Yes. You can generate pages from data at build time using createContentLoader and paths loader files for dynamic routing.

Generated from the current SKILL.md. These answers refresh after source changes.