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

chalk-edit

v0.1.0

Published

Inline editing + AI review overlay for web pages. Comment on any text, get AI-powered suggestions.

Readme

Chalk

Most web pages go through this:

Writer → Google Doc → Designer → Figma → 2-3 revision rounds → Dev → more revision rounds

Three people. Four tools. Every transition is a manual content transcription: doc to Figma text layers to JSX strings. A single copy edit means touching three tools and three people. The writer can't see it rendered. The designer reviews a mockup, not the real page. The developer gets messy input and spends days cleaning it up before they can publish.

Chalk fixes the input:

Staging page → Writer edits inline → Designer comments on the real page → AI applies → Dev imports and ships

The staging page replaces both the Google Doc and the Figma. The writer edits real copy in real layout. The designer reviews the actual rendered page, not a mockup. By the time dev gets the content, it's final: reviewed, refined, and structured as clean JSON they can import directly. Hours to publish, not days.

Chalk is a React component library that turns any staging page into this surface. Store your content as JSON with TextElement { id, text } fields. Chalk adds inline editing, anchored comments, and AI review on top.

Not a CMS. Not a page builder. A thin overlay that gives the writer and designer a shared surface, and gives the developer clean input.

Install

npm install chalk-edit

Quick start

1. Store content as JSON with TextElement fields

{
  "pageId": "landing",
  "hero": {
    "h1": { "id": "landing.hero.h1", "text": "Ship faster with fewer meetings" },
    "body": { "id": "landing.hero.body", "text": "Stop transcribing copy between tools." }
  }
}

Every text field is a TextElement { id, text }. That's the only contract.

2. Wrap your page with ChalkProvider

import { ChalkProvider, ChalkToolbar, CommentPanel, ReviewPanel, ChalkText } from "chalk-edit/react";

export default function LandingPage({ content }) {
  return (
    <ChalkProvider pageId="landing">
      <ChalkText element={content.hero.h1} tag="h1" className="text-4xl font-bold" />
      <ChalkText element={content.hero.body} tag="p" className="text-lg" />
      <ChalkToolbar />
      <CommentPanel />
      <ReviewPanel />
    </ChalkProvider>
  );
}

3. Add API routes (Next.js)

// src/app/api/chalk/content/route.ts
import { createContentHandler } from "chalk-edit/next";
const { GET, PUT } = createContentHandler({
  contentDir: "src/content",
  pageIdToSlug: (pageId) => pageId,
});
export { GET, PUT };
// src/app/api/chalk/comments/route.ts
import { createCommentsHandler } from "chalk-edit/next";
const { GET, POST, PATCH, DELETE } = createCommentsHandler({
  chalkDir: "src/content/.chalk",
});
export { GET, POST, PATCH, DELETE };
// src/app/api/chalk/review/route.ts
import { createReviewHandler } from "chalk-edit/next";
const { GET, POST } = createReviewHandler({
  contentDir: "src/content",
  chalkDir: "src/content/.chalk",
});
export { GET, POST };

Done. Your staging page is now an editing surface.

How it works

Three modes, toggled from a floating toolbar at the bottom of the page.

View -- Normal page. No editing UI. What the visitor sees.

Edit -- Every ChalkText becomes contentEditable. Click, type, save. The writer works on the real rendered page, not a doc.

Comment -- Click any text to leave a comment anchored to that specific element. The designer comments on real rendered copy in real layout, not a Figma approximation. Comments appear in a right sidebar with timestamps, resolve/reopen, and delete.

AI review

When the designer leaves comments, one button sends them all for AI review. Chalk does not call any AI API itself. Instead:

  1. Chalk saves a review request to disk (open comments + content snapshot).
  2. An external tool (Claude Code, a CI script, whatever) reads the request, reasons about all comments together, and writes edits back.
  3. Chalk polls for the edits and shows them inline with accept/reject per edit.

The AI sees every comment in context and produces coherent edits across the page. No more one-at-a-time revision rounds. The prompt is yours to build. Chalk gives you collectText() to flatten content into a map, and the comment data to work with.

Why this exists

The workflow problem isn't speed. It's the number of translations. Content gets written once and transcribed four times: doc, Figma layers, JSX, then back through the loop for revisions. Each translation introduces drift. The designer sees a mockup that doesn't match the build. The writer sees a doc that doesn't match the design. The developer gets ambiguous input and spends time reconciling what the writer meant, what the designer mocked up, and what's actually buildable.

Chalk eliminates the translations before dev. Every edit happens on the actual page. The JSON content file is the single source of truth. When the writer changes a headline, it's rendered immediately in the real layout. When the designer comments on spacing, they're looking at real CSS, not a Figma approximation. By the time the developer receives the content, it's been edited and reviewed on the real page. They import structured JSON, review it in their own environment, refine, and publish.

Core API

Pure functions. No React, no Node, no side effects.

import { findElement, updateElement, collectText, getAllElementIds } from "chalk-edit/core";
import { elementId, commentId, te, sectionFromId, pageFromId } from "chalk-edit/core";
import { TextElementSchema, CommentSchema, ReviewEditSchema } from "chalk-edit/core";

| Function | What it does | |----------|-------------| | findElement(obj, id) | Find a TextElement by ID anywhere in a nested object | | updateElement(obj, id, text) | Update a TextElement's text by ID. Mutates in place. | | collectText(obj) | Collect all TextElements into { id: text } map | | getAllElementIds(obj) | Get all TextElement IDs from a nested object | | elementId(pageId, ...path) | Generate a deterministic element ID | | commentId() | Generate a random comment ID | | te(pageId, path, text) | Shorthand to create a TextElement |

React components

import {
  ChalkProvider,    // Context provider. Wraps your page.
  ChalkText,        // Smart renderer: editable in edit mode, plain otherwise.
  ChalkToolbar,     // Floating toolbar: mode toggle, save, review.
  CommentPanel,     // Right sidebar for comments.
  ReviewPanel,      // AI edit suggestions panel.
  EditableText,     // Low-level contentEditable wrapper.
  useChalk,         // Hook to access Chalk state and actions.
} from "chalk-edit/react";

Theming

Chalk uses CSS custom properties. Set them on any parent element:

:root {
  --chalk-accent: #2563eb;
  --chalk-accent-hover: #1d4ed8;
  --chalk-text: #1D2939;
}

Next.js API handlers

Factory functions that return Next.js route handlers.

| Factory | Returns | Options | |---------|---------|---------| | createContentHandler(opts) | { GET, PUT } | contentDir, pageIdToSlug?, devOnly? | | createCommentsHandler(opts) | { GET, POST, PATCH, DELETE } | chalkDir | | createReviewHandler(opts) | { GET, POST } | contentDir, chalkDir, pageIdToSlug? |

Content writes are dev-only by default. Set devOnly: false to allow in production.

Keyboard shortcuts

| Key | Action | |-----|--------| | V | View mode | | E | Edit mode | | C | Comment mode (toggles panel) | | S | Save (edit mode, when dirty) | | R | Request AI review (comment mode, with open comments) |

Shortcuts appear as tooltips when you hover any toolbar button.

Relationship to Marker

Marker solves the same workflow problem for slide decks. Chalk solves it for web pages. Both share the same primitives (TextElement, Comment, ReviewEdit) and the pattern of element-level comments processed by AI in a single pass.

Marker is a CLI that owns the full rendering pipeline. Chalk is a component library that layers onto your existing pages.

License

MIT