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

bitwrench

v2.0.18

Published

A library for javascript UI functions.

Readme

bitwrench.js

License NPM version CI

bitwrench

Bitwrench builds UI from plain JavaScript objects — one format for components, styling, state, and server rendering, with no build step and zero dependencies. In bitwrench structure, styles, and state (including client/server) are rendered and managed as javascript objects.

// Describe UI as a JavaScript object (a "TACO")
var page = {
  t: 'div', a: { class: 'card' },
  c: [
    { t: 'h2', c: 'Hello' },
    { t: 'p',  c: 'UI as native JavaScript objects.' },
    bw.makeButton({ text: 'Click me', variant: 'primary', onclick: fn })
  ]
};

bw.DOM('#app', page);          // → live DOM
bw.html(page);                 // → HTML string (Node.js, emails, SSR)

Each object has four keys: t (tag), a (attributes), c (content), o (options for state/lifecycle). Nest them, loop them, compose them — it's just JavaScript.

Hero example output

Why bitwrench?

One file, everywhere. At ~39KB gzipped with zero dependencies, bitwrench runs on anything with a browser — phones, tablets, Raspberry Pi, even ESP32 microcontrollers. The device serves a single HTML page and pushes data as JSON; bitwrench handles all rendering, styling, and state on the client. No Node.js, no build step, no internet connection required.

Structure, styling, state, and server rendering are all handled as JavaScript objects:

  • No build toolchain — works with a <script> tag
  • 50+ ready-made components — buttons, tables, modals, forms, charts, toasts — one make*() call each, returns a composable TACO
  • CSS from JavaScriptbw.css() generates stylesheets, bw.s() composes inline styles, bw.loadStyles() or bw.makeStyles() derives a complete theme from 2 seed colors
  • Reactive statebw.component() provides .get()/.set() with ${template} bindings; bw.pub()/bw.sub() for cross-component messaging
  • Dual rendering — same object renders to live DOM (bw.DOM()) or HTML string (bw.html()) for SSR, emails, or static sites
  • Server-driven UI — push UI updates from any backend (Python, C, Rust, Go) over SSE; client.screenshot() captures the page back as PNG/JPEG
  • CLIbwcli converts Markdown, HTML, and JSON to styled standalone pages
  • Utilities — color interpolation, random data, lorem ipsum, cookies, URL params, file I/O

Coming from other Frameworks

Bitwrench uses JavaScript equivalents for most forms of front-end development. Here is a quick mapping (see the docs and Thinking in Bitwrench for more details).

| You're using | For | Bitwrench equivalent | |---|---|---| | React / Vue / Svelte | Components + reactivity | {t, a, c, o} objects + bw.component() | | JSX / templates | Markup-in-JS | Native JS objects — no compiler | | Tailwind / CSS-in-JS | Styling | bw.css(), bw.s() style composition | | Sass / PostCSS | CSS generation | bw.css() from JS objects (supports @media, @keyframes) | | ThemeProvider / CSS vars | Theming | bw.loadStyles() / bw.makeStyles() from 2 seed colors | | Streamlit / Gradio | Server-driven UI | bwserve SSE — from any language (Python, Go, C, Rust) | | Redux / Zustand / Pinia | State management | bw.component() .get()/.set() + bw.pub()/sub() | | Vite / webpack / Babel | Build tooling | Not needed — open the HTML file |

See the Framework Translation Table for side-by-side code comparisons across 22 operations.

Installation

npm install bitwrench
// ES module
import bw from 'bitwrench';

// CommonJS
const bw = require('bitwrench');

Or include directly in a page:

<script src="https://cdn.jsdelivr.net/npm/bitwrench/dist/bitwrench.umd.min.js"></script>

Getting Started

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://cdn.jsdelivr.net/npm/bitwrench/dist/bitwrench.umd.min.js"></script>
</head>
<body>
  <div id="app"></div>
  <script>
    bw.loadStyles();

    bw.DOM('#app', {
      t: 'div', a: { class: 'bw-container' },
      c: [
        { t: 'h1', c: 'My App' },
        bw.makeCard({
          title: 'Welcome',
          content: 'Built with plain JavaScript objects.'
        }),
        bw.makeButton({
          text: 'Click me',
          variant: 'primary',
          onclick: function() { alert('Hello!'); }
        })
      ]
    });
  </script>
