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

webhanger

v1.0.8

Published

Component-as-a-Service platform — bundle, sign, and deliver UI components via edge CDN

Downloads

746

Readme

WebHanger

Component-as-a-Service (CaaS) — Bundle once. Encrypt with AES-256. Deliver via edge CDN. Load anywhere with zero code.

WebHanger is a secure, edge-delivered component distribution platform. Think of it as npm for UI components — but instead of installing packages, you deploy encrypted components to a CDN and load them into any website with a single HTML tag.


Packages

| Package | Install | Description | |---|---|---| | webhanger | npm install -g webhanger | CLI + Node.js library | | webhanger-front | npm install webhanger-front | Browser SDK |


Quick Start

# 1. Install CLI
npm install -g webhanger

# 2. Setup your project (provisions S3 + CloudFront automatically)
wh init

# 3. Deploy all components, build site, zip for upload — one command
wh ship ./components ./docs 1.0.0 ./dist

Load in any website — zero JS required:

<script src="https://unpkg.com/webhanger-front@latest/browser.min.js"></script>
<script>WebHangerFront.initialize("./wh-manifest.json");</script>

<wh-component name="navbar"></wh-component>
<wh-component name="hero"></wh-component>
<wh-component name="footer"></wh-component>

CLI Reference

wh init

Interactive project setup. Provisions infrastructure automatically.

wh init

Prompts:

  • Project name
  • Storage provider: s3 | r2 | minio | local
  • Database provider: firebase | supabase | mongodb
  • Credentials

For S3: automatically creates the bucket, configures CORS + versioning, spins up a CloudFront distribution. No AWS Console needed.

Optional: setup Cloudflare Edge Worker for token validation + geo routing at the edge.

Generates webhanger.config.json.


wh ship ⭐ The main command

Deploy + build + zip in one shot.

wh ship <components-dir> <site-dir> [version] [out-dir]
wh ship ./components ./docs 1.0.0 ./dist

What it does:

  1. Deploys all components (bundle → AES encrypt → upload → sign → register)
  2. Resolves dependency graph
  3. Writes wh-manifest.json (no sensitive data in HTML)
  4. Production builds the site (minify HTML, inline CSS/JS)
  5. Zips output for direct upload
🚀 [1/4] Deploying components...
  [email protected]...    ✅
  [email protected]...      ✅

🔍 [2/4] Resolving dependency graph...

🏗️  [3/4] Building ./docs → ./dist...
  index.html         4.2 kB

📦 [4/4] Zipping ./dist...

✅ Ship complete!
  Deploy zip: ./deploy.zip (12.4 kB)

Upload deploy.zip to Netlify, S3, cPanel, or any static host.


wh deploy

Deploy a single component.

wh deploy <component-dir> <name> <version>
wh deploy ./components/navbar navbar 1.0.0

Prompts for token (auto-generate or custom) and expiry (never or seconds).


wh graph-deploy

Deploy all components in a directory and resolve the dependency graph.

wh graph-deploy <components-dir> [version] [out-dir]
wh graph-deploy ./components 1.0.0 ./output

wh build

Production build — minifies HTML, inlines local CSS/JS.

wh build <src-dir> [out-dir]
wh build ./docs ./dist

wh zip

Zip a directory for deployment.

wh zip <src-dir> [out-file]
wh zip ./dist ./deploy.zip

wh analyze

Detect framework, styling approach, and CDN dependencies automatically.

wh analyze ./components/navbar
🔍 Component Analysis

Framework : vanilla
Styling   : tailwind
Imports   : gsap, axios
CDN Assets:
  [script] https://cdn.tailwindcss.com
  [script] https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js

wh convert

Convert a vanilla HTML/CSS/JS component to any framework.

wh convert <dir> <name> <target> [out-dir]
wh convert ./components/navbar navbar react ./output

Supported targets: react vue svelte next angular astro


wh access

Role-based access control for teams.

wh access grant          # generate API key with role
wh access revoke <key>   # revoke a key
wh access list           # list all keys

Roles:

| Role | deploy | read | delete | manage_access | |---|---|---|---|---| | owner | ✅ | ✅ | ✅ | ✅ | | admin | ✅ | ✅ | ✅ | ✅ | | deployer | ✅ | ✅ | ❌ | ❌ | | viewer | ❌ | ✅ | ❌ | ❌ |


wh edge-init

Setup Cloudflare Edge Worker for production-grade delivery.

wh edge-init
# then:
cd edge && wrangler deploy

Component Structure

