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 ./distLoad 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 initPrompts:
- 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 ./distWhat it does:
- Deploys all components (bundle → AES encrypt → upload → sign → register)
- Resolves dependency graph
- Writes
wh-manifest.json(no sensitive data in HTML) - Production builds the site (minify HTML, inline CSS/JS)
- 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.0Prompts 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 ./outputwh build
Production build — minifies HTML, inlines local CSS/JS.
wh build <src-dir> [out-dir]
wh build ./docs ./distwh zip
Zip a directory for deployment.
wh zip <src-dir> [out-file]
wh zip ./dist ./deploy.zipwh 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.jswh convert
Convert a vanilla HTML/CSS/JS component to any framework.
wh convert <dir> <name> <target> [out-dir]
wh convert ./components/navbar navbar react ./outputSupported 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 keysRoles:
| 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 deployComponent Structure
components/
navbar/
index.html ← markup
style.css ← styles
script.js ← behaviour
webhanger.component.json ← assets + dependencieswebhanger.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 ./outputProgrammatic:
import { resolveGraph } from "webhanger";
const graph = await resolveGraph(config.db, projectId, "dashboard", "1.0.0");
// Returns: [chart, navbar, statsbar, dashboard] — deps firstSecurity
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 (
latest→1.2.0from 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 deployUpdate 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 SWCaching
| 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 eventsReal-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
