Custom Themes

Building custom themes from scratch with the theme interface, Layout component, and enhanceApp

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: Extend another theme
  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:

Runtime API

Access VitePress data in your theme:

Built-in Components

Extend Another Theme

Build on top of default theme or any other:

Register Plugins and Components

Async enhanceApp

For plugins that need async initialization:

Theme-Aware Layout

Handle different page layouts:

Distributing a Theme

As npm package:

Consumer usage:

Theme Config Types

For custom theme config types:

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

Last updated

Was this helpful?