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

@useknockout/react

v0.5.0

Published

React hooks for useknockout — state-of-the-art background removal API.

Downloads

617

Readme

🥊 @useknockout/react

React hooks for useknockout — state-of-the-art background removal API.

MIT License npm version npm downloads GitHub stars React TypeScript Zero deps

Install · Quick Start · Hooks · Provider · API repo

Drop-in hooks. Works with Next, Remix, Vite. Zero deps.


  • Drop-in hooksuseRemoveBackground, useReplaceBackground
  • Zero runtime dependencies — uses global fetch + FormData
  • Works everywhere React does — Next.js, Remix, Vite, CRA, React Native Web
  • First-class TypeScript — full types, no anys
  • MIT licensed

Install

npm install @useknockout/react
# or
pnpm add @useknockout/react
# or
yarn add @useknockout/react

Requires React 18+.

Quick start

1. Basic usage (no provider needed)

import { useRemoveBackground } from "@useknockout/react";

export function BackgroundRemover() {
  const { remove, dataUrl, isLoading, error } = useRemoveBackground({
    token: "kno_public_beta_4d7e9f1a3c5b2e8d6a9f7c1b3e5d8a2f",
  });

  return (
    <div>
      <input
        type="file"
        accept="image/*"
        onChange={(e) => e.target.files?.[0] && remove(e.target.files[0])}
      />
      {isLoading && <p>Processing...</p>}
      {error && <p>Error: {error.message}</p>}
      {dataUrl && <img src={dataUrl} alt="result" />}
    </div>
  );
}

2. Recommended — provider at the root

// app/layout.tsx  (Next.js App Router)
import { KnockoutProvider } from "@useknockout/react";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <KnockoutProvider token={process.env.NEXT_PUBLIC_KNOCKOUT_TOKEN}>
          {children}
        </KnockoutProvider>
      </body>
    </html>
  );
}

Then anywhere below:

import { useRemoveBackground, useReplaceBackground } from "@useknockout/react";

function RemoveDemo() {
  const { remove, dataUrl, isLoading } = useRemoveBackground();
  // ...
}

function ReplaceDemo() {
  const { replaceBackground, dataUrl, isLoading } = useReplaceBackground();

  const onFile = async (file: File) => {
    await replaceBackground({ file, bgColor: "#FF5733", format: "jpg" });
  };
  // ...
}

⚠️ Security tip: In production, proxy API calls through your own server so your token never reaches the browser. The token option here is meant for private apps, prototyping, or environments where the token is already scoped/rate-limited.


Hooks

useRemoveBackground(options?)

Removes the background from a file and returns a transparent PNG/WebP.

Options (extends KnockoutConfig):

| Option | Type | Default | Description | |---|---|---|---| | format | "png" \| "webp" | "png" | Output format (alpha included). |

Returns:

| Field | Type | Description | |---|---|---| | remove | (file: File \| Blob) => Promise<Blob> | Trigger the request. | | data | Blob \| null | Most recent result. | | dataUrl | string \| null | Object URL (auto-revoked on next call / unmount). | | isLoading | boolean | In-flight state. | | error | Error \| KnockoutError \| null | Last error. | | reset | () => void | Clear state. |

useReplaceBackground(options?)

Removes the background and composites the subject onto a new background.

Options (extends KnockoutConfig):

| Option | Type | Default | Description | |---|---|---|---| | format | "png" \| "webp" \| "jpg" | "png" | Output format. jpg = smallest file. |

Returns:

| Field | Type | Description | |---|---|---| | replaceBackground | (input) => Promise<Blob> | Trigger the request. | | data, dataUrl, isLoading, error, reset | — | Same as useRemoveBackground. |

input shape:

| Field | Type | Description | |---|---|---| | file | File \| Blob | Foreground image. | | bgColor | string? | Hex color like "#FF5733". Default "#FFFFFF". Ignored if bgUrl is set. | | bgUrl | string? | Remote URL of a background image. | | format | "png" \| "webp" \| "jpg"? | Per-call override. |

useHeadshot(options?) — v0.4.0

Studio-quality professional headshot — background removed, neutral studio backdrop, optional drop shadow, smart bust crop.

const { headshot, dataUrl, isLoading } = useHeadshot();

await headshot({ file, bgColor: "#f5f5f5", crop: "bust" });

input shape: { file, bgColor?, addShadow?, crop?: "bust" | "head" | "full", format? }

usePreview(options?) — v0.4.0

Cheap, fast low-res preview (~1.5s, 512px max). Use for thumbnail UI before triggering full-res request.

const { preview, dataUrl, isLoading } = usePreview();

await preview({ file, maxSize: 512, watermark: false });

useStats(options?) — v0.4.0

Public usage stats — total images processed, last 24h, 7-day trend. No auth required.

const { stats, data, isLoading } = useStats();

useEffect(() => { stats(); }, []);
// data → { total, last_24h, last_7d }

useUpscale(options?) — v0.6.0

Swin2SR / Real-ESRGAN x2/x4 super-resolution. Defaults to Swin2SR (SwinV2 Transformer) — sharper detail and natural texture on real photos. Pass model: "realesrgan" for the legacy backend (better on anime / illustrations).

const { upscale, dataUrl, isLoading } = useUpscale();

await upscale({ file, scale: 4 });
await upscale({ file, scale: 4, model: "realesrgan" });

input shape: { file, scale?: 2 | 4, model?: "swin2sr" | "realesrgan", format?: "png" | "webp" | "jpg" }

useFaceRestore(options?) — v0.5.0

