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

signel

v4.0.0

Published

Signel - lightweight ui library for web apps

Readme

Signel.js

Signel.js is a minimal reactive JavaScript library for building interactive UIs using native DOM APIs. It provides:

  • Reactive state management
  • Automatic DOM updates
  • Dependency-tracked effects
  • Lightweight component system
  • Optional localStorage persistence

No virtual DOM. No build step. No framework lock-in.

Table of Contents

  1. Installation
  2. Core Concepts
  3. state() – Reactive State
  4. effect() – Reactive Effects
  5. DOM Rendering
  6. Array Reactivity
  7. Persistence with localStorage
  8. Components
  9. Examples
  10. Design Philosophy & Limitations

1. Installation

Include Signel.js directly in your HTML:

<script src="https://signel.onrender.com/signel.js"></script>

Signel exposes three global APIs:

state()
effect()
component()

2. Core Concepts

Reactivity Model

Signel uses:

  • Proxies for state mutation tracking
  • Automatic dependency collection via effect()
  • Direct DOM updates (no virtual DOM)

State changes trigger:

  • DOM updates
  • Effects re-execution
  • Optional persistence

3. state() – Reactive State

Creating State

const count = state(0)

Access or update the value via .val:

count.val++        // update
console.log(count.val) // read

State API

const myState = state(initialValue, options)

Parameters

| Parameter | Description | | -------------- | ---------------------- | | initialValue | Primitive or array | | options | Optional configuration |

Options

{
  storageKey: 'key-name', // persist to localStorage
  showEach: item => `<li>${item}</li>` // array rendering template
}

4. effect() – Reactive Effects

Effects automatically re-run when any accessed state changes. Example

const count = state(0)

effect(() => {
  console.log('Count is:', count.val)
})

How it works:

  • When count.val is read inside effect
  • The effect is registered as a dependency
  • When count.val changes → effect re-runs

5. DOM Rendering

Binding State to DOM

<p class="count"></p>
count
  .root(document.body)
  .render('.count')
  • .root() defines where Signel should search
  • .render() selects elements to bind DOM updates automatically when state changes.

Two-Way Binding (Inputs)

Supported elements:

<input>
<textarea>
<select>
<input class="name">
<p class="output"></p>
const name = state('')

name
  .root(document.body)
  .render('.name')
  .render('.output')

Typing updates state → state updates DOM.

6. Array Reactivity

Arrays are fully reactive.

const todos = state([], {
  showEach: item => `<li>${item}</li>`
})

Rendering Arrays

<ul class="list"></ul>
todos
  .root(document.body)
  .render('.list')

Updating Arrays

todos.val.push('Buy milk')
todos.val.splice(0, 1)

Supported mutating methods:

  • push
  • pop
  • splice
  • shift
  • unshift Each mutation:
  • Updates the DOM
  • Triggers effects
  • Saves to storage (if enabled)

7. Persistence with localStorage

Enable persistence by providing a storageKey.

const count = state(0, {
  storageKey: 'count'
})

Behavior:

  • Loads value from localStorage on init
  • Automatically saves on every change

Arrays are stored as JSON.

8. Components

Signel supports Web Components via component().

Defining a Component

component('CounterBox', (props, mount) => {
  const count = state(0)

  count.root(mount).render('.value')

  return `
    <div>
      <span class="value"></span>
      <button>+</button>
    </div>
  `
})

Component names:

  • Must contain a hyphen
  • Are automatically converted to kebab-case
<counter-box></counter-box>

Component Props

Attributes are passed as props:

<user-card name="John"></user-card>
component('UserCard', (props) => {
  return `<p>Hello ${props.name}</p>`
})

9. Examples

Counter

<button id="inc">+</button>
<p class="count"></p>
const count = state(0)

count.root(document.body).render('.count')

document.getElementById('inc').onclick = () => {
  count.val++
}

Todo List

<input id="todoInput">
<button id="add">Add</button>
<ul class="todos"></ul>
const todos = state([], {
  showEach: item => `<li>${item}</li>`,
  storageKey: 'todos'
})

todos.root(document.body).render('.todos')

document.getElementById('add').onclick = () => {
  todos.val.push(todoInput.value)
}

10. Design Philosophy & Limitations

Philosophy

  • Minimal API
  • No build tools
  • No JSX
  • Native browser features
  • Small mental model

Limitations

  • No virtual DOM diffing
  • No deep object reactivity
  • Array rendering replaces innerHTML
  • Effects are global (not scoped)

Summary

Signel.js is ideal for:

  • Small to medium projects
  • Learning reactivity fundamentals
  • Enhancing static HTML
  • Lightweight widgets and tools
  • It gives you reactivity without framework overhead.