From fed924c2173895dad8c4b4d0f4c0c0a3e977dcdf Mon Sep 17 00:00:00 2001 From: Laurynas Keturakis Date: Thu, 22 Jan 2026 09:18:25 +0100 Subject: [PATCH 1/4] Add vite-plugin-agentation package to workspace --- pnpm-workspace.yaml | 1 + vite-plugin/package.json | 45 ++++++++++++++++++++ vite-plugin/src/index.ts | 88 +++++++++++++++++++++++++++++++++++++++ vite-plugin/tsconfig.json | 15 +++++++ 4 files changed, 149 insertions(+) create mode 100644 vite-plugin/package.json create mode 100644 vite-plugin/src/index.ts create mode 100644 vite-plugin/tsconfig.json diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bd0c434..1006306 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - '_package-export' - '_package-export/example' + - 'vite-plugin' diff --git a/vite-plugin/package.json b/vite-plugin/package.json new file mode 100644 index 0000000..509ddb5 --- /dev/null +++ b/vite-plugin/package.json @@ -0,0 +1,45 @@ +{ + "name": "vite-plugin-agentation", + "version": "0.0.1", + "description": "Vite plugin to inject Agentation visual feedback tool", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "tsc --watch", + "typecheck": "tsc --noEmit" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "typescript": "^5.0.0", + "vite": "^6.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/laulauland/agentation", + "directory": "vite-plugin" + }, + "keywords": [ + "vite", + "vite-plugin", + "agentation", + "feedback", + "visual-feedback", + "ui-feedback" + ], + "license": "PolyForm-Shield-1.0.0" +} diff --git a/vite-plugin/src/index.ts b/vite-plugin/src/index.ts new file mode 100644 index 0000000..db3f9a0 --- /dev/null +++ b/vite-plugin/src/index.ts @@ -0,0 +1,88 @@ +import type { Plugin, HtmlTagDescriptor, ViteDevServer } from 'vite' + +export interface AgentationPluginOptions { + /** + * Enable/disable the plugin. + * @default true in development + */ + enabled?: boolean +} + +const VIRTUAL_ID = 'virtual:agentation-inject' +const RESOLVED_ID = '\0' + VIRTUAL_ID + +const injectCode = ` +import { Agentation } from 'agentation'; +import { createElement } from 'react'; +import { createRoot } from 'react-dom/client'; + +function init() { + if (document.getElementById('agentation-root')) return; + + const container = document.createElement('div'); + container.id = 'agentation-root'; + document.body.appendChild(container); + + const root = createRoot(container); + root.render(createElement(Agentation)); +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); +} else { + init(); +} +` + +export default function agentationPlugin(options: AgentationPluginOptions = {}): Plugin { + const { enabled = true } = options + let server: ViteDevServer + + return { + name: 'vite-plugin-agentation', + apply: 'serve', + + config() { + return { + optimizeDeps: { + include: ['agentation', 'react', 'react-dom/client'] + } + } + }, + + configureServer(_server) { + server = _server + }, + + resolveId(id) { + if (id === VIRTUAL_ID) { + return RESOLVED_ID + } + }, + + load(id) { + if (id === RESOLVED_ID) { + return injectCode + } + }, + + transformIndexHtml() { + if (!enabled) return [] + + const tags: HtmlTagDescriptor[] = [ + { + tag: 'script', + attrs: { + type: 'module', + src: `/@id/${VIRTUAL_ID}` + }, + injectTo: 'body' + } + ] + + return tags + } + } +} + +export { agentationPlugin } diff --git a/vite-plugin/tsconfig.json b/vite-plugin/tsconfig.json new file mode 100644 index 0000000..d0cb6ff --- /dev/null +++ b/vite-plugin/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "declaration": true, + "outDir": "dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} From df374dcfef96aba50f31c7b9bb7017fa166d6bb6 Mon Sep 17 00:00:00 2001 From: Laurynas Keturakis Date: Thu, 22 Jan 2026 09:18:14 +0100 Subject: [PATCH 2/4] Add vite-plugin documentation - Add README for vite-plugin package with usage, options, and how it works - Update main README with Vite plugin installation section - Add Vite plugin section to install page on docs site --- README.md | 21 ++++++ _package-export/README.md | 21 ++++++ .../example/src/app/install/page.tsx | 25 +++++++ vite-plugin/README.md | 73 +++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 vite-plugin/README.md diff --git a/README.md b/README.md index cf161ec..cda304e 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,27 @@ function App() { The toolbar appears in the bottom-right corner. Click to activate, then click any element to annotate it. +### Vite plugin + +For Vite projects, you can use the plugin to inject Agentation automatically without modifying your app code: + +```bash +npm install vite-plugin-agentation -D +``` + +```ts +// vite.config.ts +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import agentation from 'vite-plugin-agentation' + +export default defineConfig({ + plugins: [react(), agentation()] +}) +``` + +The plugin only runs in dev mode and excludes itself from production builds. + ## Features - **Click to annotate** – Click any element with automatic selector identification diff --git a/_package-export/README.md b/_package-export/README.md index cf161ec..cda304e 100644 --- a/_package-export/README.md +++ b/_package-export/README.md @@ -25,6 +25,27 @@ function App() { The toolbar appears in the bottom-right corner. Click to activate, then click any element to annotate it. +### Vite plugin + +For Vite projects, you can use the plugin to inject Agentation automatically without modifying your app code: + +```bash +npm install vite-plugin-agentation -D +``` + +```ts +// vite.config.ts +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import agentation from 'vite-plugin-agentation' + +export default defineConfig({ + plugins: [react(), agentation()] +}) +``` + +The plugin only runs in dev mode and excludes itself from production builds. + ## Features - **Click to annotate** – Click any element with automatic selector identification diff --git a/_package-export/example/src/app/install/page.tsx b/_package-export/example/src/app/install/page.tsx index e23c810..2267587 100644 --- a/_package-export/example/src/app/install/page.tsx +++ b/_package-export/example/src/app/install/page.tsx @@ -282,6 +282,31 @@ function App() { /> +
+

