Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions _package-export/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions _package-export/example/src/app/install/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,31 @@ function App() {
/>
</section>

<section>
<h2>Vite plugin (alternative)</h2>
<p>
For Vite projects, you can use the Vite plugin which automatically
injects Agentation during development without modifying your app code.
</p>
<CodeBlock code="npm install vite-plugin-agentation" language="bash" copyable />
<p style={{ marginTop: "1rem" }}>
Add the plugin to your <code>vite.config.ts</code>:
</p>
<CodeBlock
code={`import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import agentation from "vite-plugin-agentation";

export default defineConfig({
plugins: [react(), agentation()],
});`}
language="typescript"
/>
<p style={{ marginTop: "1rem", fontSize: "0.875rem", color: "rgba(0,0,0,0.6)" }}>
The plugin only runs in dev mode and automatically excludes itself from production builds.
</p>
</section>

<section>
<h2>Requirements</h2>
<ul>
Expand Down
1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
packages:
- '_package-export'
- '_package-export/example'
- 'vite-plugin'
73 changes: 73 additions & 0 deletions vite-plugin/README.md
Original file line number Diff line number Diff line change
@@ -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 (
<>
<YourApp />
{process.env.NODE_ENV === 'development' && <Agentation />}
</>
)
}
```

## License

© 2026 Benji Taylor
Licensed under PolyForm Shield 1.0.0
47 changes: 47 additions & 0 deletions vite-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"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": "tsup",
"dev": "tsup --watch",
"typecheck": "tsc --noEmit"
},
"peerDependencies": {
"agentation": "*",
"vite": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
},
"devDependencies": {
"@types/node": "^22.0.0",
"tsup": "^8.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"
}
105 changes: 105 additions & 0 deletions vite-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import type { Plugin, HtmlTagDescriptor } 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';

let root = null;

function init() {
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);

root = createRoot(container);
root.render(createElement(Agentation));
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} 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

return {
name: 'vite-plugin-agentation',
apply: 'serve',

config() {
return {
optimizeDeps: {
include: ['agentation', 'react', 'react-dom/client']
}
}
},

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 }
21 changes: 21 additions & 0 deletions vite-plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES2020"],
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
11 changes: 11 additions & 0 deletions vite-plugin/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -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"],
}));