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

overlay-factory-worker

v0.1.0

Published

The Goose Tools Overlay Factory worker — your computer renders reel overlays for goosetools.com with Remotion and ffmpeg.

Readme

reel-factory

Automated overlay editing for Erin's reel series. Feed it b-roll + a code card + an episode JSON, get a finished vertical MP4 with the "What Prints?" title, the code card, and a timed difficulty reveal.

Flow

npx tsx scripts/make-card.ts puzzles/x.json   # write a NEW code card from a puzzle JSON
./scripts/ingest.sh                      # pull assets from ~/Desktop/Automate Editing (via Finder)
npx tsx scripts/prep-card.ts             # code-card JPGs -> transparent rounded PNGs
npx tsx scripts/new-episode.ts        # picks next card + b-roll, places the meter
npx remotion render WhatPrints out/what-prints-XXX.mp4 --props=episodes/what-prints-XXX.json
./scripts/export.sh out/what-prints-XXX.mp4   # copy to Desktop/Automate Editing/exports

Preview while tweaking: npm run dev (Remotion Studio).

Episode JSON

{
  "broll": "assets/b-roll/IMG_4858.MOV",
  "card": "assets/cards/IMG_4030.png",
  "titleLine1": "What",
  "titleLine2": "Prints?",
  "difficulty": "hard",        // easy | medium | hard
  "durationSec": 10,
  "revealAtSec": 4,            // when the difficulty meter pops in
  "trimBeforeSec": 0,          // skip into the b-roll clip
  "meterX": 70,                // set by scripts/place-overlay.ts
  "meterY": 670
}

episodes/index.json maps every code card to its episode metadata (answer, why, caption) extracted from the caption screenshots. episodes/used.json tracks which cards/b-roll are consumed.

Generating code cards

The original cards were phone screenshots of a chat app's code block, cropped by prep-card.ts. New ones are rendered directly: write a puzzle JSON in puzzles/ and run scripts/make-card.ts. It highlights the snippet with Shiki (any language), renders the CodeCard composition to a transparent rounded PNG at public/assets/cards/<slug>.png, and upserts the entry into cards.json and index.json — so re-running the same slug edits in place.

{
  "slug": "nan-trap",
  "name": "Bowser's NaN Trap",
  "language": "Python",
  "code": "score = float(\"nan\")\nbest = score\n\nprint(score == best)",
  "answer": "False",
  "why": "NaN is never equal to itself...",
  "difficulty": "easy"
}

Every card is executed before it renders and put through scripts/quality.ts: the snippet must print exactly what answer claims, print the same thing three runs in a row and on every installed Python 3.11-3.14, be answerable in a comment (no memory addresses, nothing over 120 chars), not duplicate an existing card, and carry a real why. Any failure stops the render; --no-verify and --no-gates override. Audit the whole library with npx tsx scripts/quality.ts or npx tsx scripts/verify.ts.

Cards that fail get a retired note in index.json rather than being deleted — new-episode.ts skips them, and the audits ignore them.

Keep lines under ~45 characters and snippets under ~8 lines — beyond that the script shrinks the type to fit and warns. Colors and geometry live in src/series/what-prints/codeCardTypes.ts; preview with npm run dev.

The /what-prints-card skill writes the puzzles and drives this end to end.

Engagement data

npx tsx scripts/ig-sync.ts pulls the Instagram history for @erin.codes into episodes/performance.json — captions, likes, comments, and per-post insights (reach, saves, shares, views). Read-only; the token comes from ~/code/crossposter/.env (the ig-auto-dm one has expired).

Insights calls are rate-limited, so by default it only fetches them for posts whose caption looks like a series episode. Use --since=2026-06-01 for a date range or --all for every reel; results already fetched are reused.

npx tsx scripts/report.ts then ranks the published episodes against the account's own baseline and links each post back to the card it came from (captions are the join key; set permalink on an index.json entry to force it).

Judge cards by comments per 1,000 reach — reach swings by orders of magnitude and likes track reach, so raw likes say more about distribution than about whether the puzzle landed.

Overlay Factory

The overlay components (src/overlay/) are shared: What Prints composites them over its own b-roll, and the Overlay Factory tool on Goose Tools burns them onto any clip uploaded from a phone.

Burn overlays onto a clip locally:

npm run overlay -- clip.mov overlay.json out.mp4

