npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

annotated-feedback

v0.1.27

Published

Universal feedback widget with visual annotations - standalone Convex backend + widget + MCP

Readme

Annotated Feedback

Universal feedback widget with visual annotations, powered by Convex.

Components

This package provides three integrated components:

  1. Convex Backend (convex/) - Database and API for feedback collection
  2. React Widget (widget/) - Frontend component for capturing feedback
  3. 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)

  1. Go to https://dashboard.convex.dev
  2. Create a new project: "annotated-feedback"
  3. Get your deployment URL (e.g., https://your-deployment.convex.cloud)
  4. Create a .env.local file 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:dev

Using the Widget

npm install annotated-feedback
import { 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:

  1. Wrapping the integration in a client component.
  2. Dynamically importing the widget on the client (e.g. inside useEffect or via next/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-feedback

Feedback 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 project field
  • MCP server can be scoped to one project via PROJECT env var

License

MIT