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

@webreel/core

v0.1.4

Published

Core recording engine for webreel - headless Chrome capture, cursor animation, and video compositing.

Downloads

3,942

Readme

@webreel/core

Chrome automation, recording, and overlay engine for webreel.

Launches a headless Chrome instance via the Chrome DevTools Protocol, captures screenshots at ~60fps, and encodes the result to MP4 with ffmpeg. Provides actions for clicking, typing, dragging, and cursor animation, plus on-screen overlays for keystroke labels and a custom cursor.

Installation

npm install @webreel/core

Examples

custom-theme - Demonstrates fully customizing the cursor overlay and keystroke HUD appearance using a code editor page.

drag-and-drop - Demonstrates dragging elements between positions on a kanban board.

form-filling - Demonstrates typing into form fields and clicking a submit button, simulating a login flow.

gif-output - Demonstrates outputting the recording as an animated GIF instead of the default MP4.

hello-world - The simplest possible webreel example. Opens a landing page and clicks the call-to-action button.

keyboard-shortcuts - Demonstrates pressing key combos and displaying them in the keystroke HUD overlay. Uses a code editor page as the target.

mobile-viewport - Demonstrates recording at mobile device dimensions using a finance app interface.

modifier-clicks - Demonstrates clicking elements with modifier keys held down, simulating multi-select in a file manager.

multi-demo - Demonstrates defining multiple videos in a single config file, each producing its own output from the same page.

page-scrolling - Demonstrates scrolling the page and scrolling within a specific container element on a blog post layout.

screenshots - Demonstrates capturing PNG screenshots at specific points during a recording. Useful for generating static marketing assets or documentation images alongside videos.

shared-steps - Demonstrates using include to share common setup steps across videos. The shared steps dismiss a cookie consent banner before the main video steps run.

webm-output - Demonstrates outputting the recording as a WebM video using VP9 encoding.

Usage

import {
  RecordingContext,
  launchChrome,
  connectCDP,
  navigate,
  clickAt,
  pressKey,
  pause,
  Recorder,
  InteractionTimeline,
  compose,
} from "@webreel/core";

const ctx = new RecordingContext();
ctx.setMode("record");

const chrome = await launchChrome({ headless: true });
const client = await connectCDP(chrome.port);

await client.Page.enable();
await client.Runtime.enable();
await client.Emulation.setDeviceMetricsOverride({
  width: 1080,
  height: 1080,
  deviceScaleFactor: 2,
  mobile: false,
});

const timeline = new InteractionTimeline(1080, 1080, { zoom: 2 });
ctx.setTimeline(timeline);

await navigate(client, "https://example.com");

const recorder = new Recorder(1080, 1080);
recorder.setTimeline(timeline);
await recorder.start(client, "demo.mp4", ctx);

await pause(500);
await clickAt(ctx, client, 540, 400);
await pressKey(ctx, client, "cmd+a");
await pause(1000);

await recorder.stop();

await compose(recorder.getTempVideoPath(), timeline.toJSON(), "demo.mp4");

await client.close();
chrome.kill();

API

Chrome

launchChrome(options?): Promise<ChromeInstance>

Launches a Chrome process with remote debugging enabled.

| Option | Type | Default | Description | | ---------- | --------- | ------- | -------------------- | | headless | boolean | true | Run in headless mode |

Returns a ChromeInstance with process, port, and kill().

Recorder

new Recorder(width?, height?, assetsDir?)

Creates a recorder that captures screenshots and encodes them to MP4.

recorder.start(client, outputPath, ctx?): Promise<void>

Begin capturing frames. Pass an optional RecordingContext to track cursor position and timeline events.

recorder.stop(): Promise<void>

Stop capturing, encode to MP4 with sound effects, and clean up temp files.

Actions

All action functions that animate the cursor take a RecordingContext as their first argument.

| Function | Description | | -------------------------------------------------- | ------------------------------------------------- | | navigate(client, url) | Navigate to a URL and wait for load | | waitForSelector(client, selector, timeout?) | Poll until a CSS selector matches | | findElementByText(client, text, within?) | Find an element's bounding box by text content | | findElementBySelector(client, selector, within?) | Find an element's bounding box by CSS selector | | moveCursorTo(ctx, client, x, y) | Animate the overlay cursor to a position | | clickAt(ctx, client, x, y, modifiers?) | Move cursor and click with optional modifier keys | | pressKey(ctx, client, key, label?) | Press a key combo (e.g. "cmd+z") with overlay | | typeText(ctx, client, text, delayMs?) | Type text character by character | | dragFromTo(ctx, client, fromBox, toBox) | Drag between two elements | | captureScreenshot(client, outputPath) | Save a PNG screenshot | | pause(ms?) | Wait for a duration (default 1200ms) | | modKey() | Returns "cmd" on macOS, "ctrl" elsewhere |

Overlays

| Function | Description | | -------------------------------------------------- | ----------------------------------------------------- | | injectOverlays(client, theme?, initialPosition?) | Add cursor and keystroke overlay elements to the page | | showKeys(client, labels) | Display keystroke labels on screen | | hideKeys(client) | Hide the keystroke overlay |

Prerequisites

Set CHROME_PATH to override the default Chrome location.

License

Apache-2.0