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

almostnojs

v1.3.0

Published

A minimalist, dependency-free JavaScript framework featuring tagged template rendering, DOM morphing, custom elements, state management, event handling, animations, and HTTP requests.

Downloads

44

Readme

AlmostNo.js

Version License Minified + Gzip Flexible & Easy to Learn

AlmostNo.js is a lightweight, zero-dependency JavaScript framework featuring tagged template rendering, DOM morphing, custom elements, reactive state management, chainable DOM manipulation, event handling, animations, and HTTP requests.

Features

  • Tagged Template Rendering – Lit-style html tagged templates with surgical DOM updates.
  • DOM Morphing – Reconcile live DOM against new HTML without destroying state.
  • Custom Elements – Reactive AnJSElement base class with batched updates and computed properties.
  • Tiny & Fast – 5 KB core, 6 KB extended, 12 KB full (minified + gzipped). Zero dependencies.
  • Chainable API – Familiar $().method() syntax for clean, readable code.
  • DOM Manipulation – Select, traverse, and modify elements effortlessly.
  • Events & Event Bus – Attach, delegate, trigger events; cross-component communication.
  • Reactive State – Proxy-based state with onChange, onAny, patch, and DOM bindings.
  • Components – SSR-compatible server/client components with auto-mounting.
  • HTTP Requests – Fetch wrappers with timeout handling and abort controllers.
  • Animations – Simple CSS-based transitions.
  • Utilities – Debounce, throttle, type checks, JSON parsing, and more.

Examples

See AlmostNo.js Live Examples in action.

Browser Support

AlmostNo.js targets ES2020 and works on all modern browsers (Chrome, Firefox, Edge, Safari, Opera).

Installation

NPM

npm install almostnojs
import $, { html, render, morph, AnJSElement, registerComponent } from 'almostnojs';

CDN

<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/almostnojs@latest/dist/cdn/almostno.full.js"></script>

<!-- UNPKG -->
<script src="https://unpkg.com/almostnojs@latest/dist/cdn/almostno.full.js"></script>

Self-hosting

Download the latest release from dist/browser/ and include it directly:

<script src="./almostno.full.js"></script>

Choosing the Right Version

Three prebuilt bundles are available, plus NPM with tree-shaking.

Feature Comparison

| Feature | Core | Extended | Full | NPM | |----------------------------|------|----------|------|-----| | DOM Manipulation | ✅ | ✅ | ✅ | ✅ | | Events & Event Bus | ✅ | ✅ | ✅ | ✅ | | Attributes | ✅ | ✅ | ✅ | ✅ | | HTTP Requests | ✅ | ✅ | ✅ | ✅ | | Animations | ❌ | ✅ | ✅ | ✅ | | Filtering & Traversal | ❌ | ✅ | ✅ | ✅ | | State Management | ❌ | ❌ | ✅ | ✅ | | Components | ❌ | ❌ | ✅ | ✅ | | Template Parts | ❌ | ❌ | ❌ | ✅ | | DOM Morphing | ❌ | ❌ | ❌ | ✅ | | Custom Elements | ❌ | ❌ | ❌ | ✅ |

Bundle Sizes (minified + gzipped)

| Version | Size | Path | |-------------|---------|---------------------------------------| | Core | ~5 KB | dist/browser/almostno.js | | Extended| ~6 KB | dist/browser/almostno.extended.js | | Full | ~12 KB | dist/browser/almostno.full.js |

Quick Start

Template Parts (Tagged Templates)

Render reactive templates with surgical DOM updates — only changed values are patched.

import { html, render } from 'almostnojs';

const app = document.getElementById('app');

function view(name) {
    render(html`<h1>Hello, ${name}!</h1>`, app);
}

view('World');  // First render: creates DOM
view('AnJS');   // Update: patches only the text node

Attributes

render(html`<div class="card ${active ? 'active' : ''}">
    <button disabled=${!ready}>Submit</button>
</div>`, container);

Lists

const items = ['Apple', 'Banana', 'Cherry'];
render(html`<ul>${items.map(i => html`<li>${i}</li>`)}</ul>`, container);

Unsafe HTML

import { html, unsafeHTML, render } from 'almostnojs';

render(html`<div>${unsafeHTML('<em>trusted markup</em>')}</div>`, container);

DOM Morphing

Reconcile live DOM against new HTML without destroying state, focus, or event listeners.