components/
  navbar/
    index.html              ← markup
    style.css               ← styles
    script.js               ← behaviour
    webhanger.component.json ← assets + dependencies

webhanger.component.json

{
  "assets": [
    { "type": "script", "url": "https://cdn.tailwindcss.com" },
    { "type": "script", "url": "https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js" }
  ],
  "dependencies": ["[email protected]", "[email protected]"]
}

CDN assets are auto-detected by wh analyze and merged automatically on deploy.


Dependency Graph

npm-like dependency resolution for UI components.

[email protected]
  ├── [email protected]
  └── [email protected]
        └── [email protected]
  • Depth-first resolution
  • Circular dependency detection with full chain error
  • Deps load before parent component
  • Stored in Firestore per project
wh graph-deploy ./components 1.0.0 ./output

Programmatic:

import { resolveGraph } from "webhanger";
const graph = await resolveGraph(config.db, projectId, "dashboard", "1.0.0");
// Returns: [chart, navbar, statsbar, dashboard] — deps first

Security

AES-256-GCM Encryption

Every component chunk (HTML/CSS/JS) is encrypted before upload.

Key     = SHA-256(projectId + salt)
Payload = iv:tag:ciphertext  (base64)
Salts   = "::html" | "::css" | "::js"

HMAC-SHA256 Signed URLs

token = HMAC-SHA256(projectId:componentPath:expires, secretKey)

Integrity Check

SHA-256 hash of raw content stored in payload. Verified after decryption — detects tampering.

Domain Restriction

WebHangerFront.load(url, pid, token, 0, "[data-wh]", null, [], {
    allowedDomains: ["mysite.com", "app.io"]
});

Token Expiry

// Never expires
wh.deploy("./navbar", "navbar", "1.0.0");

// Expires in 24 hours
wh.deploy("./navbar", "navbar", "1.0.0", { expiresInSeconds: 86400 });

Manifest-based Delivery

Tokens, projectId, and CDN URLs never appear in HTML. Fetched at runtime from wh-manifest.json.


Edge Worker (Cloudflare Workers)

Runs at the edge before S3:

  • HMAC token validation
  • Version resolution (latest1.2.0 from KV)
  • Geo-based routing (India → ap-south-1, Europe → eu-west-1)
  • Rate limiting (100 req/min per IP)
wh init  # answer yes to edge worker setup
cd edge && wrangler deploy

Update cdn.url in webhanger.config.json to your worker URL — all requests now go through the edge.


Multi-CDN Failover

{
  "cdn": {
    "url": "https://primary.cloudfront.net",
    "fallbacks": [
      "https://fallback.r2.dev",
      "https://backup.b-cdn.net"
    ]
  }
}

SDK tries each URL in order. If primary fails, automatically falls back — zero code changes needed.


Browser SDK

Zero-code (recommended)

<script src="https://unpkg.com/webhanger-front@latest/browser.min.js"></script>
<script>WebHangerFront.initialize("./wh-manifest.json");</script>

<wh-component name="navbar"></wh-component>
<wh-component name="hero"></wh-component>
<wh-component name="footer" sandbox></wh-component>

Manual load

WebHangerFront.load(
    cdnUrl,      // string or array (multi-CDN)
    projectId,   // decrypt key
    token,       // HMAC token
    expires,     // unix timestamp, 0 = never
    selector,    // CSS selector, default "[data-wh]"
    onSignal,    // optional signal callback
    deps,        // optional pre-resolved deps array
    options      // optional options object
);

Lifecycle hooks

WebHangerFront.load(url, pid, token, 0, "[data-wh]", null, [], {
    beforeMount: ({ html }) => showSpinner(),
    afterMount:  ({ target }) => hideSpinner(),
    onError:     (err) => showFallback(err),
    sandbox:     true,                          // Shadow DOM isolation
    allowedDomains: ["mysite.com"]              // domain restriction
});

Signal callback

WebHangerFront.load(url, pid, token, 0, "[data-wh]", ({ stage, ...detail }) => {
    // stages: start → fetching → assets → deps → injecting → done | error
    console.log(stage, detail.time, detail.source);
});

Plugin system

WebHangerFront.use({
    install({ on, emit }) {
        on("load",   ({ time, source }) => analytics.track("load", { time, source }));
        on("error",  ({ message })      => errorTracker.capture(message));
        on("metric", ({ name, value })  => dashboard.update(name, value));
    }
});

Observability

