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

@diklein/dkbezeler

v0.3.0

Published

Bake screenshots and screen recordings into a drawn device bezel at build time. The frame is generated from Apple's dimensional drawings for the phone that took the capture (every iPhone since the 12), matched by the capture's pixel size; no frame art is

Readme

DKBezeler

Bake screenshots and screen recordings into a device bezel at build time, extracted from the publishing pipeline behind diklein.com.

The bezel is drawn, not downloaded. DKBezeler carries the millimetre geometry of every iPhone since the 12 (transcribed from Apple's accessory dimensional drawings) and renders the frame for the phone that took your capture: the housing's continuous-curvature corner, the cover-glass inset, the bezel width, the Dynamic Island or notch, the buttons, all at the sheet's numbers. No frame art ships with the package and none is fetched.

A baked asset is a plain file. A framed still is one PNG, transparent outside the device, that sits on any background and travels through any image pipeline like every other image. A framed clip is a light version and a dark version of the mp4, with corners matched to your page backgrounds because H.264 has no alpha.

npx @diklein/dkbezeler "Screen Recording.mov" --out public/img
npx @diklein/dkbezeler onboarding.png --out public/img

Requirements: Node 18+. Stills need nothing else. Baking videos needs ffmpeg installed on your machine (brew install ffmpeg on macOS); the CLI checks and tells you if it is missing.

How it picks the phone

A capture's native pixel size names the phone that took it. 1206 × 2622 is an iPhone 18 Pro screen (and a 17 Pro's; the newest wins), 1260 × 2736 an iPhone Air, 1170 × 2532 an iPhone 14, and so on; dkbezeler devices prints the table. Where generations share a screen size (the 16, 15 Pro and 15 all shoot 1179 × 2556) the newest model wins, and --device <id> picks another. A capture a pixel or two off its native size, as some exports are, still matches, and loses those pixels to a whole-pixel crop rather than to resampling.

Every bake prints which phone it chose and why.

What the frame is made of

Apple publishes dimensional drawings of each iPhone for accessory makers. They dimension the housing, the cover glass, the display active area, the corner as sample points along its curve (it is not an arc), the Dynamic Island or notch, and every button. DKBezeler carries those numbers for twenty-six phones, from the iPhone 12 to the iPhone 17 family, and draws the frame from them with one generator: a superellipse fitted to Apple's corner samples, true parallel-curve insets for the glass and bezel, the buttons and Camera Control where the sheet puts them. The drawings themselves are Apple's and are not reproduced; only numbers are.

The frame is rendered at whatever scale makes the active area exactly your capture's pixels, so the capture is never resampled. A 1179-wide screenshot bakes into a 1324-wide PNG; the sidecar says so.

Baking

dkbezeler <input …> [options]

--device <id>      force a phone (see `dkbezeler devices`)
--out <dir>        output dir (default alongside the input)
--name <base>      output base name, used verbatim
--bg-light <hex>   video corner color, light version (default #ffffff)
--bg-dark <hex>    video corner color, dark version (default #0f1317)

Stills produce <base>-framed.png. Videos produce <base>-light.mp4 and <base>-dark.mp4 at a display-friendly width, -3x variants at the clip's native resolution, and matching .jpg posters, at the clip's own frame rate capped at 60.

Every bake also writes <base>-bezel.json: the framed file's pixel size, the active-area rect, the phone it matched, and the frame's corner geometry, so a page can size the box and shape a loading shimmer before the file arrives.

Video corners must match your page backgrounds. H.264 has no alpha, so the area outside the device is baked opaque, one version per theme. Corners that don't match the page read as tinted squares. Set your two backgrounds once and every video bake in the project uses them:

npx @diklein/dkbezeler theme --light "#ffffff" --dark "#0f1317"

--bg-light / --bg-dark override per bake, and a bake that falls back to the defaults says so loudly. One subtlety the defaults encode: near-black values decode about one unit darker through the YUV420 round trip, so set the dark value one step brighter than your CSS background (the default #0f1317 is what actually decodes to #0e1215).

dkbezeler check <input> exits 0 when a file looks like a phone capture (portrait, aspect between 1.95 and 2.35, at least 700px wide), for wiring into watchers and hooks.

Other devices

For a device the generator does not know (an iPad, a Watch, an Android phone), bring your own frame: any PNG of the device with a transparent screen cutout ringed by solid bezel. DKBezeler measures the cutout from the alpha channel and bakes into it exactly as it did before 0.2.

npx @diklein/dkbezeler measure my-frame.png --name "iPad Pro"
npx @diklein/dkbezeler capture.png --frame "iPad Pro"

Registered frames also serve as a fallback when a capture matches no known phone. Pull requests that add a phone's geometry are welcome; a device is a data entry.

Display components

npx shadcn add https://diklein.com/r/dk-bezeler.json

installs DKBezelImage and DKBezelVideo into components/dk-bezeler/. Import the stylesheet once, then pass the pixel sizes from the sidecar:

<DKBezelImage src="/img/onboarding-framed.png" width={1324} height={2700} alt="Onboarding" />
<DKBezelVideo base="/img/checkout" width={900} height={1836} alt="Checkout flow" />

DKBezelVideo renders both versions and shows exactly one with CSS, following the shadcn .dark convention with a prefers-color-scheme fallback. The hidden one is display:none, so it never downloads past its header or plays. Both components take a renderImage slot or className if you want your own image pipeline in the loop.

Why the bake is pixel-careful

The capture goes into the frame at its own pixels, cropped by whole pixels only when it must be, never scaled. Around the device's rounded corners the frame's outermost pixels are antialiased, and a naive composite lets the screen rectangle show through them. DKBezeler clips the screen to the real active-area path and, for videos, overlays a final exterior pass that fills everything outside the silhouette with the frame over your page colour, plus explicit frame-rate and colour-range handling (full-range phone recordings quietly shift colours on the web's limited-range decode path if you let them).

License

MIT. The device geometry is transcribed from Apple's public dimensional drawings; the drawings themselves are Apple's and are not included.