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

@twobirds/microcomponents

v0.2.5

Published

Micro Components

Readme

logo

MICRO COMPONENTS

MCs are function blocks that you attach to DOM nodes. These are re-usable in any frontend framework.

There are helpers for the following functionalities:

  • Web Components: create native web components. Their functionality is comprised of a set of inner MCs.
  • State is done by observable objects that you can attach callbacks to. This also allows for 1-way binding to DOM placeholders, and it can be extended to allow for complex data driven state machines.
  • Form Handling allows for 2-way binding from an observable form object to DOM form input elements.
  • Communication between DOM micro components is ensured via direct selected or directional bubbling CustomEvent's.
  • Autoloading allows for build-free websites that dynamically load JS requirements into DOM HTMLElements.

The distinguishing feature is its minimalism, portability and granular modularization. In an almost literal sense MCs work like childrens building blocks, where a chest full of unassuming parts lets you compose whatever functionality lies in your imagination.

You work with one of the established frameworks? You can still put this hands-on tool in your tool belt. You then have a plugin fallback solution for when your FW fails you or lacks functionality.

Prominent Features

  • No-build development
  • Very shallow learning curve - easy on newbies
  • Strictly web standards compliant
  • Very little abstraction

Status

  • API stable
  • Typedoc documentation needs some brushing

Links

demo shop (on-demand loading). No build, on-demand loading elements. Check code in debugger.

demo shop (bundled in one JS file). 9 kB including the library.

Check the typedoc API reference if you want to drill into the source code.

The progress of coding is occasionally being streamed on twitch.

Examples

Functional Principle

  • This section only shows the priciple: how Micro Components are stored in the DOM
  • The section after this shows Web Components / Custom Elements
  • All examples on this page are Javascript.
  • The package has full Typescript support

html before:

<div></div>

code:

// create a custom micro component class
class MyMC extends DC {
	helloWorld() {
		console.log('Hello World');
	}
}

// get some element from the DOM
const element = document.querySelector('div');

// Add the custom micro component instance to the target element programatically
DC.add(element, 'myMC', new MyMC(element));

// Hello World
element
	._mc
	.myMC
	.helloWorld();

html after:

<div data-mc></div>
  • The data-mc attribute indicates that this HTML element contains at least one micro component. This is needed for the selectors.
  • The _mc property is the only interference with the DOM, so any other system should be happy to work with this.

Web Components / Custom Elements

You can define a custom element using a micro component as its primary functional instance. You are still free to add many more micro components to the custom element at runtime.

code:

// create a micro component class
class MyComponent extends DC {}
// define it as a web component
defineCE('my-component', MyComponent);

after: you can use ...

<my-component></my-component>

... in your template. The custom element will auto-attach.

Or you can construct it programmatically:

const ctor = getCE('my-component');
const body = document.body;
body.append(new ctor());
  • For more examples regarding web components, go to the typedocs
  • Check the sources of the demo shop in the browser debugger

State and 1-way-binding

Declare states and directly connect them to DOM placeholders.

code:

observePlugin(DC);
// create a custom micro component class
class MyMC extends DC {

	state = { text: 'Hello world!' };

	constructor(target) {
		super(target);

		this.target.innerHTML = '{text}'; // simplicity, there are other methods

		this
		.bind( 'state', target ) // one way binding
		.subscribe( 'state', (value) => { // attach your own callbacks
			console.log(value);
		});

		// changing the state will change the DOM
		this.state.text = 'Hallo Welt'; // also triggers console.log()
	}
}

Forms and 2-way-binding

Similar to observables above, you can 2-way-bind an observable object to form input fields.

Changes in the object properties trigger input field changes and vice versa.

code:

formValuesPlugin(DC);
// create a custom micro component class
targetHtml = /*HTML*/ `
<form>
	<input name="textInput" value="Hallo Welt!"/>
</form>
`;
class MyMC extends DC {
	constructor(target) {
		super(target);

		this.target.innerHTML = targetHtml;

		this.formData = { textInput: '' };

		this
		.formValues(target, 'formData')// link the form property to the DOM input fields
		.subscribe( 'formData', (data) => {
			console.log(data); // the form data object
		});

		// now simply changing the form property will change the DOM input fields
		this.form.textinput = 'Hello World!';

		// ... and editing the form input will change the 'form' property
	}
}

