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

kubbe

v0.2.0

Published

A tiny React library that normalizes logo visuals — like stacking wooden blocks neatly

Readme

🌲 Kubbe

A tiny React library that makes logos look good together — like stacking wooden blocks neatly.

The Problem

Real-world logos are messy. Some have padding, some don't. Some are dense and blocky, others are thin and airy. Put them in a row and they look chaotic.

Kubbe fixes this automatically.

Getting Started

npm install kubbe
import { KubbeStrip } from "kubbe";

function LogoStrip() {
  return (
    <KubbeStrip
      logos={["/logos/acme.svg", "/logos/globex.svg", "/logos/initech.svg"]}
    />
  );
}

That's it! Kubbe will analyze each logo and normalize them to look visually balanced.

Options

gap

Space between logos. Default is 16.

<KubbeStrip logos={logos} gap={24} />

baseSize

How big the logos should be, in pixels. Default is 48.

<KubbeStrip logos={logos} baseSize={64} />

densityAware and densityFactor

Kubbe measures the "visual weight" of each logo. Dense, solid logos get scaled down. Light, thin logos get scaled up. This is on by default.

  • densityAware={false} — Turn it off
  • densityFactor — How strong the effect is (0 = off, 0.5 = default, 1 = strong)
// Stronger density compensation
<KubbeStrip logos={logos} densityFactor={0.8} />

// Turn it off
<KubbeStrip logos={logos} densityAware={false} />

scaleFactor

How to handle logos with different shapes (wide vs tall). Default is 0.5.

Imagine you have two logos:

  • Logo A: wide (200×100)
  • Logo B: tall (100×200)

scaleFactor = 0 → Same width for all logos

  • Logo A: 48×24 (short)
  • Logo B: 48×96 (very tall)

scaleFactor = 1 → Same height for all logos

  • Logo A: 96×48 (very wide)
  • Logo B: 24×48 (narrow)

scaleFactor = 0.5 → Balanced (default)

  • Neither gets too wide nor too tall
  • Looks most natural
<KubbeStrip logos={logos} scaleFactor={0.5} />

alignBy

How to align logos. Default is "bounds".

  • "bounds" — Align by geometric center (bounding box)
  • "visual-center" — Align by visual weight center (accounts for asymmetric logos)
  • "visual-center-x" — Align by visual weight center horizontally only
  • "visual-center-y" — Align by visual weight center vertically only
<KubbeStrip logos={logos} alignBy="visual-center" />

cropToContent

When enabled, logos are cropped to their content bounds and returned as base64 images. This removes any whitespace/padding baked into the original image files. Default is false.

<KubbeStrip logos={logos} cropToContent />

Using the Hook

For custom layouts, use the useKubbe hook directly:

import { useKubbe } from "kubbe";

function CustomGrid() {
  const { isLoading, normalizedLogos } = useKubbe({
    logos: ["/logo1.svg", "/logo2.svg"],
  });

  if (isLoading) return <div>Loading...</div>;

  return (
    <div className="grid">
      {normalizedLogos.map((logo) => (
        <img
          key={logo.src}
          src={logo.src}
          width={logo.normalizedWidth}
          height={logo.normalizedHeight}
        />
      ))}
    </div>
  );
}

getVisualCenterTransform

When using the hook, you can apply visual center alignment with the getVisualCenterTransform helper:

import { useKubbe, getVisualCenterTransform } from "kubbe";

function CustomGrid() {
  const { normalizedLogos } = useKubbe({ logos });

  return (
    <div className="grid">
      {normalizedLogos.map((logo) => (
        <img
          key={logo.src}
          src={logo.src}
          width={logo.normalizedWidth}
          height={logo.normalizedHeight}
          style={{ transform: getVisualCenterTransform(logo, "visual-center") }}
        />
      ))}
    </div>
  );
}

Custom Image Component

Use with Next.js Image or any custom component:

import Image from "next/image";

<KubbeStrip
  logos={logos}
  renderImage={(props) => (
    <Image
      src={props.src}
      alt={props.alt}
      width={props.width}
      height={props.height}
    />
  )}
/>;

How It Works

  1. Content Detection — Analyzes each logo to find its true boundaries, ignoring whitespace and padding
  2. Aspect Ratio Normalization — Scales logos based on their shape using the scaleFactor
  3. Density Compensation — Measures pixel density and adjusts size so dense logos don't overpower light ones

All processing happens client-side using canvas. No AI, fully deterministic.

Development

bun install
bun test
bun run storybook

License

MIT