Vite plugin (alternative)

+

+ For Vite projects, you can use the Vite plugin which automatically + injects Agentation during development without modifying your app code. +

+ +

+ Add the plugin to your vite.config.ts: +

+ +

+ The plugin only runs in dev mode and automatically excludes itself from production builds. +

+
+

Requirements

    diff --git a/vite-plugin/README.md b/vite-plugin/README.md new file mode 100644 index 0000000..9d12f27 --- /dev/null +++ b/vite-plugin/README.md @@ -0,0 +1,73 @@ +# vite-plugin-agentation + +Vite plugin that automatically injects [Agentation](https://agentation.dev) into your development server. No code changes required. + +## Install + +```bash +npm install vite-plugin-agentation -D +``` + +## Usage + +Add the plugin to your `vite.config.ts`: + +```ts +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import agentation from 'vite-plugin-agentation' + +export default defineConfig({ + plugins: [react(), agentation()] +}) +``` + +Start your dev server and Agentation appears automatically. + +## How it works + +The plugin hooks into Vite's dev server and: + +1. Injects a script tag into the HTML response +2. The script creates a container element and mounts the Agentation React component +3. Agentation loads from the `agentation` npm package (must be installed separately) + +The plugin only runs in dev mode (`apply: 'serve'`), so it's automatically excluded from production builds. + +## Options + +```ts +agentation({ + enabled: true // default: true - set to false to disable +}) +``` + +## Requirements + +- Vite 4, 5, 6, or 7 +- React 18+ (peer dependency of `agentation`) +- `agentation` package installed + +## Why use this over direct import? + +The Vite plugin approach is useful when you want to add Agentation to an existing project without modifying application code. It's also convenient for teams where not everyone needs the feedback tool—developers can install the plugin locally without affecting the shared codebase. + +For full control over placement and rendering, use the direct import method instead: + +```tsx +import { Agentation } from 'agentation' + +function App() { + return ( + <> + + {process.env.NODE_ENV === 'development' && } + + ) +} +``` + +## License + +© 2026 Benji Taylor +Licensed under PolyForm Shield 1.0.0 From 92a08cb30a8485e8454b81adebbd83f8f4240c71 Mon Sep 17 00:00:00 2001 From: Laurynas Keturakis Date: Thu, 22 Jan 2026 11:19:54 +0100 Subject: [PATCH 3/4] Align vite-plugin build config with main package - Switch from tsc to tsup for consistency - Add tsup.config.ts with ESM output - Update tsconfig.json to match main package conventions --- vite-plugin/package.json | 5 +++-- vite-plugin/tsconfig.json | 14 ++++++++++---- vite-plugin/tsup.config.ts | 11 +++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 vite-plugin/tsup.config.ts diff --git a/vite-plugin/package.json b/vite-plugin/package.json index 509ddb5..ca4610c 100644 --- a/vite-plugin/package.json +++ b/vite-plugin/package.json @@ -16,8 +16,8 @@ "dist" ], "scripts": { - "build": "tsc", - "dev": "tsc --watch", + "build": "tsup", + "dev": "tsup --watch", "typecheck": "tsc --noEmit" }, "peerDependencies": { @@ -25,6 +25,7 @@ }, "devDependencies": { "@types/node": "^22.0.0", + "tsup": "^8.0.0", "typescript": "^5.0.0", "vite": "^6.0.0" }, diff --git a/vite-plugin/tsconfig.json b/vite-plugin/tsconfig.json index d0cb6ff..f42ae88 100644 --- a/vite-plugin/tsconfig.json +++ b/vite-plugin/tsconfig.json @@ -1,14 +1,20 @@ { "compilerOptions": { "target": "ES2020", + "lib": ["DOM", "DOM.Iterable", "ES2020"], "module": "ESNext", "moduleResolution": "bundler", - "declaration": true, - "outDir": "dist", "strict": true, - "esModuleInterop": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, "skipLibCheck": true, - "forceConsistentCasingInFileNames": true + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true }, "include": ["src"], "exclude": ["node_modules", "dist"] diff --git a/vite-plugin/tsup.config.ts b/vite-plugin/tsup.config.ts new file mode 100644 index 0000000..b91fdcb --- /dev/null +++ b/vite-plugin/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "tsup"; + +export default defineConfig((options) => ({ + entry: ["src/index.ts"], + format: ["esm"], + dts: true, + splitting: false, + sourcemap: true, + clean: !options.watch, + external: ["vite"], +})); From df4c3ec976c2a561060dce50352e83577289d29a Mon Sep 17 00:00:00 2001 From: Laurynas Keturakis Date: Thu, 22 Jan 2026 11:26:14 +0100 Subject: [PATCH 4/4] Fix plugin code issues - Add agentation as peer dependency for proper npm/pnpm warnings - Remove unused server variable and ViteDevServer import - Add proper HMR cleanup with import.meta.hot.dispose --- vite-plugin/package.json | 1 + vite-plugin/src/index.ts | 33 +++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/vite-plugin/package.json b/vite-plugin/package.json index ca4610c..eb86ea5 100644 --- a/vite-plugin/package.json +++ b/vite-plugin/package.json @@ -21,6 +21,7 @@ "typecheck": "tsc --noEmit" }, "peerDependencies": { + "agentation": "*", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" }, "devDependencies": { diff --git a/vite-plugin/src/index.ts b/vite-plugin/src/index.ts index db3f9a0..3507271 100644 --- a/vite-plugin/src/index.ts +++ b/vite-plugin/src/index.ts @@ -1,4 +1,4 @@ -import type { Plugin, HtmlTagDescriptor, ViteDevServer } from 'vite' +import type { Plugin, HtmlTagDescriptor } from 'vite' export interface AgentationPluginOptions { /** @@ -16,14 +16,23 @@ import { Agentation } from 'agentation'; import { createElement } from 'react'; import { createRoot } from 'react-dom/client'; +let root = null; + function init() { - if (document.getElementById('agentation-root')) return; + const existing = document.getElementById('agentation-root'); + if (existing) { + // Clean up previous root if it exists (HMR case) + if (root) { + root.unmount(); + } + existing.remove(); + } const container = document.createElement('div'); container.id = 'agentation-root'; document.body.appendChild(container); - const root = createRoot(container); + root = createRoot(container); root.render(createElement(Agentation)); } @@ -32,11 +41,23 @@ if (document.readyState === 'loading') { } else { init(); } + +if (import.meta.hot) { + import.meta.hot.dispose(() => { + if (root) { + root.unmount(); + root = null; + } + const container = document.getElementById('agentation-root'); + if (container) { + container.remove(); + } + }); +} ` export default function agentationPlugin(options: AgentationPluginOptions = {}): Plugin { const { enabled = true } = options - let server: ViteDevServer return { name: 'vite-plugin-agentation', @@ -50,10 +71,6 @@ export default function agentationPlugin(options: AgentationPluginOptions = {}): } }, - configureServer(_server) { - server = _server - }, - resolveId(id) { if (id === VIRTUAL_ID) { return RESOLVED_ID