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>
6.2 KiB
6.2 KiB
Vue Support
Build Vue component libraries with tsdown.
Overview
tsdown provides first-class support for Vue libraries through integration with unplugin-vue and rolldown-plugin-dts for type generation.
Quick Start
Use Starter Template
npx create-tsdown@latest -t vue
Basic Configuration
Install Dependencies
pnpm add -D unplugin-vue vue-tsc
Minimal Setup
// tsdown.config.ts
import { defineConfig } from 'tsdown'
import Vue from 'unplugin-vue/rolldown'
export default defineConfig({
entry: ['./src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['vue'],
plugins: [
Vue({ isProduction: true }),
],
dts: {
vue: true, // Enable Vue type generation
},
})
How It Works
unplugin-vue
Compiles .vue single-file components:
- Transforms template to render functions
- Handles scoped styles
- Processes script setup
vue-tsc
Generates TypeScript declarations:
- Type-checks Vue components
- Creates
.d.tsfiles - Preserves component props types
- Exports component types
Component Example
Single File Component
<!-- src/Button.vue -->
<script setup lang="ts">
interface Props {
type?: 'primary' | 'secondary'
disabled?: boolean
}
defineProps<Props>()
defineEmits<{
click: []
}>()
</script>
<template>
<button
:class="['btn', `btn-${type}`]"
:disabled="disabled"
@click="$emit('click')"
>
<slot />
</button>
</template>
<style scoped>
.btn {
padding: 8px 16px;
border-radius: 4px;
}
.btn-primary {
background: blue;
color: white;
}
</style>
Export Components
// src/index.ts
export { default as Button } from './Button.vue'
export { default as Input } from './Input.vue'
export { default as Modal } from './Modal.vue'
// Re-export types
export type { ButtonProps } from './Button.vue'
Common Patterns
Component Library
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['vue'],
plugins: [
Vue({
isProduction: true,
style: {
trim: true,
},
}),
],
dts: {
vue: true,
},
clean: true,
})
Multiple Components
export default defineConfig({
entry: {
index: 'src/index.ts',
Button: 'src/Button.vue',
Input: 'src/Input.vue',
Modal: 'src/Modal.vue',
},
format: ['esm', 'cjs'],
external: ['vue'],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
With Composition Utilities
// src/composables/useCounter.ts
import { ref } from 'vue'
export function useCounter(initial = 0) {
const count = ref(initial)
const increment = () => count.value++
const decrement = () => count.value--
return { count, increment, decrement }
}
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: ['vue'],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
TypeScript Configuration
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"jsx": "preserve",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"strict": true,
"isolatedDeclarations": true,
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Package.json Configuration
{
"name": "my-vue-library",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
},
"files": ["dist"],
"peerDependencies": {
"vue": "^3.0.0"
},
"devDependencies": {
"tsdown": "^0.9.0",
"typescript": "^5.0.0",
"unplugin-vue": "^5.0.0",
"vue": "^3.4.0",
"vue-tsc": "^2.0.0"
}
}
Advanced Patterns
With Vite Plugins
Some Vite Vue plugins may work:
import Vue from 'unplugin-vue/rolldown'
import Components from 'unplugin-vue-components/rolldown'
export default defineConfig({
entry: ['src/index.ts'],
external: ['vue'],
plugins: [
Vue({ isProduction: true }),
Components({
dts: 'src/components.d.ts',
}),
],
dts: { vue: true },
})
JSX Support
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: ['vue'],
plugins: [
Vue({
isProduction: true,
script: {
propsDestructure: true,
},
}),
],
inputOptions: {
transform: {
jsx: 'automatic',
jsxImportSource: 'vue',
},
},
dts: { vue: true },
})
Monorepo Vue Packages
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: ['vue', /^@mycompany\//],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
Plugin Options
unplugin-vue Options
Vue({
isProduction: true,
script: {
defineModel: true,
propsDestructure: true,
},
style: {
trim: true,
},
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('custom-'),
},
},
})
Tips
- Always externalize Vue - Don't bundle Vue itself
- Enable vue: true in dts - For proper type generation
- Use platform: 'neutral' - Maximum compatibility
- Install vue-tsc - Required for type generation
- Set isProduction: true - Optimize for production
- Add peer dependency - Vue as peer dependency
Troubleshooting
Type Generation Fails
Ensure vue-tsc is installed:
pnpm add -D vue-tsc
Enable in config:
dts: { vue: true }
Component Types Missing
Check TypeScript config:
{
"compilerOptions": {
"jsx": "preserve",
"moduleResolution": "bundler"
}
}
Vue Not Externalized
Add to external:
external: ['vue']
SFC Compilation Errors
Check unplugin-vue version:
pnpm add -D unplugin-vue@latest
Related
- Plugins - Plugin system
- Dependencies - External packages
- DTS - Type declarations
- React Recipe - React component libraries