annotated-feedback
v0.1.27
Published
Universal feedback widget with visual annotations - standalone Convex backend + widget + MCP
Maintainers
Readme
Annotated Feedback
Universal feedback widget with visual annotations, powered by Convex.
Components
This package provides three integrated components:
- Convex Backend (
convex/) - Database and API for feedback collection - React Widget (
widget/) - Frontend component for capturing feedback - MCP Server (
mcp/) - Model Context Protocol server for AI agents
Setup
Prerequisites
- Convex account (sign up at https://convex.dev)
- Node.js 20+
- pnpm (or npm/yarn)
Creating a New Convex Project
IMPORTANT: This package requires its own isolated Convex project.
Option 1: Manual Setup (Recommended for first-time setup)
- Go to https://dashboard.convex.dev
- Create a new project: "annotated-feedback"
- Get your deployment URL (e.g.,
https://your-deployment.convex.cloud) - Create a
.env.localfile in this directory:CONVEX_DEPLOYMENT=prod:your-deployment-name CONVEX_URL=https://your-deployment.convex.cloud
Option 2: CLI Setup (Interactive)
npx convex init
# Choose "Create new project"
# Name it "annotated-feedback"Deploying the Backend
# Deploy to production
pnpm convex:deploy
# Or start development mode
pnpm convex:devUsing the Widget
npm install annotated-feedbackimport { FeedbackProvider } from 'annotated-feedback/widget'
import 'annotated-feedback/widget/styles'
function App() {
return (
<FeedbackProvider
convexUrl="https://your-deployment.convex.cloud"
project="my-app"
enabled={process.env.NODE_ENV !== 'production'}
hotkey="Alt+F"
>
{/* your app */}
</FeedbackProvider>
)
}Next.js (App Router) SSR Notes
The widget depends on Excalidraw, which references window/navigator during module evaluation. When a Next.js App Router layout imports FeedbackProvider directly, the server render path throws ReferenceError: navigator is not defined.
Work around this by:
- Wrapping the integration in a client component.
- Dynamically importing the widget on the client (e.g. inside
useEffector vianext/dynamic({ ssr: false })).
Example pattern:
"use client";
import { useEffect, useState } from "react";
export function FeedbackWidgetProvider({ children }) {
const [FeedbackProvider, setFeedbackProvider] = useState(null);
useEffect(() => {
import("annotated-feedback/widget").then((mod) => {
setFeedbackProvider(() => mod.FeedbackProvider);
});
}, []);
return (
<>
{children}
{FeedbackProvider ? (
<FeedbackProvider
convexUrl={process.env.NEXT_PUBLIC_FEEDBACK_CONVEX_URL!}
project="my-app"
enabled
showButton
/>
) : null}
</>
);
}This keeps the widget disabled during SSR, then hydrates the overlay once the browser environment is available.
Using the MCP Server
claude mcp add annotated-feedback --scope user -- \
env CONVEX_URL="https://your-deployment.convex.cloud" \
PROJECT="my-app" \
npx -y annotated-feedbackFeedback Watcher
Use scripts/watch-feedback.ts (or the standalone CJS version) to stream pending feedback and invoke a shell command per item. The example command /action-feedback-item {id} in the config uses the claude-comms helper from https://github.com/screwyforcepush/claude-comms.
Development
See individual package READMEs:
- Widget:
widget/README.md - MCP:
mcp/README.md
Architecture
This package uses a shared Convex backend model:
- Multiple apps can submit feedback to one central deployment
- Apps are distinguished by the
projectfield - MCP server can be scoped to one project via
PROJECTenv var
License
MIT