import { morph } from 'almostnojs';

morph(document.getElementById('app'), '<div class="updated">New content</div>');

Custom Elements

Build reactive web components with AnJSElement.

import { AnJSElement, html, registerComponent } from 'almostnojs';

class MyCounter extends AnJSElement {
    init() {
        this.state.count = 0;
    }

    render() {
        return html`
            <button @click=${() => this.state.count++}>
                Clicked ${this.state.count} times
            </button>`;
    }
}

registerComponent('my-counter', MyCounter);
<my-counter></my-counter>

Features: reactive state proxy, batched microtask updates, computed properties, observedAttributes reflection, init() / updated() / destroy() lifecycle hooks, auto-cleanup with this.own(), updateComplete promise, repeat() keyed lists.

Keyed Lists with repeat()

import { AnJSElement, html, repeat, registerComponent } from 'almostnojs';

class TodoList extends AnJSElement {
    init() {
        this.state.items = [
            { id: 1, text: 'Learn AnJS' },
            { id: 2, text: 'Build something' },
        ];
    }

    render() {
        return html`<ul>${repeat(
            this.state.items,
            item => item.id,
            item => html`<li>${item.text}</li>`
        )}</ul>`;
    }
}

registerComponent('todo-list', TodoList);

Auto-Cleanup

class LiveWidget extends AnJSElement {
    init() {
        // Automatically unsubscribed when element disconnects
        this.own($.listen('data:update', (data) => {
            this.state.value = data;
        }));
    }
    render() { return html`<span>${this.state.value}</span>`; }
}

Awaiting Updates

const el = document.querySelector('my-counter');
el.state.count = 42;
await el.updateComplete;
// DOM is now updated

DOM Manipulation

$('div').text('Hello, World!');
$('#box').css('color', 'red').class('highlight');

Events

$('#btn').on('click', () => alert('Clicked!'));
$.emit('app:ready', { ts: Date.now() });
$.listen('app:ready', data => console.log(data));

State Management

const state = $('#app').state({ count: 0 });
$('#increment').on('click', () => state.count++);
$('#display').bind(state);
<div id="app">
    <span id="display" data-bind="count"></span>
    <button id="increment">+1</button>
</div>

Components

$.component("Card",
    ({ state, props }) => `
        <div class="card">
            <h3>${props.title}</h3>
            <p>Likes: <span data-bind-this="likes"></span></p>
            <button data-action="like">Like</button>
        </div>`,
    () => $.state({ likes: 0, like() { this.likes++ } })
);
<Card title="Hello"></Card>

HTTP Requests

$.get('/api/data').then(console.log);
$.post('/api/submit', { name: 'Jane' });
$.get('/api/slow', { timeout: 3000 });

API Reference

Template Parts

| Function | Description | |----------|-------------| | html`...` | Tagged template literal — returns a TemplateResult | | render(result, container) | Render a TemplateResult into a DOM element | | clearTemplate(container) | Clear cached template data for a container | | unsafeHTML(string) | Mark a string as trusted HTML (bypasses escaping) |

DOM Morphing

| Function | Description | |----------|-------------| | morph(target, newHTML) | Reconcile live DOM to match new HTML string |

Custom Elements

| Export | Description | |--------|-------------| | AnJSElement | Base class for reactive custom elements | | registerComponent(name, cls) | Register a custom element (idempotent) | | repeat(items, keyFn, templateFn) | Keyed list helper for efficient DOM reconciliation |

AnJSElement Instance API

| Member | Description | |--------|-------------| | state | Reactive proxy — property writes trigger batched updates | | computed(name, deps, fn) | Define a computed property | | render() | Return html`...` or a string — called on every update | | update() | Force a synchronous DOM update | | own(disposerFn) | Register a cleanup function — called automatically on disconnect | | updateComplete | Promise that resolves after the current render cycle | | static updateStrategy | 'microtask' (default) or 'raf' for frame-coalesced updates | | init() | Lifecycle hook — called once after first render | | updated() | Lifecycle hook — called after every render | | destroy() | Lifecycle hook — called on disconnect before auto-cleanup |

Core

  • $(selector) – Select elements.
  • $.extend(name, func, force) – Extend AlmostNo.js.

Iteration

  • .each(fn) – Iterate over matched elements.
  • .get(index) – Get an element by index.
  • .clone(deep) – Clone an element.

