diff --git a/.cursor/skills/framework-doctor/SKILL.md b/.cursor/skills/framework-doctor/SKILL.md
index f6ea700..1da7bda 100644
--- a/.cursor/skills/framework-doctor/SKILL.md
+++ b/.cursor/skills/framework-doctor/SKILL.md
@@ -1,11 +1,11 @@
---
name: framework-doctor
description: |
- Framework Doctor scans Svelte and React projects for security, performance, correctness, and architecture issues. Outputs a 0-100 score with actionable diagnostics.
+ Framework Doctor scans Svelte, React, and Vue projects for security, performance, correctness, and architecture issues. Outputs a 0-100 score with actionable diagnostics.
- Use when: reviewing code, finishing a feature, fixing bugs, handling user input or HTML rendering, using eval/dynamic code, or when the user mentions XSS, dead code, svelte-check, knip, oxlint, framework-doctor, react-doctor, svelte-doctor.
+ Use when: reviewing code, finishing a feature, fixing bugs, handling user input or HTML rendering, using eval/dynamic code, or when the user mentions XSS, dead code, svelte-check, knip, oxlint, framework-doctor, react-doctor, svelte-doctor, vue-doctor.
- Triggers on: security patterns, {@html}, eval(), new Function(), svelte-check, knip, oxlint, Svelte 5 migration, React best practices.
+ Triggers on: security patterns, {@html}, v-html, eval(), new Function(), svelte-check, knip, oxlint, Svelte 5 migration, React best practices, Vue/Nuxt patterns.
metadata:
version: 1.0.0
---
@@ -14,7 +14,7 @@ metadata:
Scans your frontend codebase for security, performance, correctness, and architecture issues. Auto-detects Svelte or React from `package.json`. Outputs a 0-100 score with actionable diagnostics.
-**Supported:** Svelte, React (Vue, Angular coming soon)
+**Supported:** Svelte, React, Vue (Angular coming soon)
## IMPORTANT: Run After Making Changes
@@ -29,6 +29,7 @@ Scan project?
├─ Auto-detect framework → npx -y @framework-doctor/cli . --verbose --diff
├─ Svelte only → npx -y @framework-doctor/svelte . --verbose --diff
├─ React only → npx -y @framework-doctor/react . --verbose --diff
+├─ Vue only → npx -y @framework-doctor/vue . --verbose --diff
├─ Flags (verbose, diff, score) → references/cli/commands.md
└─ What gets checked → references/checks/RULE.md
```
@@ -44,6 +45,15 @@ Svelte guidance?
└─ What doctor checks → references/checks/RULE.md
```
+### "I'm working with Vue"
+
+```
+Vue guidance?
+├─ Run doctor → npx -y @framework-doctor/vue . --verbose --diff
+├─ Security (v-html) → references/security/vue.md (if exists)
+└─ What doctor checks → references/checks/RULE.md
+```
+
### "I'm working with React"
```
diff --git a/README.md b/README.md
index bc4201a..b4a8463 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
[](https://www.npmjs.com/package/@framework-doctor/cli)
[](https://www.npmjs.com/package/@framework-doctor/cli)
-Framework Doctor auto-detects your framework and runs the right health check. Supports **Svelte** and **React**; Vue and Angular coming soon.
+Framework Doctor auto-detects your framework and runs the right health check. Supports **Svelte**, **React**, and **Vue**; Angular coming soon.
## Quick start
@@ -18,6 +18,7 @@ Or run a specific doctor directly:
```bash
npx -y @framework-doctor/react . # React
npx -y @framework-doctor/svelte . # Svelte
+npx -y @framework-doctor/vue . # Vue
```
## Try it
@@ -47,6 +48,14 @@ See [examples/README.md](examples/README.md) for more demo projects and commands
- `npx -y @framework-doctor/react . --verbose` - include file and line details
- `npx -y @framework-doctor/react . --score` - print only the numeric score (CI-friendly)
+**Vue (direct):**
+
+- `npx -y @framework-doctor/vue .` - run a full scan
+- `npx -y @framework-doctor/vue . --verbose` - include file and line details
+- `npx -y @framework-doctor/vue . --score` - print only the numeric score (CI-friendly)
+- `npx -y @framework-doctor/vue . --diff main` - scan only files changed against `main`.
+- `npx -y @framework-doctor/vue . --project web` - select a specific workspace package.
+
**Svelte (direct):**
- `npx -y @framework-doctor/svelte .` - run a full scan
@@ -79,7 +88,7 @@ Options:
-h, --help display help for command
```
-React doctor options: `--no-lint`, `--no-dead-code`, `--verbose`, `--score`, `--no-analytics`, `--project`, `--diff`. See [packages/react-doctor/README.md](packages/react-doctor/README.md).
+React doctor options: `--no-lint`, `--no-dead-code`, `--verbose`, `--score`, `--no-analytics`, `--project`, `--diff`, `--offline`. See [packages/react-doctor/README.md](packages/react-doctor/README.md).
## Security checks
diff --git a/examples/vue/demo-app/README.md b/examples/vue/demo-app/README.md
new file mode 100644
index 0000000..31fc3cd
--- /dev/null
+++ b/examples/vue/demo-app/README.md
@@ -0,0 +1,28 @@
+# Framework Doctor Vue Demo
+
+A minimal Vue 3 + Vite app with **intentional issues** for testing [Framework Doctor](https://github.com/pitis/framework-doctor).
+
+## Run the doctor
+
+From the framework-doctor repo root (after `pnpm install` and `pnpm build`):
+
+```bash
+pnpm exec framework-doctor examples/vue/demo-app
+# or directly:
+pnpm exec vue-doctor examples/vue/demo-app
+```
+
+## Intentional issues
+
+- **Security** — `eval()`, `new Function()`, `setTimeout("string")` in `src/lib/SecurityTest.ts`
+- **Dead code** — Unused exports in `src/lib/orphanUtils.ts`
+- **v-html** — `v-html` with user content in `App.vue`
+- **XSS** — `javascript:` URLs in `App.vue`
+- **Accessibility** — div with `role="button"` (no keyboard support), empty anchor links
+
+## Develop
+
+```bash
+pnpm install
+pnpm dev
+```
diff --git a/examples/vue/demo-app/index.html b/examples/vue/demo-app/index.html
new file mode 100644
index 0000000..392d59c
--- /dev/null
+++ b/examples/vue/demo-app/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Framework Doctor Vue Demo
+
+
+
+
+
+
diff --git a/examples/vue/demo-app/package.json b/examples/vue/demo-app/package.json
new file mode 100644
index 0000000..c268cdc
--- /dev/null
+++ b/examples/vue/demo-app/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "framework-doctor-vue-demo",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Demo Vue app for Framework Doctor - includes intentional issues",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vue-tsc --noEmit && vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.0.0",
+ "typescript": "^5.0.0",
+ "vite": "^6.0.0",
+ "vue": "^3.0.0",
+ "vue-tsc": "^2.1.10"
+ },
+ "packageManager": "pnpm@10.30.0"
+}
diff --git a/examples/vue/demo-app/public/favicon.svg b/examples/vue/demo-app/public/favicon.svg
new file mode 100644
index 0000000..426c179
--- /dev/null
+++ b/examples/vue/demo-app/public/favicon.svg
@@ -0,0 +1 @@
+
diff --git a/examples/vue/demo-app/src/App.vue b/examples/vue/demo-app/src/App.vue
new file mode 100644
index 0000000..9a4d22e
--- /dev/null
+++ b/examples/vue/demo-app/src/App.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
Framework Doctor Vue Demo
+
A minimal Vue app with intentional issues for vue-doctor testing.
+
+
+
+
+
+
+
vue-doctor test section (intentional issues)
+
+
+
+
+
diff --git a/examples/vue/demo-app/src/components/DoctorTestComponent.vue b/examples/vue/demo-app/src/components/DoctorTestComponent.vue
new file mode 100644
index 0000000..06b6853
--- /dev/null
+++ b/examples/vue/demo-app/src/components/DoctorTestComponent.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/examples/vue/demo-app/src/lib/SecurityTest.ts b/examples/vue/demo-app/src/lib/SecurityTest.ts
new file mode 100644
index 0000000..1a9208c
--- /dev/null
+++ b/examples/vue/demo-app/src/lib/SecurityTest.ts
@@ -0,0 +1,13 @@
+/**
+ * INTENTIONAL SECURITY ISSUES for vue-doctor testing.
+ * These are dangerous patterns that should be flagged by linters.
+ */
+
+export const dangerousEval = (userInput: string): unknown => eval(userInput);
+
+export const dangerousFunction = (userCode: string): (() => void) =>
+ new Function(userCode) as () => void;
+
+export const dangerousTimeout = (): void => {
+ setTimeout("console.log('arbitrary code')", 100);
+};
diff --git a/examples/vue/demo-app/src/lib/orphanUtils.ts b/examples/vue/demo-app/src/lib/orphanUtils.ts
new file mode 100644
index 0000000..7c1fbe8
--- /dev/null
+++ b/examples/vue/demo-app/src/lib/orphanUtils.ts
@@ -0,0 +1,8 @@
+/**
+ * INTENTIONAL: Unused file for vue-doctor testing.
+ * This file is not imported anywhere - knip will report it as unused.
+ */
+
+export const ORPHAN_CONSTANT = 42;
+
+export const orphanHelper = (value: number): number => value * 2;
diff --git a/examples/vue/demo-app/src/main.ts b/examples/vue/demo-app/src/main.ts
new file mode 100644
index 0000000..8dd6bc1
--- /dev/null
+++ b/examples/vue/demo-app/src/main.ts
@@ -0,0 +1,5 @@
+import { createApp } from 'vue';
+import App from './App.vue';
+import './style.css';
+
+createApp(App).mount('#app');
diff --git a/examples/vue/demo-app/src/style.css b/examples/vue/demo-app/src/style.css
new file mode 100644
index 0000000..2887f6a
--- /dev/null
+++ b/examples/vue/demo-app/src/style.css
@@ -0,0 +1,13 @@
+#app {
+ max-width: 800px;
+ margin: 0 auto;
+ padding: 2rem;
+ font-family: system-ui, sans-serif;
+}
+
+.example {
+ margin: 1rem 0;
+ padding: 1rem;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+}
diff --git a/examples/vue/demo-app/src/vite-env.d.ts b/examples/vue/demo-app/src/vite-env.d.ts
new file mode 100644
index 0000000..149f067
--- /dev/null
+++ b/examples/vue/demo-app/src/vite-env.d.ts
@@ -0,0 +1,7 @@
+///
+
+declare module '*.vue' {
+ import type { DefineComponent } from 'vue';
+ const component: DefineComponent