Run the worker so /dashboard/overlay can send jobs to this machine. The token comes from ~/.goosetools/env, where the Carousel Maker's installer already put it — one token serves every Goose Tools worker on a machine:

npm run overlay:worker      # foreground, stops when the terminal closes
npm run overlay:install     # keep it running across reboots (launchd)
npm run overlay:uninstall   # stop it and remove the agent

overlay:install writes ~/Library/LaunchAgents/com.goosetools.overlay.plist, matching the Carousel/Caption/Brand agents. Logs land in ~/.goosetools/overlay-worker.log. The plist sets PATH explicitly — launchd starts with an almost-empty environment, and the render shells out to ffmpeg, npx and claude, so an inherited-PATH assumption is what leaves one of these agents running but failing every job.

Two passes, and the split is the point. Remotion renders only the overlay, alpha-only to ProRes 4444, at --scale so the 1080x1920 composition rasterizes natively at the output resolution. ffmpeg then composites that over the untouched source. The footage never enters Chrome, so a 4K clip stays 4K and renders in seconds rather than minutes — and every coordinate in the overlay components stays in 1080x1920 space no matter the output size.

Output is HEVC in yuv420p. That pixel format isn't cosmetic: the overlay filter hands back BGRA, and an HEVC file in BGRA imports into iOS Photos as a file that won't play.

Series

What Prints? is special-cased in the worker — it runs your snippet, checks the answer against a real run, applies the quality gates, and places the meter against the footage. Nothing generated can do that, which is why it stays code.

Every other series is generated. Tapping "+ New series" on Goose Tools queues a job; this machine reads your reference images with Claude and writes series/<slug>/:

series/hot-take/
  series.json     the fields the form asks for, and where each layer sits
  claim.html      self-contained HTML+CSS, {{field}} placeholders
  verdict.html

series/ is gitignored — each worker builds its own from its own user's references, so no two machines have the same set.

The hard rule for templates is no CSS animation. Remotion renders by seeking to each frame and screenshotting, so a CSS animation or transition freezes on whatever the first frame painted. Motion comes from the layer's enter value (fade, slide-up, slide-down, pop), which the composition drives with Remotion's own spring. Templates also can't carry <script> or any external URL; scripts/series.ts rejects a generation that does, and the composition strips scripts again at render time rather than trusting it.

Instagram's safe area

src/overlay/safeArea.ts holds where Instagram draws over a reel, as three rectangles rather than one inset margin — the action rail only runs down the lower half, so a flat "keep the right 260px clear" would flag the title and card as unsafe when nothing is near them.

| Zone | Area | |---|---| | top bar | full width, y 0-250 | | action rail | x 820-1080, y 1080-1700 | | caption | x 0-820, y 1500-1920 |

npx tsx scripts/check-safe-area.ts episodes/what-prints-00X.json measures the real overlay bounding boxes out of a render (same two-render diff as the legibility check) and reports anything intersecting a zone. It also flags elements outside the 3:4 centre crop that the profile grid uses for thumbnails.

Numbers are conservative — IG moves its chrome between app versions and notched phones differ from flat ones. If something looks wrong on a real phone, adjust the zones there and every check follows.

Does it read on a phone?

npx tsx scripts/check-legibility.ts episodes/what-prints-00X.json renders three frames twice — once whole, once with hideOverlays so only the background draws — diffs them to find the overlay pixels, and measures real contrast.

Text (the title) is scored on local contrast: strokes against what's immediately around them in the finished frame, so the dark halo counts. Panels (the code card, the difficulty pill) are scored on how well the opaque block separates from the footage, because their internal contrast is fixed by design. Thresholds are calibrated against the known-bad title, which measured 4.3:1 and would have passed a textbook WCAG bar; the fixed one measures 12.3:1.

new-episode.ts runs this automatically after placing the meter.

Notes

  • macOS blocks direct shell reads of ~/Desktop (TCC). All Desktop I/O goes through Finder AppleScript — that's why ingest/export use osascript.
  • Exports are silent; add trending audio in Instagram.
  • The title and code card are in fixed positions every episode (title centred 200px from the top, card centred at 86% width). The difficulty meter has a house position too — lower-left at (70, 1400) — and scripts/place-overlay.ts only moves it when the footage there is more than 25% busier than the calmest spot available. The comparison is relative because footage with Erin in frame scores high everywhere. Override by editing meterX/meterY.
  • New series (Interviewer, Games): add src/series/<name>/ with its own composition, register it in src/Root.tsx, same episode-JSON pattern.