Musea
⚠️ Work in Progress: Musea is still evolving. File formats, APIs, and UI behavior may change.
Musea is Vize's art-file and component-gallery toolchain.
vize_museais the Rust core for parsing*.art.vue, generating docs, building prop palettes,@vizejs/vite-plugin-museais the recommended gallery and dev-server workflow today.musea-vrtis the CLI for visual regression snapshots, a11y audits, approvals, cleanup, and
Overview

Musea uses *.art.vue files to describe component variants with Vue-native syntax.
Installation
Install vp once from the Vite+ install guide, then add the package:
vp install -D @vizejs/vite-plugin @vizejs/vite-plugin-musea vize
Recommended Usage: Vite Plugin
// vite.config.ts
import { defineConfig } from "vite";
import vize from "@vizejs/vite-plugin";
import { musea } from "@vizejs/vite-plugin-musea";
export default defineConfig({
plugins: [
vize(),
musea({
include: ["**/*.art.vue"],
basePath: "/__musea__",
previewCss: ["src/styles/main.css"],
previewSetup: "musea.preview.ts",
}),
],
});
Run your normal Vite dev server and open the configured Musea route:
vp dev
http://localhost:5173/__musea__
If you install the vize npm package, vp exec vize musea is a convenience wrapper around Vite:
vp exec vize musea
vp exec vize musea --build
Shared Config
musea() options override shared config. Put stable project defaults in vize.config.ts and keep
preview-only settings in vite.config.ts.
// vize.config.ts
import { defineConfig } from "vize";
export default defineConfig({
musea: {
include: ["src/**/*.art.vue"],
exclude: ["node_modules/**", "dist/**"],
basePath: "/__musea__",
storybookCompat: false,
inlineArt: false,
},
});
Shared config currently covers include, exclude, basePath, storybookCompat, and
inlineArt. Pass previewCss, previewSetup, tokensPath, theme, and storybookOutDir
directly to musea().
Art Files
<script setup lang="ts">
import MyButton from "./MyButton.vue";
</script>
<art
title="MyButton"
component="./MyButton.vue"
category="Components"
status="ready"
tags="button, ui, input"
action-events="click, focus"
>
<variant name="Default" default>
<MyButton type="button">Click me</MyButton>
</variant>
<variant name="Outlined">
<MyButton type="button" outlined>Click me</MyButton>
</variant>
</art>
Anatomy
| Element / Attribute | Purpose |
|---|---|
<art> |
Root metadata block |
title |
Display name |
component |
Relative path to the source component |
category |
Sidebar grouping |
status |
Optional status badge |
tags |
Search and filtering tags |
action-events |
Events to capture in the gallery |
capture-mousemove |
Include mousemove in captured actions |
<variant> |
Named component variation |
default |
Marks the default variant |
Keep art files close to the component when variants are part of the component's contract:
src/components/Button.vue
src/components/Button.art.vue
Use a separate stories or art directory when a design system owns many cross-cutting examples:
src/components/Button.vue
stories/forms/Button.art.vue
stories/navigation/Menu.art.vue
Inline Art
When inlineArt is enabled, regular .vue files that contain an <art> block can appear in the
gallery. This is useful for small components where examples should live in the same file.
musea({
inlineArt: true,
});
Inside inline art, use <Self> to render the host component.
Gallery Features

Musea can surface:
component and variant metadata
prop palette generation
design token views
accessibility checks
visual regression testing helpers
Storybook-compatible output when requested
Props Palette

The palette pipeline can infer interactive controls from component metadata and art definitions.
Design Tokens

@vizejs/vite-plugin-musea can ingest a Style Dictionary-compatible token file and expose it in
the gallery UI.
musea({
tokensPath: "src/tokens.json",
});
Preview Configuration
You can inject project CSS and preview setup code:
musea({
previewCss: ["src/styles/main.css", "src/styles/musea-preview.css"],
previewSetup: "musea.preview.ts",
});
This is useful for installing plugins such as vue-i18n or vue-router in the preview iframe.
// musea.preview.ts
import type { App } from "vue";
import { createI18n } from "vue-i18n";
export default function setup(app: App) {
app.use(
createI18n({
legacy: false,
locale: "en",
messages: {
en: {},
},
}),
);
}
Visual Regression Testing
The package exposes the musea-vrt binary:
vp exec musea-vrt --base-url http://localhost:5173
vp exec musea-vrt --update
vp exec musea-vrt --ci --json
vp exec musea-vrt --a11y
vp exec musea-vrt approve
vp exec musea-vrt approve "Button/*"
vp exec musea-vrt clean
Typical CI flow starts the Vite server in one process, then runs the snapshot command against it:
vp dev --host 0.0.0.0
vp exec musea-vrt --base-url http://localhost:5173 --ci --json
Use --update locally to refresh baselines, approve to accept failed snapshots, and clean to
remove orphaned snapshots after deleting variants.
Generate Art Files
Use the generator to create a first .art.vue draft from an existing component:
vp exec musea-vrt generate src/components/Button.vue
The generated file is a starting point. Review the variants, titles, tags, and prop coverage before committing it.
Storybook Output
Enable Storybook-compatible CSF generation when you want Musea art files to feed a Storybook setup:
musea({
storybookCompat: true,
storybookOutDir: ".storybook/stories",
});
CLI Status
vize musea exists in the Rust CLI, but the recommended Musea workflow today is still the Vite
plugin path. Treat the Rust subcommand as experimental while the dedicated gallery workflow settles.
The Rust subcommand can scaffold a starter art project:
vize musea new
Related Packages
@vizejs/vite-plugin-musea@vizejs/musea-mcp-servervize_musea