WebHangerFront.on("load",   ({ time, source }) => console.log(time, source));
WebHangerFront.on("metric", ({ name, value })  => console.log(name, value));

console.log(WebHangerFront.metrics);
// { loads: 5, cacheHits: 3, errors: 0, totalTime: 420 }

Hard flush

await WebHangerFront.clearCache();
// Clears: localStorage, IndexedDB, SW caches, sessionStorage, unregisters SW

Caching

| Layer | Used for | |---|---| | localStorage | Components < 50KB | | IndexedDB | Components ≥ 50KB | | Service Worker | Offline fallback |

Stale-while-revalidate — returns cached version instantly, refreshes in background.


Node.js API

import { WebHanger } from "webhanger";
const wh = new WebHanger();

// Deploy
const result = await wh.deploy("./components/navbar", "navbar", "1.0.0", {
    expiresInSeconds: 86400,   // optional
    token: "custom-token",     // optional
    dependencies: ["[email protected]"]
});
// { cdnUrl, cdnUrls, token, expires, dependencies }

// Resolve
const comp = await wh.resolve("navbar", "1.0.0");

// Rotate token without redeploying
await wh.resign("navbar", "1.0.0", { expiresInSeconds: 3600 });

// Delete from storage
await wh.remove("navbar", "1.0.0");

// Get config
const config = wh.getConfig();

Named exports

import {
    bundle, encrypt, decrypt, integrityHash,
    signUrl, verifyToken, generateSecretKey,
    upload, remove,
    registerComponent, getComponent,
    deploy, resolveGraph,
    convert, analyzeComponent,
    build,
    grantAccess, revokeAccess, checkPermission, listAccess, generateApiKey,
    provisionBucket, provisionCloudFront,
    loadConfig
} from "webhanger";

Storage Providers

| Provider | Notes | |---|---| | s3 | AWS S3 — auto-provisions bucket + CloudFront | | r2 | Cloudflare R2 — zero egress fees | | minio | Self-hosted MinIO — S3-compatible | | local | Local disk — dev/testing only |

Database Providers

| Provider | Notes | |---|---| | firebase | Firebase Firestore — free tier, real-time | | supabase | Supabase Postgres — open source | | mongodb | MongoDB Atlas — flexible documents |


webhanger.config.json

{
  "project": "my-app",
  "projectId": "wh_1234567890",
  "secretKey": "64-char-hex-secret",
  "webHangerVersion": "1.0.0",
  "storage": {
    "provider": "s3",
    "accessKey": "...",
    "secretKey": "...",
    "bucket": "my-bucket",
    "region": "ap-south-1",
    "distributionId": "EXXXXX"
  },
  "cdn": {
    "url": "https://primary.cloudfront.net",
    "fallbacks": ["https://fallback.r2.dev"]
  },
  "db": {
    "provider": "firebase",
    "serviceAccountPath": "./firebase-service-account.json"
  }
}

Keep this file private. Never commit it. Add to .gitignore.


Architecture

Developer
  └── wh ship ./components ./docs
        ├── wh analyze    → detect Tailwind, GSAP, deps
        ├── wh bundle     → html + css + js → single payload
        ├── AES-256-GCM   → encrypt each chunk (SHA-256 key)
        ├── SHA-256 hash  → integrity fingerprint
        ├── S3 upload     → store encrypted payload
        ├── HMAC sign     → project-scoped signed URL
        ├── Firestore     → register metadata + dep graph
        ├── wh build      → minify HTML, inline assets
        └── wh zip        → deploy.zip ready for upload

Browser
  └── <wh-component name="navbar">
        ├── fetch wh-manifest.json
        ├── check token expiry
        ├── stale-while-revalidate cache
        ├── fetch from CloudFront (or Edge Worker)
        │     └── Edge: validate token + geo route + rate limit
        ├── multi-CDN failover if primary fails
        ├── load CDN assets (Tailwind, GSAP, etc.)
        ├── resolve + load dependency graph
        ├── AES-256-GCM decrypt in memory
        ├── SHA-256 integrity verify
        ├── domain restriction check
        ├── inject CSS → HTML → JS (or Shadow DOM)
        ├── fire lifecycle hooks
        └── emit metrics + plugin events

Real-World Use Cases

  • Enterprise micro-frontends — shared UI across 50+ apps, update once
  • Education platforms — push UI updates to all school sites instantly
  • Low-bandwidth regions — cache once, serve offline via Service Worker
  • Security platforms — inject warnings/banners dynamically across sites
  • White-label SaaS — per-tenant component customization

License

ISC