Monorepo layout

Hover is a single pnpm workspace. packages/* ship to npm; examples/* are smoke targets.

Published packages

PackageWhat it does
@hover-dev/coreThe Node service: agent CLI invocation, Playwright CDP preflight, WebSocket bridge between the widget and the agent. Owns the plugin API (Reference → Plugin API).
@hover-dev/widget-bootstrapThe widget itself — HTML template, CSS, vanilla JS. Builds a script bundle every bundler-plugin re-uses byte-identically.
vite-plugin-hoverThe Vite dev-server shim. apply: 'serve' so it's a no-op in production builds.
@hover-dev/astroAstro integration. Astro's HTML pipeline bypasses Vite's transformIndexHtml, so this package wraps the core service + widget bundle behind Astro's injectScript('page', …).
@hover-dev/nuxtNuxt module. Nuxt renders HTML through Nitro, not Vite, so we push the widget into nuxt.options.app.head.script.
@hover-dev/nextNext.js (App Router, Turbopack) integration. Three pieces: withHover config wrapper, register() from @hover-dev/next/instrumentation, and the <HoverScript /> Server Component.
webpack-plugin-hoverWebpack 5 plugin — vanilla webpack-dev-server, Rspack / Rsbuild, legacy CRA / Vue CLI. Hooks HtmlWebpackPlugin.alterAssetTagGroups. Does NOT cover Next 16+ (Turbopack default).
@hover-dev/clinpx @hover-dev/cli setup — reads the user's package.json, picks the right shim, AST-mutates their bundler config via magicast.
@hover-dev/securityThe first optional plugin. MITM HTTPS proxy + flow inspector + MCP server for the agent. See Features → Security testing.

Examples

Each example runs on its own port and uses one of the bundler shims, so they double as smoke targets for every integration:

ExamplePortStresses
basic-app5173Login + counter + todos — minimal happy-path test
e-commerce5174Cart state, product grid, checkout, cross-tab popup payment flow
stock-registration5175Realistic ~50-field brokerage account form, conditional reveals
canvas-paint5176Canvas drawing + DOM toolbar (canvas pixels are opaque to Playwright snapshots)
payment-provider5177Deliberately unintegrated third-party payment page; popup target for e-commerce
astro-app5178Astro 5 dogfood
nuxt-app5179Nuxt 4 dogfood
webpack-app5180Vanilla webpack 5 + webpack-dev-server
rn-web-app5181React Native Web — RN components rendering to DOM
next-app5182Next 16 App Router (Turbopack default)
turbo-monorepoturbo + pnpm-workspace with two Next.js 15 apps (apps/web, apps/game); reproduces the shape real users have when running npx @hover-dev/cli setup on a turbo project; not part of pnpm dev:example:*

Concurrent examples are supported. The Hover service auto-bumps from 127.0.0.1:51789 up through :51798; each widget reads window.__HOVER_PORT__ and connects only to its own service.

Next.js entry-point tax

Most packages set main / exports directly to src/*.ts, so consumers' transpilers see TypeScript source with zero build step. The dev loop is "edit .ts → HMR."

Two exceptions: @hover-dev/core and @hover-dev/widget-bootstrap point main / exports at dist/*.js. Reason: @hover-dev/next consumes them via await import(…) from inside Next's instrumentation.ts, and Next 16's Turbopack does not rewrite NodeNext-style .js import specifiers back to on-disk .ts files inside transitively-traced source packages (open issue vercel/next.js#82945).

Practical implications:

  • A root postinstall hook runs pnpm --filter @hover-dev/core --filter @hover-dev/widget-bootstrap build after every pnpm install. Fresh clones get usable dist/ artefacts before anyone touches an example.
  • pnpm dev:example:next-app spawns concurrently with tsc --watch for both packages + next dev itself. Edits to packages/core/src/service.ts re-emit packages/core/dist/service.js in ~500 ms; Next picks up the changed dist file and HMRs.
  • Other examples (Vite / Astro / Nuxt / Webpack / RN Web) tolerate src-entry shape but consume those two packages via dist too. The postinstall guarantees dist exists; the watchers aren't running for those examples, so a cross-package edit during example dev needs either a one-shot pnpm --filter @hover-dev/core build or a separate pnpm --filter @hover-dev/core dev terminal.

This is temporary. When vercel/next.js#82945 ships, both packages switch back to src-entry shape and the watcher dance goes away. Tracking comment lives in packages/next-integration/src/withHover.ts.