Files
agent-skills/skills/vitepress/references/features-data-loading.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

221 lines
4.3 KiB
Markdown

---
name: vitepress-data-loading
description: Build-time data loaders for fetching remote data or processing local files
---
# Data Loading
VitePress data loaders run at build time to load arbitrary data that's serialized as JSON in the client bundle.
## Basic Usage
Create a file ending with `.data.js` or `.data.ts`:
```ts
// example.data.ts
export default {
load() {
return {
hello: 'world',
timestamp: Date.now()
}
}
}
```
Import the `data` named export:
```vue
<script setup>
import { data } from './example.data.ts'
</script>
<template>
<pre>{{ data }}</pre>
</template>
```
## Async Data
Fetch remote data:
```ts
// api.data.ts
export default {
async load() {
const response = await fetch('https://api.example.com/data')
return response.json()
}
}
```
## Local Files with Watch
Process local files with hot reload:
```ts
// posts.data.ts
import fs from 'node:fs'
import { parse } from 'csv-parse/sync'
export default {
watch: ['./data/*.csv'],
load(watchedFiles) {
// watchedFiles = array of absolute paths
return watchedFiles.map(file => {
return parse(fs.readFileSync(file, 'utf-8'), {
columns: true,
skip_empty_lines: true
})
})
}
}
```
## createContentLoader
Helper for loading markdown content (common for blogs/archives):
```ts
// posts.data.ts
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md')
```
Returns array of `ContentData`:
```ts
interface ContentData {
url: string // e.g. /posts/hello.html
frontmatter: Record<string, any>
src?: string // raw markdown (opt-in)
html?: string // rendered HTML (opt-in)
excerpt?: string // excerpt HTML (opt-in)
}
```
With options:
```ts
// posts.data.ts
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
includeSrc: true, // Include raw markdown
render: true, // Include rendered HTML
excerpt: true, // Include excerpt (content before first ---)
transform(rawData) {
// Sort by date, newest first
return rawData
.sort((a, b) => +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date))
.map(page => ({
title: page.frontmatter.title,
url: page.url,
date: page.frontmatter.date,
excerpt: page.excerpt
}))
}
})
```
## Usage Example: Blog Index
```ts
// posts.data.ts
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
excerpt: true,
transform(data) {
return data
.filter(post => !post.frontmatter.draft)
.sort((a, b) => +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date))
}
})
```
```vue
<!-- posts/index.md -->
<script setup>
import { data as posts } from './posts.data.ts'
</script>
<template>
<ul>
<li v-for="post in posts" :key="post.url">
<a :href="post.url">{{ post.frontmatter.title }}</a>
<span>{{ post.frontmatter.date }}</span>
</li>
</ul>
</template>
```
## Typed Data Loaders
```ts
// example.data.ts
import { defineLoader } from 'vitepress'
export interface Data {
posts: Array<{ title: string; url: string }>
}
declare const data: Data
export { data }
export default defineLoader({
watch: ['./posts/*.md'],
async load(): Promise<Data> {
// ...
return { posts: [] }
}
})
```
## In Build Hooks
Use in config for generating additional files:
```ts
// .vitepress/config.ts
import { createContentLoader } from 'vitepress'
export default {
async buildEnd() {
const posts = await createContentLoader('posts/*.md').load()
// Generate RSS feed, sitemap, etc.
}
}
```
## Accessing Config
```ts
// example.data.ts
import type { SiteConfig } from 'vitepress'
export default {
load() {
const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG
return { base: config.site.base }
}
}
```
## Key Points
- Data loaders run only at build time in Node.js
- File must end with `.data.js` or `.data.ts`
- Import the `data` named export (not default)
- Use `watch` for local file hot reload during dev
- `createContentLoader` simplifies loading markdown collections
- Keep data small - it's inlined in the client bundle
- Heavy data should use `transform` to reduce payload
<!--
Source references:
- https://vitepress.dev/guide/data-loading
-->