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

wompo

v2.0.2

Published

Wompo is a performant React-like JS library to create Web-Components that are re-usable, shareable, and beginner-friendly.

Downloads

652

Readme

Fast, React-like, Web-Components.

Published on npm

Documentation

Check the full documentation for Wompo at wompo.dev.

ko-fi

Quick Example: Counter

Creating a custom Counter component is very easy with Wompo, and works exactly like React!

import { defineWompo, html } from 'wompo';

export default function CounterComponent({ styles: s }) {
  const [count, setCount] = useState(0);
  const inc = () => setCount(count + 1);
  return html`<button class=${s.button} @click=${inc}>
    Current value: ${count}
  </button>`;
}

CounterComponent.css = `
  .button {
    border-radius: 10px;
    background-color: #573ef6;
    color: #fff;
    padding: 10px 20px;
    border: none;
  }
`

defineWompo(CounterComponent);

Then, you can simply render it in you HTML:

<counter-component></counter-component>
<!-- Will render: <button>Current value: 0!</button> -->

Server-Side Rendering

Wompo ships a string-based SSR engine and a client-side hydration runtime. The same defineWompo components render on the server, hydrate selectively on the client (islands-first), and stream suspended content out of order.

Render to string

import { renderToString } from 'wompo/ssr';
import Counter from './counter.js';

const { html, headTags, css, islands } = await renderToString(Counter, { start: 5 });
// html:    `<counter-component ...>…</counter-component>`
// headTags: inline `<style>` block with the CSS of every component used (dedup'd)
// css:     Map<componentName, css> for extraction into separate files
// islands: per-component hydration metadata (name, mode, doc-order index)

Streaming Suspense

import { renderToStream, BOUNDARY_RUNTIME_SCRIPT } from 'wompo/ssr';

const stream = renderToStream(Page, props);
// → ReadableStream<Uint8Array>:
//   1. <script>__wompoR=…</script> + <style> + shell with <wompo-boundary id="Bn">FALLBACK</…>
//   2. for each resolved boundary (in completion order):
//      <template data-wompo-resolve="Bn">…real content…</template>
//      <script>self.__wompoR("Bn")</script>

The runtime script (~140 bytes) swaps each <template data-wompo-resolve> into its <wompo-boundary> placeholder as chunks arrive.

Islands & hydration

A component becomes an island by passing island: 'load' | 'idle' | 'visible' to defineWompo, or by writing client:load|idle|visible on the call site (the attribute wins). The server emits data-wompo-island plus a <template data-wompo-props> carrying its initial props serialized with a minimal devalue-style codec (supports Date, Map, Set, BigInt, cycles, undefined, NaN, Infinity).

// Page.js (server)
defineWompo(MyCounter, { name: 'my-counter', island: 'visible' });
// Page.client.js (loaded by the document shell)
import { hydrate } from 'wompo/hydrate';
hydrate(document);
// Each [data-wompo-island] is hydrated per its mode:
//   load    → immediately
//   idle    → requestIdleCallback (fallback setTimeout)
//   visible → IntersectionObserver with rootMargin: 200px

On a structural mismatch between the SSR'd DOM and what the component would clone, hydration falls back to a destructive re-render with a console.warn.

Server Actions

import { defineAction } from 'wompo/ssr';

export const addItem = defineAction(async (name) => {
  // …hit a DB, queue, etc.
  return { id: 1, name };
});

defineAction returns the function as-is on the server. When the wrapped reference is passed through an island's props payload, the client receives a {__wompoAction: '<id>'} marker and substitutes a fetch proxy hitting your framework's /_action/:id endpoint. The companion wompro framework wires this endpoint up for you.

Build / link

npm run build      # tsc + esbuild → dist/

dist/wompo.js (core), dist/ssr/index.js (SSR + actions + stream), and dist/wompo/hydrate.js (client) are the published subpaths.