Vue in Markdown
VitePress markdown files are compiled as Vue Single-File Components, enabling full Vue functionality.
Interpolation
Vue expressions work in markdown:
{{ 1 + 1 }}
{{ new Date().toLocaleDateString() }}Directives
HTML with Vue directives:
<span v-for="i in 3">{{ i }}</span>
<div v-if="$frontmatter.showBanner">
Banner content
</div>Script and Style
Add <script setup> and <style> after frontmatter:
---
title: My Page
---
<script setup>
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'
const count = ref(0)
</script>
# {{ $frontmatter.title }}
Count: {{ count }}
<button @click="count++">Increment</button>
<MyComponent />
<style module>
.button {
color: red;
}
</style>Note: Use <style module> instead of <style scoped> to avoid bloating page size.
Importing Components
Local import (code-split per page):
<script setup>
import CustomComponent from '../components/CustomComponent.vue'
</script>
<CustomComponent />Global Components
Register in theme for use everywhere:
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme';
import MyGlobalComponent from './MyGlobalComponent.vue';
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('MyGlobalComponent', MyGlobalComponent);
},
};Then use in any markdown:
<MyGlobalComponent />Important: Component names must contain a hyphen or be PascalCase to avoid being treated as inline HTML elements.
Runtime API
Access VitePress data:
<script setup>
import { useData, useRoute, useRouter } from 'vitepress'
const { page, frontmatter, theme, site } = useData()
const route = useRoute()
const router = useRouter()
</script>
Current page: {{ page.relativePath }}Global Variables
Available without import:
# {{ $frontmatter.title }}
Params: {{ $params.id }}Components in Headers
# My Title <Badge type="tip" text="v2.0" />Escaping Vue Syntax
Prevent Vue interpolation:
<span v-pre>{{ will be displayed as-is }}</span>Or use container:
::: v-pre
{{ this won't be processed }}
:::Vue in Code Blocks
Enable Vue processing in fenced code with -vue suffix:
```js-vue
Hello {{ 1 + 1 }}
```CSS Pre-processors
Supported out of the box (install the preprocessor):
npm install -D sass # for .scss/.sass
npm install -D less # for .less
npm install -D stylus # for .styl/.stylus<style lang="scss">
.title {
font-size: 20px;
}
</style>Using Teleports
Teleport to body only with SSG:
<ClientOnly>
<Teleport to="#modal">
<div>Modal content</div>
</Teleport>
</ClientOnly>VS Code IntelliSense
Enable Vue language features for .md files:
// tsconfig.json
{
"include": ["docs/**/*.ts", "docs/**/*.vue", "docs/**/*.md"],
"vueCompilerOptions": {
"vitePressExtensions": [".md"]
}
}// .vscode/settings.json
{
"vue.server.includeLanguages": ["vue", "markdown"]
}Key Points
- Markdown files are Vue SFCs - use
<script setup>and<style> - Access page data via
useData()or$frontmatterglobal - Import components locally or register globally in theme
- Use
<style module>instead of<style scoped> - Wrap non-SSR components in
<ClientOnly> - Component names must be PascalCase or contain hyphens