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

web-signature

v0.2.6

Published

Primitive and fast framework for rendering web interfaces

Downloads

133

Readme

Signature

GitHub package.json versionNPM Version

This is a primitive and simple component-based declarative rendering framework.

Features

  • Simplicity and primitiveness
  • Declarative rendering
  • Flexibility, and Object-Oriented Architecture

Quick Start

To get started with Signature, simply run this command:

npm create signature@latest

You will be offered several project templates (almost all templates use Vite). After creating the project, follow the instructions to install dependencies and run:

cd <your-project-name>
npm install
npm run dev

Introduction

Signature uses four classes as its basis:

  • Signature - which processes the entire page and components.
  • Component - which defines a standard structure for any element.
  • Prop - which defines properties for components.
  • Library - which defines a set of components.

In short, Signature allows you to create a website using simple and straightforward components that are easy to customize and extend.

Briefly about Signature

The signature is the main class that is responsible for processing the entire page. It is used to add components, register libraries, and essentially render the page.

// Creating a Signature instance

import {Signature} from 'web-signature';

const si = new Signature();

To add a component, use the Signature.add(component: ComponentConstructor, name?: string) method, which takes the component class and its name. For example:

import {Signature, Component} from 'web-signature';

class MyComponent extends Component {
	/* ... */
}

const si = new Signature();

si.add(MyComponent, 'my-component');
// The <my-component> tag will be processed by this class.

Although the component name is not required, it is recommended to specify it to avoid problems when building the project.

To register a library, the Signature.register(library: Library) method is used, which takes an instance of the Library. For example:

import {Signature} from 'web-signature';
import {MyLibrary} from './my-library';

const si = new Signature();
si.register(new MyLibrary());

For rendering the page there is a Signature.contact(selector: string, callback?) method. For example:

import {Signature} from 'web-signature';

const si = new Signature();

si.contact('#app', () => {
	console.log('Page rendered successfully!');
});

About Component

This is an abstract class from which all components inherit. It defines a standard structure for any element. It has a main method Component.render(), and component lifecycle hooks such as Component.onMount().

To create a component, you need to inherit the Component class and implement the Component.render(): string method and the name field. Let's create a simple component that simply displays text:

import {Component, html} from 'web-signature';

class MyComponent extends Component {
	name = 'my-component';

	render(): string {
		return html`<div>Hello, World!</div>`;
	}
}

<div id="app">
    <my-component></my-component>
</div>

Now let's make a counter component that will increment the value when clicked. To do this, we will need to update it somehow and track events. For a component to be able to update, it must have its own ref. Ref - allows you to associate a component instance with its DOM element, if the ref is not specified, the Signature will not remember the component instance. And to track events, we will use the Component.onMount(el: Element) hook, which is called after the component has been added to the page.

import {Signature, Component, html} from 'web-signature';

export class Counter extends Component {
	name = "counter";

	count = 0;

	render(): string {
		// Rendering the component as a button with the current count
		return html`<button type="button">Count is ${this.count}</button>`;
	}

	onMount(el: Element): void {
		el.addEventListener('click', () => {
			// Since a ref is required to update a component, we check if it is defined.
			if (this.ref === undefined) {
				throw Error();
			}

			this.count++;

			// Update the component
			this.ref.update();
		});
	}
}

const si = new Signature();
si.add(Counter, "Counter");
si.contact("#app");

The HTML should look like this:


<div id="app">
    <counter ref></counter>
</div>

It is not necessary to specify a specific ref, the signature will generate it itself, but if you want the ref to have a specific name, you can specify it in the attribute. You can also set the component options to auto-generate the ref if it was not specified.

// ...
class Counter extends Component {
	options = {
		generateRefIfNotSpecified: true
	}
	// ...
}

// ...

Let's make it possible to set the number of steps to increment the counter, using Props. We need to create a Prop step with type number.

import {Signature, Component, Prop, html} from 'web-signature';

export class StepCounter extends Component {
	name = "step-counter";

	count = 0;

	// In this field, we create a Prop step with type number
	props = {
		// We have specified that this Prop is required and must be a number greater than or equal to 1.
		step: new Prop("number", true, (val) => Number(val) >= 1)
	}

	render(): string {
		// Rendering the component as a button with the current count
		return html`<button type="button">Count is ${this.count}</button>`;
	}

	onMount(el: Element): void {
		el.addEventListener('click', () => {
			// Since a ref is required to update a component, we check if it is defined.
			if (this.ref === undefined) {
				throw Error();
			}

			//After processing Props, the specified values are written to this.data
			this.count += this.data.step as number;

			// Update the component
			this.ref.update();
		});
	}
}

const si = new Signature();
si.add(StepCounter, "Step-counter");
si.contact("#app");

The HTML should look like this:


<div id="app">
    <Step-counter ref step="2"></Step-counter>
</div>

Now, when you click the button, the counter will increase by the specified number of steps (in our case, it is 2 steps).

Quick about the Library

The Library class allows you to create a set of components that can be used in a project. It has no other purpose than to facilitate the registration of components in Signature, and avoiding component name collisions by grouping them.

Let's create a library that will contain our Counter and StepCounter components:

import {Library} from 'web-signature';

// Importing the components
import {Counter} from './Counter';
import {StepCounter} from './StepCounter';

// Creating a library instance
const myLibrary = new Library('ML');

// Adding components to the library
myLibrary.add(Counter, "Counter");
myLibrary.add(StepCounter, "Step-counter");

export default myLibrary;

To register the library in Signature, use the Signature.register(library: Library) method:

import {Signature} from 'web-signature';

// Importing the library
import myLibrary from './myLibrary';

const si = new Signature();

// Registering the library
si.register(myLibrary);

si.contact('#app');

Now you can use the components from the library in your HTML, but all components will be available with the prefix ML-, i.e. ML-counter and ML-step-counter, the pattern is the library name is used as a prefix for the component name [libName]-[componentName].


<div id="app">
    <ML-counter ref></ML-counter>
    <ML-step-counter ref step="2"></ML-step-counter>
</div>

See more here