Event Handlers

Native Events

Events and there handlers are defined and triggered inside the system automatically.

You can use events separately in vanilla JS to communicate with micro components.

code:

// create a custom micro component class
class MyMC extends DC {
	constructor(target) {
		super(target);

		// attach event handler programatically
		let onHoverHandler = this.on('hover', () => {
			// ...
		});

		// remove event handler
		this.off('hover', onHoverHandler);
	}

	// this native event handler is attached automatically
	onClick() {
		console.log('HTMLElement clicked!');
	}

	// this native event handler is attached automatically
	oneClick() {
		console.log('HTMLElement clicked! ( only fires once )');
	}
}

Custom Events

code:

// create a custom micro component class
class MyMC extends DC {
	constructor(target) {
		super(target);

		payload = {
			test: 42,
		};

		setTimeout(() => {
			this.trigger('customEvent', payload);
		});
	}

	// this event handler is attached automatically
	onCustomEvent(ev) {
		console.log('onCustomEvent called with', ev.data.test); // "42"
	}
}

Goals

This code aims at improving Javascript modularity and encapsulation. Micro Components are built on OOP for structure, so you should embrace DRY, KISS and SOLID principles.

MCs provide a runtime app structure that is directly linked to the browser DOM. That is you don't need web components, you can attach MCs to plain HTMLElements. Having said this: the library also allows for standard web component programming, acting as a framework.

In general this is a HTML / Web Standards first system. There is almost no abstraction, especially not for templating, except state binding to the DOM via simple placeholders.

It has no interference with other frameworks, since it creates a second layer that hovers above the DOM. So what you intended to work as an add-on to React, is usable e.g. in Angular also.

And, of course, you can use it as your main framework using its custom web component functionality.

Its basic principle is composition over inheritance. Also it helps to embrace DIY (Do It Yourself) over Toolchains, but this is up to your personal preference.

You can use Vanilla JS or Typescript or both in parallel in your project. For example you could use plain JS for rapid prototyping functionalities, then convert to TS for production.

Most of all this system by design allows for outsourcing without sharing the main development system. It is absolutely granular as it enforces DRY (Don't Repeat Yourself).

Finally it allows for a clear distinction between Junior, Senior and Architect roles in a project. No more hiring junior programmers with 5 years experience in 50 tools under their belt. A junior in this system is somebody who likes HTML, CSS and JS/TS - nothing more. Teaching all of this system starting at zero takes 1 day. The rest is finger muscle memory and learning/knowing web standards.

Distinguishing Features

There are a few potentially unique aspects of this micro components system that might differentiate it from other framework or library:

  • Pure OOP Approach: The system explicitly positions itself as a strict object-oriented alternative to the functional approaches that dominate many modern frameworks.

  • Minimal Interference: The system has minimal DOM interference, only adding _mc property to DOM nodes that contain code. This makes it unusually compatible with other frameworks or libraries.

  • Hierarchical Component Traversal: The built-in ancestor/closest/child/descendant traversal methods provide a clean way to navigate component relationships.

  • Direct DOM Integration: Unlike virtual DOM-based frameworks, this approach works directly with the actual DOM while still providing component encapsulation.

  • Outsourcing Potential: Your external coders do not need to access your code repository or your toolchain.

The strongest argument might be for developers who prefer OOP, want minimal framework lock-in, and need a lightweight solution that works well with existing code or other libraries.

Contact

Feel free to contact me for any questions or inquiries:

email Frank Thürigen

You can fund this.

Disclaimer

I decided to extract this functionality from the now deprecated twoBirds framework, because it is a useful tool in itself and it is framework agnostic.

Later this will be backported into twoBirds as a dependency, and twoBirds will become a completely modularized MC UI package on the base of MCs.

Deprecated test:

manual testing ( also a speed test ).