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

@manyducks.co/dolla

v4.5.1

Published

A fast, batteries-included JavaScript framework with a React-inspired API and the power of signals.

Readme

💲 @manyducks.co/dolla

bundle size bundle size

Dolla is a research framework for trying out ideas. The goal is to create a full-featured framework that, first and foremost, provides the best developer experience possible out of the box. Low resource usage and small code size are secondary objectives.

Dolla is based on experience working with React, Angular, Vue, Svelte and Flutter, and is an amalgamation of all the things I liked and ways I wish things worked, all rolled into a single framework for making web-based SPAs. It's more than a toy and less than a production-ready workhorse. It's a labor of love. Use at your own joy and peril.

Features

  • 🚥 Signals — pinpoint reactive updates with no virtual DOM
  • 📦 Views — reusable UI components that run once and update via signals
  • 💾 Stores — share state across components via the context tree
  • 🧩 Context inheritance — prototypal context chain for stores, debug, and arbitrary data
  • 🎨 CSS-in-JS — scoped class names, reactive CSS variables, template composition
  • 🔀 Router — nested routes, lazy loading, guards, preload, error views
  • 🌍 i18n — pluralization, formatting, async translation loading
  • 📡 HTTP client — middleware pipeline, typed responses
  • 📜 Virtual list — recycled DOM pool, infinite scroll, sticky headers
  • Temporal helpersdebounce and throttle
  • 🐛 Debug logging — colored, taggable, filterable
  • 🔥 HMR — hot module replacement via Vite plugin

Installation

npm install @manyducks.co/dolla

Quick start

A counter with reactive state, lifecycle hooks, and conditional rendering:

import { html, createAtom, createRoot, compose, onEffect, showIf } from "@manyducks.co/dolla";

function Counter() {
  const [count, setCount] = createAtom(0);
  const isEven = compose(() => count() % 2 === 0);

  onEffect(this, () => console.log("count:", count()));

  return html`
    <div>
      <p>Count: ${count}</p>
      <button onClick=${() => setCount((c) => c + 1)}>+</button>
      <button onClick=${() => setCount((c) => c - 1)}>-</button>
      ${showIf(isEven, html`<p>That's even!</p>`)}
    </div>
  `;
}

createRoot(document.body).mount(Counter);

Documentation

| Area | Description | | --------------------------------------- | ---------------------------------------------------------------- | | Reactivity | Signals — atoms, compose, effects, batch, peek | | Effects | Auto-tracking vs deps-array, lifecycle-scoped effects | | Components | Views, Stores, control flow helpers, context, portals | | CSS | CSS-in-JS with scoped classes, reactive variables, composition | | Refs | Direct DOM access with createRef | | Hooks | Lifecycle, context, store, and debug hooks reference | | Utilities | debounce, throttle, subscribe, batch, peek, sleep | | HMR | Hot module replacement with Vite | | Router | Client-side SPA routing with nested routes, guards, lazy loading | | Translate | i18n with pluralization, formatting, async loading | | HTTP Client | Middleware-based HTTP client | | Virtual List | High-performance virtual scrolling with sticky headers | | JSX | Using JSX with Dolla |

Sub-packages

Dolla is modular. Import only what you need:

| Import path | Size | Includes | | ------------------------------- | -------------- | ------------------------------------------------------------- | | @manyducks.co/dolla | ~11 KB gzipped | Core — signals, markup, components, lifecycle, CSS, utilities | | @manyducks.co/dolla/router | +~4.7 KB | Client-side router with nested routes | | @manyducks.co/dolla/translate | +~1.2 KB | i18n translation system | | @manyducks.co/dolla/http | +~1.2 KB | Middleware-based HTTP client | | @manyducks.co/dolla/virtual | +~0 KB (lazy) | Virtual scrolling list |

Stores

A Store shares state across views in the same subtree. Parent calls addStore to create it, children call getStore to retrieve it.

import { html, createAtom, createRoot, compose, addStore, getStore, showIf, forEach } from "@manyducks.co/dolla";

function TodoStore() {
  const [items, setItems] = createAtom([
    { id: 1, text: "Learn Dolla", done: false },
    { id: 2, text: "Build something", done: false },
  ]);
  const addItem = (text) => setItems((list) => [...list, { id: Date.now(), text, done: false }]);
  const toggle = (id) => setItems((list) => list.map((i) => (i.id === id ? { ...i, done: !i.done } : i)));
  return { items, addItem, toggle };
}

function App() {
  addStore(this, TodoStore);
  return html`<${TodoList} />`;
}

function TodoList() {
  const store = getStore(this, TodoStore);

  return html`
    <p>${compose(() => store.items().filter((i) => !i.done).length)} remaining</p>
    <ul>
      ${forEach(
        store.items,
        (item) => item.id,
        (item) => html`
          <li onClick=${() => store.toggle(item().id)}>${showIf(() => item().done, "✅")} ${() => item().text}</li>
        `,
      )}
    </ul>
    <button onClick=${() => store.addItem("New task")}>Add</button>
  `;
}

createRoot(document.body).mount(App);

A few points about how Dolla works:

  • The component function runs once (no re-renders). All runtime changes happen through atoms.
  • Pass getters, not values. Writing ${count} in a template stays reactive; writing ${count()} is evaluated once and won't update.
  • DOM updates are batched as a microtask. Use batch to group signal changes and trigger a single update.
  • Getters are tracked inside compose and createEffect/onEffect. Use peek to read without tracking.

Derived state

Only a single number changes below, but three values update in sync — compose chains automatically track their dependencies.

import { html, createRoot, createAtom, compose } from "@manyducks.co/dolla";

function Converter() {
  const [celsius, setCelsius] = createAtom(0);

  const fahrenheit = compose(() => (celsius() * 9) / 5 + 32);

  const description = compose(() => {
    const f = fahrenheit();
    if (f <= 32) return "Freezing ❄️";
    if (f >= 90) return "Hot! 🔥";
    return "Moderate 🌤️";
  });

  return html`
    <div>
      <input type="number" value=${celsius} oninput=${(e) => setCelsius(e.target.valueAsNumber)} />
      <p>Celsius: ${celsius}°C</p>
      <p>Fahrenheit: ${fahrenheit}°F</p>
      <p>Condition: ${description}</p>
    </div>
  `;
}

createRoot(document.body).mount(Converter);

JSX

Set jsxImportSource in your tsconfig.json:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@manyducks.co/dolla"
  }
}

Then write components with JSX instead of html\...``:

function Hello({ name }) {
  return <p>Hello, {name}!</p>;
}

No build step

You can skip the bundler entirely and use html tagged templates. They work directly in the browser.


🦆 That's a lot of ducks.