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

@dwk/webmention

v0.1.0-beta.2

Published

Webmention receiver (async verification queue) and sender.

Readme

@dwk/webmention

Webmention (W3C) receiver + sender. Endpoint package.

Part of the @dwk IndieWeb + Solid cohort. See the package specification for the full requirements.

The receiver validates source/target synchronously, returns 202 Accepted, and enqueues the pair for asynchronous link verification. The queue consumer fetches the source, confirms it links to the target, and persists (or removes) the mention in an inbox. The sender discovers a target's Webmention endpoint and notifies it on publish. Cloudflare specifics (Queue, D1) are confined to this package; the parsing and verification logic is pure and unit-tests without a Workers runtime.

Receiver

import { createWebmention } from "@dwk/webmention";

const webmention = createWebmention({ baseUrl: "https://example.com" });

// In your Worker's fetch handler, mount under any path prefix:
//   POST /webmention   (application/x-www-form-urlencoded: source, target)
return webmention(request, env, ctx);

createWebmention validates up front — both fields are syntactically valid http(s) URLs, sourcetarget, and target is a resource under this receiver's control (baseUrl's host, plus any allowedHosts). Invalid requests get 400 with a stable error code in the body; valid ones are enqueued and get 202. Other methods get 405. The handler fails loudly if the required WEBMENTION_QUEUE binding is missing.

Async verification (queue consumer)

import { createWebmentionQueueConsumer } from "@dwk/webmention";

const verify = createWebmentionQueueConsumer({ baseUrl: "https://example.com" });

export default {
  fetch: webmention,
  queue: verify, // bound to WEBMENTION_QUEUE
};

The consumer fetches each source, checks for a link to target, and upserts the verified mention into the inbox — or removes it when the source no longer links. Jobs that throw are retried.

Sender

import { sendWebmentions } from "@dwk/webmention";

// On publish, notify each outbound link's target:
const results = await sendWebmentions(myPostUrl, outboundLinks);

Endpoint discovery follows the spec: the HTTP Link header (rel=webmention) wins, then the first <link>/<a rel="webmention"> in document order, with relative URLs resolved against the (post-redirect) document URL — honoring a <base href> and ignoring endpoints inside HTML comments. The legacy http://webmention.org/ rel is also accepted. The sender refuses to POST a discovered endpoint that is not http(s).

Bindings (Env fragment)

| Binding | Type | Required | Purpose | | ------------------ | ------------ | -------- | ---------------------------------------- | | WEBMENTION_QUEUE | Queue | yes | Async verification of received mentions. | | WEBMENTION_INBOX | D1Database | yes* | Default inbox for verified mentions. |

* WEBMENTION_INBOX is optional when you pass a custom inbox in config — for example, to store mentions in the @dwk/solid-pod Durable Object when composed into a pod.

Config

| Field | Type | Default | Purpose | | -------------- | ------------ | -------------- | --------------------------------------------- | | baseUrl | string | — | Receiver origin; target must live under it. | | allowedHosts | string[] | [] | Extra controlled hostnames. | | inbox | InboxStore | D1 from env | Override the default inbox store. | | fetch | FetchLike | global fetch | Override fetch (verification/discovery). | | logger | Logger | noopLogger | Structured logs (see @dwk/log). | | metrics | Metrics | noopMetrics | Queryable counters (see @dwk/log). |

Observability

Logging and metrics are opt-in and injected (see @dwk/log), defaulting to no-ops. Both seams share one event vocabulary (WebmentionLogEvent), so a log line and its counter line up — SSRF blocks (by reason), receive accepted/rejected, verification outcomes (by links/status), queue retries (by reason), and send outcomes (by delivered/status):

import { consoleLogger, analyticsEngineMetrics } from "@dwk/log";
import { createWebmention } from "@dwk/webmention";

const webmention = createWebmention({
  baseUrl: "https://example.com",
  logger: consoleLogger({ minLevel: "info" }),
  // env.WEBMENTION_METRICS is an AnalyticsEngineDataset binding.
  metrics: analyticsEngineMetrics(env.WEBMENTION_METRICS),
});

Both honor the redaction policy: only sanitized hosts, status, reason codes, booleans, and counts — never tokens, bodies, or full URLs.

Federation handoff (documented config, not core code)

To bridge to the fediverse, emit h-card / h-entry markup on your published pages and include Bridgy Fed (https://fed.brid.gy/) as one of the outbound targets you pass to sendWebmentions. Bridgy Fed discovers your page's Webmention endpoint and handles the ActivityPub translation; no special code in this package is required.

Conformance

The discovery and verification logic is unit-tested against the webmention.rocks discovery cases — including exact rel matching (not naïve substring), endpoints hidden in HTML comments, escaped HTML, empty vs. missing href, <base href> resolution, query-string endpoints, and multiple/ordered endpoint advertisements.

Scope

  • Verification is link-level: the source document must contain an href/src resolving to the target. Full Microformats2 extraction (author, content, mention type) is intentionally out of scope to keep the Worker bundle within the runtime budget; the inbox records source, target, and the verification time.

License

ISC