# Extending the Default Theme VitePress comes with its default theme providing many features out of the box. You can check out the full features in the [Default Theme Config Overview](/reference/default-theme-config). There are several cases where you may want to extend the default theme: 1. You want to modify the Vue app, for example register global components; 2. You want to tweak the CSS styling; 3. You want to inject custom content into the theme via layout slots. ## Using a Custom Theme You can enable a custom theme by adding the `.vitepress/theme/index.js` or `.vitepress/theme/index.ts` file (the "theme entry file"). ``` . ├─ docs │ ├─ .vitepress │ │ ├─ theme │ │ │ └─ index.js │ │ └─ config.js │ └─ index.md └─ package.json ``` A VitePress custom theme is simply an object containing four properties and is defined as follows: ```ts interface Theme { Layout: Component // Vue 3 component NotFound?: Component enhanceApp?: (ctx: EnhanceAppContext) => Awaitable setup?: () => void } interface EnhanceAppContext { app: App // Vue 3 app instance router: Router // VitePress router instance siteData: Ref } ``` The theme entry file should export the theme as its default export: ```js // .vitepress/theme/index.js import Layout from './Layout.vue' export default { // root component to wrap each page Layout, // this is a Vue 3 functional component NotFound: () => 'custom 404', enhanceApp({ app, router, siteData }) { // app is the Vue 3 app instance from `createApp()`. // router is VitePress' custom router. `siteData` is // a `ref` of current site-level metadata. }, setup() { // this function will be executed inside VitePressApp's // setup hook. all composition APIs are available here. } } ``` ...where the `Layout` component could look like this: ```vue ``` The default export is the only contract for a custom theme. Inside your custom theme, it works just like a normal Vite + Vue 3 application. Do note the theme also needs to be [SSR-compatible](./using-vue#browser-api-access-restrictions). To distribute a theme, simply export the object in your package entry. To consume an external theme, import and re-export it from the custom theme entry: ```js // .vitepress/theme/index.js import Theme from 'awesome-vitepress-theme' export default Theme ``` ## Extending the Default Theme If you want to extend and customize the default theme, you can import it from `vitepress/theme` and augment it in a custom theme entry. Here are some examples of common customizations: ## Registering Global Components ```js // .vitepress/theme/index.js import DefaultTheme from 'vitepress/theme' export default { ...DefaultTheme, enhanceApp(ctx) { // extend default theme custom behaviour. DefaultTheme.enhanceApp(ctx) // register your custom global components ctx.app.component('MyGlobalComponent' /* ... */) } } ``` Since we are using Vite, you can also leverage Vite's [glob import feature](https://vitejs.dev/guide/features.html#glob-import) to auto register a directory of components. ## Customizing CSS The default theme CSS is customizable by overriding root level CSS variables: ```js // .vitepress/theme/index.js import DefaultTheme from 'vitepress/theme' import './custom.css' export default DefaultTheme ``` ```css /* .vitepress/theme/custom.css */ :root { --vp-c-brand: #646cff; --vp-c-brand-light: #747bff; } ``` See [default theme CSS variables](https://github.com/vuejs/vitepress/blob/main/src/clien/reference/default-theme-default/styles/vars.css) that can be overridden. ## Layout Slots The default theme's `` component has a few slots that can be used to inject content at certain locations of the page. Here's an example of injecting a component into the before outline: ```js // .vitepress/theme/index.js import DefaultTheme from 'vitepress/theme' import MyLayout from './MyLayout.vue' export default { ...DefaultTheme, // override the Layout with a wrapper component that // injects the slots Layout: MyLayout } ``` ```vue ``` Or you could use render function as well. ```js // .vitepress/theme/index.js import { h } from 'vue' import DefaultTheme from 'vitepress/theme' import MyComponent from './MyComponent.vue' export default { ...DefaultTheme, Layout() { return h(DefaultTheme.Layout, null, { 'aside-outline-before': () => h(MyComponent) }) } } ``` Full list of slots available in the default theme layout: - When `layout: 'doc'` (default) is enabled via frontmatter: - `doc-footer-before` - `doc-before` - `doc-after` - `sidebar-nav-before` - `sidebar-nav-after` - `aside-top` - `aside-bottom` - `aside-outline-before` - `aside-outline-after` - `aside-ads-before` - `aside-ads-after` - When `layout: 'home'` is enabled via frontmatter: - `home-hero-before` - `home-hero-info` - `home-hero-image` - `home-hero-after` - `home-features-before` - `home-features-after` - Always: - `layout-top` - `layout-bottom` - `nav-bar-title-before` - `nav-bar-title-after` - `nav-bar-content-before` - `nav-bar-content-after` - `nav-screen-content-before` - `nav-screen-content-after`