This document provides guidance for AI agents working on the VuePress Ecosystem monorepo. Read it before making any changes.
- Target developers: concise, clear, essential information only
- Focus on essential information developers need to understand and implement features
- No typos or grammar errors
This is a pnpm workspaces monorepo that contains the official VuePress 2 plugins, themes, and tooling. All published packages are under the @vuepress/ scope (except create-vuepress and vp-update), and the workspace also includes some private / non-published packages.
plugins/ # Official plugins (grouped into sub-categories)
themes/ # Official themes
tools/ # CLI tools and shared helpers
docs/ # Documentation site (VuePress site)
e2e/ # End-to-end Playwright tests
scripts/ # Shared build scripts (tsdown config, release helpers)
- Node.js ≥ 22.12.0
- pnpm ≥ 10 (
packageManageris pinned inpackage.json)
| Command | What it does |
|---|---|
pnpm run bundle |
Build every package with tsdown (required before e2e tests) |
pnpm run test:unit |
Run Vitest unit tests |
pnpm run test:e2e |
Run Playwright e2e tests |
pnpm run test |
Run test:unit + test:e2e |
pnpm run lint |
OxLint + Oxfmt + Stylelint (auto-fix) |
pnpm run lint:check |
Same checks without auto-fix |
pnpm run format |
Format all files with Oxfmt |
pnpm run clean |
Delete all dist/ outputs |
pnpm run type:check |
TypeScript type checking (no emit) |
Important: All packages compile TypeScript to
./dist/viatsdown. Thedist/directories are git-ignored. Runpnpm bundlebefore running e2e tests or working with the docs site. Unit tests (pnpm test:unit) run Vitest directly against TypeScript sources via aliases and do not require a build step.
Plugins are grouped into sub-categories:
| Category | Plugins |
|---|---|
ai/ |
plugin-llms — generates llms.txt / llms-full.txt for LLM crawlers |
analytics/ |
plugin-baidu-analytics, plugin-clarity-analytics, plugin-google-analytics, plugin-umami-analytics |
blog/ |
plugin-blog, plugin-comment, plugin-feed |
development/ |
plugin-active-header-links, plugin-git, plugin-palette, plugin-reading-time, plugin-rtl, plugin-sass-palette, plugin-theme-data, plugin-toc |
features/ |
plugin-back-to-top, plugin-catalog, plugin-copy-code, plugin-copyright, plugin-icon, plugin-medium-zoom, plugin-notice, plugin-nprogress, plugin-photo-swipe, plugin-watermark |
markdown/ |
plugin-append-date, plugin-links-check, plugin-markdown-chart, plugin-markdown-container, plugin-markdown-ext, plugin-markdown-file-tree, plugin-markdown-hint, plugin-markdown-image, plugin-markdown-include, plugin-markdown-math, plugin-markdown-preview, plugin-markdown-stylize, plugin-markdown-tab, plugin-prismjs, plugin-revealjs, plugin-shiki |
pwa/ |
plugin-pwa, plugin-remove-pwa |
search/ |
plugin-docsearch, plugin-meilisearch, plugin-search, plugin-slimsearch |
seo/ |
plugin-seo, plugin-sitemap |
tools/ |
plugin-auto-frontmatter, plugin-cache, plugin-google-tag-manager, plugin-redirect, plugin-register-components, plugin-replace-assets |
theme-default— The official VuePress default theme (@vuepress/theme-default)
| Package | Description |
|---|---|
helper (@vuepress/helper) |
Shared utilities for node, client, and shared environments |
highlighter-helper (@vuepress/highlighter-helper) |
Shared utilities for syntax highlighter plugins (Shiki, Prism) |
shiki-twoslash (@vuepress/shiki-twoslash) |
TwoSlash integration for the Shiki plugin |
create-vuepress |
CLI scaffolding tool (npm create vuepress) |
vp-update (vp-update) |
CLI for updating VuePress project dependencies |
Each plugin/theme follows this layout:
src/
client/ # Browser-only code (Vue components, composables, styles)
node/ # Node.js-only code (plugin factory, markdown-it extensions)
shared/ # Code that runs in both environments (types, constants, utils)
index.ts # Re-exports node entry (consumed by VuePress core)
tests/ # Vitest unit tests (*.spec.ts)
tsdown.config.ts # Per-package tsdown build config (imports tsdownConfig from scripts/)
package.json
All source files are in src/. Compiled output goes to dist/ (git-ignored).
Plugins that must inject client-side styles or register components conditionally based on options use a src/node/prepareClientConfigFile.ts that generates a client config at build time. It returns app.writeTemp('<plugin>/config.js', ...) and the plugin exposes it via clientConfigFile: () => prepareClientConfigFile(app, options). This is required when the set of imports depends on options (e.g. only import a style when the matching option is enabled) — a static src/client/config.ts is used instead when the config is always the same.
-
Relative imports must use
.jsextension even though the source files are.ts:import { foo } from './utils.js' // ✅ import { foo } from './utils' // ❌
-
No cross-folder imports between
client,node, andshared:client/— no Node.js APIs, no imports fromnode/node/— no browser APIs, no imports fromclient/shared/— no Node.js or browser APIs, no imports fromclient/ornode/
-
No bundled external dependencies — the
bundlecommand must not emit warnings about bundled externals. -
Avoid shadowing imports with option names — when a plugin option shares a name with an imported markdown-it plugin (e.g.
steps), alias the import:import { steps as stepsPlugin } from './steps.js'.
- All CSS classes must start with the
vp-prefix (e.g.vp-copy-code).- Exception: Classes for third-party integrations (e.g.
waline-wrapper).
- Exception: Classes for third-party integrations (e.g.
- CSS custom property naming:
- Color variables must contain
-c-(e.g.--vp-c-brand). - Plugin-scoped variables are prefixed with the plugin name.
- Theme-scoped variables are prefixed with
vp-. - Icon variables inside class definitions must use
--icon.
- Color variables must contain
- Reuse theme-default CSS variables instead of hardcoding colors. Commonly used:
--vp-c-bg-alt,--vp-c-bg-elv,--vp-c-text,--vp-c-text-mute,--vp-c-divider,--vp-c-border,--vp-c-accent,--vp-c-shadow,--vp-t-color,--vp-t-transform. - Use logical properties (
inset-inline-start,padding-inline-start,margin-inline-start) rather thanleft/rightphysical properties to support RTL. - SCSS files that use
@use 'pkg:@vuepress/helper'require the package to declare@vuepress/helperas a runtimedependencyorpeerDependencyin itspackage.json(not only as adevDependency), so downstream SCSS builds can resolve the import.
- All user-visible exports must have JSDoc comments.
- Comments are bilingual: English description first, then Chinese, separated by a blank line.
- Include
@param(bilingual, separated with/) for every parameter. - Include
@returns(bilingual) for every non-voidreturn value. - Include
@defaultfor every option that has a default value (including@default false). - Include
@exampleonly on exported functions. @descriptionis optional — add only when extra explanation is genuinely needed.
- Internal implementations do not require JSDoc, but existing ones must remain correct.
- Plugin entrypoint files (
*Plugin.ts,*Theme.ts) are exempt from@param/@returnsand complexity rules.
JSDoc template:
/**
* English description
*
* (optional) English detailed description
*
* 中文描述
*
* (可选)中文详细描述
*
* @param paramName - English description / 中文描述
*
* @default defaultValue
* @example
* // Example code in TypeScript
*/Commits follow Conventional Commits. The allowed scopes are the package directory names (e.g. plugin-shiki, theme-default, helper) plus e2e and release. Examples:
feat(plugin-shiki): add line number toggle
fix(theme-default): correct sidebar scroll position
chore(e2e): update playwright version
- Plugin and theme factory exports:
- The exported function name must match the package name (camelCase, e.g.
pluginShiki,themeDefault). - All types used in the public API must also be exported from the package index.
- The exported function name must match the package name (camelCase, e.g.
- Single-function files: the filename must match the exported function/class name.
All packages use a shared tsdownConfig factory defined in scripts/tsdown.ts:
- Output format: ESM only (
format: 'esm'). - Output directory:
./dist/per package. - Source maps are always emitted; code is minified in production (
NODE_ENV=production). - CSS is processed by the
@tsdown/cssplugin with SCSS support viasass-embedded. CSS chunks are split and emitted as separate files. - Packages that emit CSS must declare
"./dist/**/*.css"insideEffectsinpackage.json. - To emit SCSS/CSS from
src/client/styles/, add a wildcard entry totsdown.config.ts:tsdownConfig(['node/index', { 'client/styles/*': './src/client/styles/*.scss' }]). The CSS lands indist/client/styles/*.css. - If a CSS chunk must be importable at runtime (e.g. from a generated client config), map it in
package.jsonexports, e.g."./<name>.css": "./dist/client/styles/<name>.css", and reference it withgetModulePath('<pkg>/<name>.css', import.meta)from@vuepress/helper. - The
tsdownConfighelper acceptsonlyBundle,alwaysBundle, andneverBundleoptions for fine-grained dependency bundling control. Modules starting with@internal/and@temp/are never bundled. pnpm run type:checkresolves@vuepress/<plugin-name>from the packagedist/, so build the affected package (pnpm --filter <pkg> build) before type-checking.
- Unit tests: located at
<package>/tests/**/*.spec.ts, run with Vitest (pnpm test:unit). - E2e tests: located in
e2e/, run with Playwright (pnpm test:e2e). - Vitest aliases resolve
@vuepress/<plugin-name>directly to the TypeScript source so you do not need to build before unit testing an individual package. - Time-sensitive tests should be run with
TZ=Etc/UTC(already set by thetest:unitscript).
- Create the package directory under the appropriate
plugins/<category>/,themes/, ortools/subfolder. - Add a
package.jsonwithname,version,description,type: "module", and the standardexports/filesfields (reference an existing package). - Add a
tsdown.config.tsthat callstsdownConfig(...)from../../scripts/tsdown.ts(adjust the relative path as needed). - Write source in
src/{client,node,shared}/following the API usage restrictions above. - Export everything from
src/index.ts. - Add unit tests under
tests/.
The documentation site lives in docs/ and is built with VuePress. Each plugin has English and Chinese documentation pages. When changing plugin options or behavior, update the matching docs.
- Consistent with code behaviors
- Chinese/English content must be consistent in structure and content
- Make content concise and clear, remove unnecessary words, avoid redundancy, prefer shorter if possible
- Use "你" instead of "您" in Chinese
- Ignore any errors with
@[code ...as they are VuePress code import grammar, which is not standard. - Ignore any errors with VuePress components in markdown.
- When a container (
::: name) ends right after a list item, oxfmt re-indents the closing:::under the list item. Keep the closing marker at column 0 by adding a blank line between the last list item and:::.
Each option in plugin/theme documentation must include these sections in this exact order:
-
Type
- English:
- Type: \type`` - Chinese:
- 类型:\type`` - Follow with code fence for complex types
- English:
-
Required Status
- Only for required options:
- Required: Yes/- 必填:是 - Never write "Required: No" for optional options
- Only for required options:
-
Default Value
- INCLUDE Default when: Default value is NOT the expected/obvious value
- OMIT Default when: Default value is expected/obvious
booleanoptions withfalsedefault → OMITstringoptions with''default → OMITobjectoptions withundefineddefault → OMIT
- Format:
- Default: \value`/- 默认值:`value``
-
Details (必须包含)
- English:
- Details: Brief description - Chinese:
- 详情:简要描述 - Prefer same line for short contents and paragraph for long contents.
- English:
Example Format:
### optionName
- Type: `boolean`
- Details: Whether to enable this feature.
### requiredOption
- Type: `string`
- Required: Yes
- Details: The required configuration.
### optionWithNonStandardDefault
- Type: `number`
- Default: `100`
- Details: Custom timeout value.The following table covers the PR / build / release workflows. The repo also has issue-triage automation (issue-commented.yml, issue-daily.yml, issue-labeled.yml) which are not relevant to code changes.
| Workflow | Trigger | What it does |
|---|---|---|
check.yml |
Push / PR | Lint, type-check, unit tests |
e2e.yml |
Push / PR | Playwright e2e tests (dev + build) |
coverage.yml |
Push to main |
Code coverage report (Coveralls) |
docs.yml |
Push to main |
Deploys the documentation site |
release.yml |
Manual | Full release pipeline |