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 🙏

© 2026 – Pkg Stats / Ryan Hefner

payloadcms-visual-editor

v0.0.2

Published

A Payload CMS plugin for inline editing and visual feedback.

Readme

Payload Visual Editor

License: MIT

Edit CMS content directly on your live pages. Annotate everything else.

Payload Visual Editor eliminates the round-trip between your frontend and the admin panel. Content editors click and edit text fields right where they appear on the page. For elements that live in code (layout, styling, components), switch to annotation mode — place visual markers with comments and send the feedback to your developers, GitHub issues, or an AI agent via webhooks.

Features

  • Inline Content Editing — Click any CMS-managed text field on your page to edit, save as draft, or publish without ever opening the admin panel (text fields only — other fields coming soon)
  • Visual Annotation Mode — Place numbered markers anywhere on the page — perfect for elements that live in code rather than your CMS
  • Route Feedback Anywhere — Export annotations as markdown, send them to a webhook (GitHub issues, CI pipelines, dev notifications), or connect to an AI agent via MCP (coming soon)
  • Draft-Aware — Full integration with Payload's draft mode, including save and publish from the toolbar
  • React Component Detection — Annotate with React component paths in development mode
  • Draggable & Customizable — Repositionable toolbar, dark/light theme, 7 marker colors, keyboard shortcuts (Cmd+Shift+F to toggle)
  • Per-Collection Configuration — Enable or disable editing per Payload collection

Demo

https://github.com/user-attachments/assets/746a7f89-88c8-44b0-87ff-1c53a08c028f

Installation

npm install payload-visual-editor
# or
pnpm add payload-visual-editor
# or
yarn add payload-visual-editor

Requirements

  • Payload CMS 3.x
  • Draft mode configured on your collections

Note: The visual editor requires Payload's draft mode to be enabled. When fetching documents, pass contentSourceMap: true in the query context to populate the _sourceMap field.

Quick Start

1. Add the plugin to your Payload config

// payload.config.ts
import { payloadVisualEditor } from 'payload-visual-editor'

export default buildConfig({
  plugins: [
    payloadVisualEditor({
      collections: {
        pages: true,
        posts: true,
      },
    }),
  ],
})

2. Mark your frontend elements as editable

Use the createEditableAttrs helper to extract editable paths from the _sourceMap field, then spread the attributes on your elements.

// app/(frontend)/[slug]/page.tsx
import { getPayload } from 'payload'
import { createEditableAttrs } from 'payload-visual-editor'

export default async function Page({ params }) {
  const payload = await getPayload({ config: configPromise })

  const pageResult = await payload.find({
    collection: 'pages',
    context: {
      contentSourceMap: true,
    },
    draft: true,
    limit: 1,
  })

  const page = pageResult.docs[0]
  const editable = createEditableAttrs(page._sourceMap)

  return (
    <main>
      <h1 {...editable('title')}>{page.title}</h1>
      <p {...editable('description')}>{page.description}</p>
    </main>
  )
}

3. Mount the toolbar on your page

import { VisualEditorToolbar } from 'payload-visual-editor/client'

{
  draft && page._sourceMap ? (
    <VisualEditorToolbar
      documentInfo={{
        id: page.id,
        collection: 'pages',
        hasDrafts: true,
      }}
      editablePaths={Object.keys(page._sourceMap)}
    />
  ) : null
}

4. Start editing

Visit any draft page on your frontend. The toolbar appears at the bottom of the viewport. Click any editable element to edit it inline, or switch to annotation mode to leave visual feedback.

Configuration

Plugin Options

payloadVisualEditor({
  collections: {
    // Keys are collection slugs, values enable the plugin for that collection
    pages: true,
    posts: true,
  },
  // Set to true to disable the plugin without removing it from config
  disabled: false,
})

VisualEditorToolbar Props

Required:

| Prop | Type | Description | | -------------- | -------------------------------------------------------------------- | ----------------------------------------------------- | | documentInfo | { id: string \| number; collection: string; hasDrafts: boolean } | Payload CMS document metadata for the current page | | editablePaths| string[] | Array of PayloadCMS content paths that can be edited |

Optional:

| Prop | Type | Default | Description | | -------------------- | ---------------------------------------------- | ----------- | ------------------------------------------------------------------ | | className | string | - | Custom class applied to the toolbar container | | copyToClipboard | boolean | true | Copy markdown output to clipboard when copy button is clicked | | endpoint | string | - | Server URL for sync (e.g. "http://localhost:4747") | | sessionId | string | - | Pre-existing session ID to join | | webhookUrl | string | - | Webhook URL to receive annotation events | | enableDemoMode | boolean | false | Enable demo mode with sample annotations | | demoAnnotations | DemoAnnotation[] | - | Array of demo annotations to display | | demoDelay | number | 1000 | Delay in ms before showing demo annotations | | onAnnotationAdd | (annotation: Annotation) => void | - | Callback fired when an annotation is added | | onAnnotationDelete | (annotation: Annotation) => void | - | Callback fired when an annotation is deleted | | onAnnotationUpdate | (annotation: Annotation) => void | - | Callback fired when an annotation comment is edited | | onAnnotationsClear | (annotations: Annotation[]) => void | - | Callback fired when all annotations are cleared | | onCopy | (markdown: string) => void | - | Callback fired when copy button is clicked | | onSubmit | (output: string, annotations: Annotation[]) | - | Callback fired when "Send to Agent" is clicked | | onSessionCreated | (sessionId: string) => void | - | Called when a new session is created |

How It Works

  1. Plugin injection — The plugin adds a virtual _sourceMap JSON field to each configured collection
  2. Query with contentSourceMap — When you query a document with context: { contentSourceMap: true }, Payload populates the _sourceMap field with content-to-path mappings
  3. createEditableAttrs() — Extracts paths from _sourceMap and returns data-payload-path attributes to spread on your elements
  4. Toolbar activation — The VisualEditorToolbar reads these attributes to identify editable elements, enabling click-to-edit and annotation on your live pages
┌─────────────────────────────────────────────────────────┐
│  Payload Query (contentSourceMap: true)                  │
│         ↓                                                │
│  _sourceMap field populated with content-to-path data    │
│         ↓                                                │
│  createEditableAttrs() → data-payload-path attributes    │
│         ↓                                                │
│  VisualEditorToolbar reads paths → enables editing       │
└─────────────────────────────────────────────────────────┘

Contributing

Clone the repo and install dependencies:

git clone https://github.com/<your-org>/payload-visual-editor
cd payload-visual-editor
pnpm install

Set up the dev environment:

cp dev/.env.example dev/.env
# Update DATABASE_URL and PAYLOAD_SECRET in dev/.env

Start the dev server:

pnpm dev

Visit http://localhost:3000 to see the demo app.

Testing & Linting

pnpm test        # Run integration + e2e tests
pnpm test:int    # Integration tests only
pnpm test:e2e    # E2E tests only
pnpm lint        # Lint source files
pnpm lint:fix    # Auto-fix lint issues
pnpm typecheck   # Run TypeScript type checking
pnpm build       # Build the package

Attribution

This plugin is based on Agentation by Benji Taylor. The original project provides an annotation toolbar for visual feedback on web pages. This plugin adapts those concepts and integrates them with Payload CMS for inline content editing and draft-aware annotation workflows.

The dev server website design is based on Tailark's Mist component kit by Méschac Irung.

License

MIT