Files
stack/packages/mosaic/framework/skills/vitepress/references/features-vue.md
T
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00

3.6 KiB

name, description
name description
vue-in-vitepress-markdown Using Vue components, script setup, directives, and templating in markdown files

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 $frontmatter global
  • 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