GFPGAN v1.4 face restoration. Restores blurred/compressed faces while preserving identity. Multi-face safe; background also upscaled.

const { faceRestore, dataUrl, isLoading } = useFaceRestore();

await faceRestore({ file });

input shape: { file, format?: "png" | "webp" | "jpg" }

useStudioShot(options?) — v0.3.0

E-commerce product preset — cutout, centered on a canvas, optional drop shadow, standardized aspect. Pass transparent: true for a transparent-background PNG.

const { generate, dataUrl, isLoading } = useStudioShot();

await generate(file, { aspect: "1:1" });
await generate(file, { transparent: true }); // transparent PNG
await generate(file, { enhance: true });     // brightness + saturation lift

generate(file, options?){ bgColor?, aspect?, padding?, shadow?, transparent?, enhance?, enhanceStrength?, format?: "png" | "webp" | "jpg" }

useSmartCrop(options?) — v0.3.0

Auto-crop to the subject bounding box + padding. Transparent cutout by default.

const { generate, dataUrl, isLoading } = useSmartCrop();
await generate(file, { padding: 32 });

generate(file, options?){ padding?, transparent?, format?: "png" | "webp" | "jpg" }

useSticker(options?) — v0.3.0

Sticker — thick contour outline around the subject on a transparent bg (iMessage / WhatsApp style).

const { generate, dataUrl, isLoading } = useSticker();
await generate(file, { strokeWidth: 24 });

generate(file, options?){ strokeColor?, strokeWidth?, format?: "png" | "webp" }

useOutline(options?) — v0.3.0

Outline — thin stroke around the subject on a transparent bg.

const { generate, dataUrl, isLoading } = useOutline();
await generate(file, { outlineColor: "#000000", outlineWidth: 4 });

generate(file, options?){ outlineColor?, outlineWidth?, format?: "png" | "webp" }

useCompare(options?) — v0.3.0

Before/after side-by-side — original on the left, cutout (on a checkerboard) on the right. Great for marketing screenshots.

const { generate, dataUrl, isLoading } = useCompare();
await generate(file);

generate(file, options?){ format?: "png" | "webp" }

useMask(options?) — v0.3.0

Black/white subject mask for your own compositing pipeline.

const { generate, dataUrl, isLoading } = useMask();
await generate(file);

generate(file, options?){ format?: "png" | "webp" }

All hooks return { data, dataUrl, isLoading, error, reset } plus the trigger function above.


KnockoutProvider

Provide token, baseUrl, timeoutMs, or a custom fetch to all child hooks.

<KnockoutProvider
  token="kno_..."
  baseUrl="https://useknockout--api.modal.run"
  timeoutMs={60_000}
>
  <App />
</KnockoutProvider>

Per-hook options merge over provider values — override just what you need at the call site.


KnockoutConfig

| Option | Type | Default | Description | |---|---|---|---| | token | string | — | Bearer token. Required when the API has auth enabled. | | baseUrl | string | https://useknockout--api.modal.run | Override for self-hosted deployments. | | timeoutMs | number | 60_000 | Per-request timeout. | | fetch | typeof fetch | globalThis.fetch | Custom fetch (SSR / edge runtimes / polyfills). |


KnockoutError

Thrown on any non-2xx response. Fields:

  • status — HTTP status code
  • code"auth" | "rate_limit" | "bad_request" | "payload_too_large" | "server" | "unknown"
  • body — raw response body string
import { KnockoutError } from "@useknockout/react";

const { remove, error } = useRemoveBackground();

if (error instanceof KnockoutError && error.code === "payload_too_large") {
  // prompt the user to pick a smaller image
}

Complete drag-and-drop example

import { useState } from "react";
import { useRemoveBackground } from "@useknockout/react";

export function RemoveBgDropzone() {
  const [isDragging, setIsDragging] = useState(false);
  const { remove, dataUrl, isLoading, error, reset } = useRemoveBackground();

  const onFiles = async (files: FileList | null) => {
    const file = files?.[0];
    if (!file) return;
    await remove(file);
  };

  return (
    <div
      onDragOver={(e) => { e.preventDefault(); setIsDragging(true); }}
      onDragLeave={() => setIsDragging(false)}
      onDrop={(e) => { e.preventDefault(); setIsDragging(false); onFiles(e.dataTransfer.files); }}
      style={{
        border: `2px dashed ${isDragging ? "#007BFF" : "#ccc"}`,
        borderRadius: 12,
        padding: 48,
        textAlign: "center",
      }}
    >
      {isLoading && <p>Removing background…</p>}
      {error && <p style={{ color: "crimson" }}>{error.message}</p>}
      {!dataUrl && !isLoading && (
        <label>
          <p>Drop an image or click to pick one</p>
          <input
            type="file"
            accept="image/*"
            onChange={(e) => onFiles(e.target.files)}
            hidden
          />
        </label>
      )}
      {dataUrl && (
        <div>
          <img src={dataUrl} alt="cutout" style={{ maxWidth: "100%" }} />
          <button onClick={reset}>Try another</button>
        </div>
      )}
    </div>
  );
}

Framework notes

  • Next.js App Router — the provider and hooks work in any "use client" component. Keep NEXT_PUBLIC_KNOCKOUT_TOKEN in env for prototyping, or proxy through a route handler in production.
  • React Server Components — do not call these hooks in RSCs. They require a browser runtime (fetch, FormData, URL.createObjectURL).
  • React Native — use @useknockout/node instead; RN's FormData semantics differ enough that this package targets web only.

License

MIT — see LICENSE.