DOM Manipulation

  • .content(value, html) – Get/set text or HTML content.
  • .text(value) – Get/set text content.
  • .html(value) – Get/set HTML content.
  • .css(prop, value) – Get/set CSS styles.
  • .class(name, add) – Add, remove, or toggle classes.
  • .display(show) – Show or hide elements.
  • .hide() / .show() – Convenience hide/show.
  • .remove() – Remove elements from the DOM.
  • .empty() – Remove all child elements.
  • .insert(content, position) – Insert elements at a position.
  • .append(content) / .prepend(content) – Insert content at start/end.
  • .before(content) / .after(content) – Insert adjacent content.
  • .prop(name, value) – Get/set DOM properties.
  • .val(value) – Get/set form element values.
  • .focus() / .blur() – Focus and blur.

Attributes

  • .id(value) – Get/set the id attribute.
  • .attr(name, value) – Get/set attributes.
  • .removeAttr(name) – Remove an attribute.
  • .serialize() – Serialize a form.

Events

  • .on(event, selector?, handler) – Attach event listeners (optional delegation).
  • .off(event, selector?, handler) – Remove event listeners.
  • .delegate(event, selector, handler) – Delegated event listener.
  • .undelegate(event, selector, handler) – Remove delegated listener.
  • .trigger(event) – Dispatch an event.

Event Bus

  • $.emit(event, data) – Emit a global event.
  • $.listen(event, handler) – Listen for a global event.
  • $.forget(event, handler) – Remove a global event listener.

Traversal

  • .next() / .prev() – Adjacent siblings.
  • .parent() – Parent element.
  • .children() – Direct children.
  • .siblings() – All siblings.
  • .closest(selector) – Closest matching ancestor.

Filtering

  • .filter(callbackOrSelector) – Filter elements.
  • .find(selector) – Find descendants.
  • .first() / .last() – First or last element.
  • .even() / .odd() – Even or odd indexed elements.
  • .has(className) – Check for a class.

Animations

  • .animate(styles, duration, easing) – Animate CSS properties.
  • .fade(opacity, duration) – Fade to a specific opacity.
  • .fadeIn(duration) / .fadeOut(duration) – Fade in/out.

State Management

  • .state(initialState) – Create a reactive state proxy.
  • .bind(state, context) – Bind state to DOM via data-bind.
  • .unbind(state) – Remove bindings.
  • $.global(name, initial) – Create or retrieve global state.
  • $.hasGlobal(name) – Check if a global state exists.
  • $.clearGlobal(name) – Remove a global state.

HTTP Requests

  • $.get(url, options) – GET request.
  • $.post(url, data, options) – POST request.
  • $.put(url, data, options) – PUT request.
  • $.delete(url, options) – DELETE request.
  • $.patch(url, data, options) – PATCH request.
  • $.head(url, options) – HEAD request.
  • $.options(url, options) – OPTIONS request.
  • $.abortController() – Create an AbortController.

Utilities

  • $.json(string) – Safe JSON parse (returns null on failure).
  • $.trim(string) – Trim whitespace.
  • $.range(x, min, max) – Check if a number is within range.
  • $.isFunction(v) / $.isObject(v) / $.isString(v) / $.isNumber(v) – Type checks.
  • $.contains(parent, child) – Check DOM containment.
  • $.debounce(fn, delay) – Debounced function.
  • $.throttle(fn, limit) – Throttled function.
  • $.element(tag, attrs, children) – Create an element.

Event Aliases

  • .click(cb) / .change(cb) / .submit(cb) / .keydown(cb) / .keyup(cb) / .mouseover(cb) / .mouseout(cb) – Event shortcuts.

Why AlmostNo.js?

  • Modern & Minimal – No legacy baggage. ES2020 modules with tree-shaking.
  • Tagged Templates – Lit-inspired rendering without a build step.
  • DOM Morphing – Efficient reconciliation without virtual DOM overhead.
  • Custom Elements – First-class web component support.
  • Reactive State – Proxy-based reactivity with automatic DOM updates.
  • Easy to Learn – Familiar jQuery-style API with modern capabilities.
  • Fast & Lightweight – 5–12 KB gzipped depending on bundle.
  • Extensible – Add custom methods, components, and global state.

License

This project is licensed under the MIT License — see the LICENSE file for details.