</body>
</html>

Adding State

Wrap any TACO in bw.component() to get a reactive component with .get(), .set(), and template bindings:

var counter = bw.component({
  t: 'div', c: [
    { t: 'span', c: 'Count: ${count}' },
    { t: 'button', c: '+1', a: {
      onclick: function() { counter.set('count', counter.get('count') + 1); }
    }}
  ],
  o: {
    state: { count: 0 },
    methods: {
      reset: function(comp) { comp.set('count', 0); }
    }
  }
});

bw.DOM('#app', counter);
counter.set('count', 42);   // DOM updates automatically
counter.reset();             // methods from o.methods are callable on the handle

Important: event handlers go in a: { onclick: fn }, not in o.mounted. Handlers attached via addEventListener in o.mounted are silently lost when a component re-renders. Always use onclick/onchange/etc. inside a: — bitwrench re-attaches them on every render automatically.

For low-level control, you can also use o.render + bw.update() directly — see the State Management guide.

For communication between components, use pub/sub:

bw.sub('item-added', function(detail) {
  console.log('New item:', detail.name);
});

bw.pub('item-added', { name: 'Widget' });

CSS from JavaScript

bw.css() generates CSS from objects. bw.s() composes inline styles from reusable utility objects:

// Generate and inject a stylesheet
bw.injectCSS(bw.css({
  '.my-card': { padding: '1rem', borderRadius: '8px' }
}));

// Compose inline styles from objects
{ t: 'div', a: { style: bw.s({ display: 'flex' }, { gap: '1rem' }, { padding: '1rem' }) } }

// Responsive breakpoints
bw.responsive('.hero', {
  base: { fontSize: '1.5rem' },
  md:   { fontSize: '2.5rem' }
});

Theming

bw.loadStyles() derives a design system — buttons, alerts, badges, cards, forms, tables, hover states, focus rings — from two seed colors. Themes are scoped to DOM subtrees, so different sections of a page can use different themes. toggleStyles() switches between primary and alternate palettes:

bw.loadStyles({
  primary: '#336699',
  secondary: '#cc6633'
});

bw.toggleStyles();  // switch between primary and alternate palettes

Core API

| Function | Description | |---|---| | bw.html(obj) | Convert an object to an HTML string | | bw.DOM(selector, obj) | Mount an object to a DOM element | | bw.raw(str) | Mark a string as pre-escaped HTML (no double-escaping) | | bw.component(taco) | Wrap a TACO in a ComponentHandle with .get()/.set() reactive API | | bw.css(rules) | Generate CSS from a JS object | | bw.s(...objs) | Compose inline style objects into a style string | | bw.responsive(sel, breakpoints) | Generate @media CSS rules from JS | | bw.loadStyles() | Inject the built-in stylesheet (or pass config to theme) | | bw.makeStyles(config) | Generate a scoped theme from seed colors (returns styles object) | | bw.toggleStyles() | Switch between primary and alternate palettes | | bw.patch(id, content) | Update a specific element by UUID | | bw.update(el) | Re-render via the element's o.render function | | bw.message(target, action, data) | Send a message to a component by tag name | | bw.pub(topic, detail) | Publish a message to subscribers | | bw.sub(topic, handler) | Subscribe to a topic; returns an unsub function | | bw.inspect(target) | Debug a component in the browser console | | bw.apply(msg) | Apply a bwserve protocol message to the DOM |

See the full API Reference for all functions.

CLI

Convert Markdown, HTML, or JSON files to styled standalone pages:

# Convert Markdown to a self-contained HTML page
bwcli README.md -o index.html --standalone

# Apply a theme preset
bwcli doc.md -o doc.html --standalone --theme ocean

# Custom colors
bwcli doc.md -o doc.html --standalone --theme "#336699,#cc6633"

Flags: --output/-o, --standalone/-s, --cdn, --theme/-t, --css/-c, --title, --favicon/-f, --highlight, --verbose/-v

Pipe Server

bwcli serve turns any language into a bwserve backend — send JSON protocol messages via HTTP POST or stdin, and connected browsers update in real time:

