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

@powforge/news-witness

v0.1.0

Published

DoI-weighted news credibility on Nostr. A story endorsed by 5 long-tenured humans outranks one flooded by 500 fresh bot accounts. Sybil-resistant news ranking with no central registry.

Readme

@powforge/news-witness

npm version license

Your community news feed is gameable by 50 bot accounts. Hacker News ranking, Reddit upvotes, content discovery on any open feed — one operator with fifty fresh accounts can flood the front page with whatever they want surfaced. Centralized identity verification (KYC, captcha, phone) makes the gate slightly tighter and leaks who you are.

@powforge/news-witness makes the credibility weight of a vouch a function of the witness's depth-of-identity score. A story endorsed by three long-tenured human witnesses outranks one flooded by five hundred fresh accounts. Established voices actually matter; bot farms don't.

No central registry. No KYC. Anyone can read the score formula and re-derive a witness's weight from their public Nostr history.

Install

npm install @powforge/news-witness

Quick start

const {
  submitStory,
  vouchStory,
  getCredibilityScore,
  getTopStories,
} = require('@powforge/news-witness');
const { generateSecretKey } = require('nostr-tools/pure');

const authorSk = generateSecretKey();
const witnessSk = generateSecretKey();
const relays = ['wss://relay.powforge.dev'];

// 1. Author submits a story. Returns a NIP-33 coordinate and a signed event.
const { storyId, event: storyEvent } = submitStory({
  url: 'https://example.com/some-article-worth-reading',
  title: 'Some article worth reading',
  topic: 'bitcoin',
  summary: 'A short note on why this matters.',
  secretKey: authorSk,
});
// Publish storyEvent to your relays however you normally would.

// 2. A witness vouches. Pass `relays` and the signed vouch will be published.
await vouchStory({
  storyId,
  secretKey: witnessSk,
  url: 'https://example.com/some-article-worth-reading',
  topic: 'bitcoin',
  rationale: 'Verified the source independently.',
  relays,
});

// 3. Anyone can compute the DoI-weighted credibility.
const score = await getCredibilityScore(storyId, relays);
console.log('Raw vouches:', score.rawVouches);
console.log('Weighted credibility:', score.weightedCredibility);
console.log('Top witnesses:', score.topWitnesses);

// 4. Or rank an entire topic by weighted credibility.
const top = await getTopStories('bitcoin', relays, { limit: 10 });
for (const s of top.stories) {
  console.log(s.weightedCredibility, '-', s.title, s.url);
}

API

submitStory({ url, title, topic?, summary?, secretKey?, authorPubkey? })

Builds a NIP-33 parameterized replaceable event (kind: 30178). The d-tag is a deterministic hash of the canonical URL, so the same URL by the same author always maps to the same coordinate (NIP-33 lets the author update title/summary later — the most recent event wins).

With secretKey it returns a signed event ready to publish. Without, you supply authorPubkey and get an unsigned template (useful for NIP-07 browser signers — you sign in the browser).

URL canonicalization: trailing slash, fragment, common tracking params (utm_*, fbclid, gclid, ref) are stripped; query params are sorted; host casing is normalized. So https://Example.com/x/?utm_source=tg#frag and https://example.com/x produce the same d-tag.

Returns { storyId, dTag, coordinate, event, canonicalUrl }. storyId and coordinate are the same kind:pubkey:dTag string — pass it everywhere else.

vouchStory({ storyId, secretKey?, witnessPubkey?, url?, topic?, rationale?, relays?, publishTimeout? })

Builds a kind: 1985 vouch event carrying an a-tag pointing at the story plus optional r (URL) and t (topic) tags so aggregators can dedup and topic-rank without re-fetching the story event. If relays is passed and the event is signed, also publishes it and returns publish acks per relay.

Returns { event, published? }.

getCredibilityScore(storyId, relays, opts?)

Fetches all vouches for storyId from relays, looks up each unique witness's DoI score (via @powforge/identity), and returns both raw vouch count and DoI-weighted credibility plus the top witnesses.

{
  storyId,
  authorPubkey,
  rawVouches: 23,
  weightedCredibility: 700,
  witnesses: [{ pubkey, weight }, ...],
  topWitnesses: [{ pubkey, weight }, ...],   // top 5 by default
  ignored: [],                                // any witness whose score lookup failed
}

One vouch per witness, latest wins. A witness who vouches twice (replays / accidental duplicates) only counts once.

Self-vouches are ignored. The story author cannot boost their own submission — that signal is meaningless.

Multi-relay duplicates are deduped. If two relays both return the same vouch event, it counts once.

getTopStories(topic, relays, opts?)

Pulls every story tagged with topic, scores each via getCredibilityScore, and returns them ranked by weightedCredibility (descending). NOT ranked by raw vouch count — that's the whole point.

Returns:

{
  topic: 'bitcoin',
  stories: [
    {
      storyId, url, title, authorPubkey,
      rawVouches: 3,
      weightedCredibility: 450,
      topWitnesses: [...],
    },
    ...
  ],
}

Pass opts.limit (default 20) to cap the result count.

Why DoI-weighted credibility?

A witness's depth-of-identity score is the sum of irreversible work they've done across four dimensions of public Nostr history:

| Dimension | Hard-to-fake signal | |-----------|---------------------| | Social | Bidirectional engagement with deep peers (not broadcast follower-count) | | Access | NIP-13 proof-of-work bits accumulated across all events | | Vouch | Inbound vouches from other deep identities, sqrt-diluted by voucher reach | | Economic | Lightning zaps from many distinct funded wallets |

A fresh sock puppet has none of these. Faking them is non-cheap: zaps cost real sats; vouches require coaxing real deep identities to vouch you; PoW costs CPU; bidirectional social ties require humans on the other end who actually engage.

Read the score formula and the audit trail at powforge.dev/explorer.

Adversary handling

  • 50 sock puppets vouching the same story → each contributes near-zero weight; combined credibility stays a tiny fraction of one real long-tenured witness's vouch.
  • Author self-vouches their own story → ignored entirely.
  • Witness vouches twice → only their most recent vouch counts.
  • Two relays return the same vouch event → deduped by event id.
  • Witness has never used Nostr → counts in raw vouch count but contributes zero weight.
  • Relay drops the story event → vouches still tally; only getTopStories ranking needs the story event for url/title metadata.
  • DoI score lookup fails for a witness → that witness lands in ignored, the rest of the tally still runs.

Composition

@powforge/news-witness is a pure helper. It doesn't run a server, doesn't store state, doesn't mint keys. It assumes a Nostr stack you already have and a relay (or several) you already trust. Drop it under any feed, ranker, or aggregator.

For richer demos, a managed credibility service, or a paywalled tally endpoint, see powforge.dev.

License

MIT.