bwcli serve --port 8080 --input-port 9000
curl -X POST http://localhost:9000 -d '{"type":"patch","target":"temp","content":"23.5 C"}'

Build Formats

| Format | File | Use case | |--------|------|----------| | UMD | bitwrench.umd.min.js | Browsers and Node.js | | ESM | bitwrench.esm.min.js | Modern bundlers (Vite, webpack, etc.) | | CJS | bitwrench.cjs.min.js | Node.js require() | | ES5 | bitwrench.es5.min.js | Legacy browsers (IE11) |

All formats include source maps. A separate CSS file (bitwrench.css) is also available for use without JavaScript.

Documentation

Start here:

  • Thinking in Bitwrench — the complete guide. Covers TACO, styling (bw.css, bw.s, bw.responsive), composition, events, the three-level component model, bwserve, and common patterns
  • LLM Guide — compact single-file reference with all APIs, patterns, and rules. Designed for AI-assisted development but works as a cheat sheet for anyone

Reference guides (in docs/):

  • TACO Format — the {t, a, c, o} object format
  • State Management — three-level component model, ComponentHandle, reactive state
  • Component Library — all 50+ make*() functions with signatures and examples
  • Theming — palette-driven theme generation, presets, design tokens
  • CLI — the bwcli command for file conversion and pipe server
  • bwserve — server-driven UI protocol (SSE, actions, embedded devices)

Tutorials:

Interactive demos (live site):

Example apps (in examples/):

FAQ

Is this a framework? — No. Bitwrench is a library (~39KB gzipped). No lifecycle to learn, no project structure to follow. Import it, call functions, done.

Does it scale to large apps? — Bitwrench targets single-page tools, dashboards, prototypes, embedded UIs, and content sites — apps where a single HTML file or a handful of files is the right form factor. For a 500-route SPA with team-scale state management, React or Vue is a better fit.

How does bitwrench compare to React/Vue? — They solve different problems at different scales. React and Vue provide a component model, virtual DOM, and ecosystem for large team-built SPAs. Bitwrench provides rendering and state primitives in a single file with no build step, aimed at single-page tools, dashboards, embedded devices, and server-driven UIs. They coexist fine — use whichever fits the job.

How does CSS work? — Bitwrench doesn't own your CSS. Use any external stylesheet, Tailwind, or CSS file you want — bitwrench doesn't interfere. On top of that, bw.css() generates CSS from JS objects (with @media, @keyframes, pseudo-classes), bw.s() composes inline style objects, and bw.loadStyles() or bw.makeStyles() derives a complete theme from 2 seed colors. You can use all three together or none at all.

What's the difference between bw.DOM() and bw.html()? — Same TACO input, two outputs. bw.DOM('#app', taco) mounts live DOM elements in a browser. bw.html(taco) returns an HTML string — use it in Node.js scripts, email generators, static site builds, or anywhere you need markup without a browser. One object format, two rendering modes.

What is bwserve? — bwserve lets any server push UI updates to a browser over SSE. The server sends TACO objects as JSON; the browser renders them. It's language-agnostic — the server can be Python, Go, Rust, C, or a shell script. Anything that can write JSON to an HTTP response can drive a bitwrench UI. See the bwserve docs.

Can I use bitwrench on embedded devices? — Yes — this is a primary use case. An ESP32 or Raspberry Pi serves one HTML page with bitwrench loaded, then pushes sensor data as JSON patches over SSE. The device never generates HTML. See the ESP32 tutorial.

Can I use it with TypeScript? — Yes. Type declarations are included. TACO objects are plain JSON-compatible objects that TypeScript infers naturally.

What about accessibility? — BCCL components emit semantic HTML with ARIA attributes where applicable. You can add any aria-* attribute via a: { 'aria-label': '...' }.

Development

npm install          # install dev dependencies
npm run build        # build all dist formats (UMD, ESM, CJS, ES5)
npm test             # run unit tests (1000+ tests)
npm run test:cli     # run CLI tests
npm run test:e2e     # run Playwright browser tests
npm run lint         # run ESLint
npm run cleanbuild   # full production build with SRI hashes

License

BSD-2-Clause — (c) M. A. Chatterjee / deftio