
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
almostnojs
Advanced tools
A minimalist, dependency-free JavaScript framework featuring tagged template rendering, DOM morphing, custom elements, state management, event handling, animations, and HTTP requests.
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.
html tagged templates with surgical DOM updates.AnJSElement base class with batched updates and computed properties.$().method() syntax for clean, readable code.onChange, onAny, patch, and DOM bindings.See AlmostNo.js Live Examples in action.
AlmostNo.js targets ES2020 and works on all modern browsers (Chrome, Firefox, Edge, Safari, Opera).
npm install almostnojs
import $, { html, render, morph, AnJSElement, registerComponent } from 'almostnojs';
<!-- 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>
Download the latest release from dist/browser/ and include it directly:
<script src="./almostno.full.js"></script>
Three prebuilt bundles are available, plus NPM with tree-shaking.
| 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 | ❌ | ❌ | ❌ | ✅ |
| 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 |
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
render(html`<div class="card ${active ? 'active' : ''}">
<button disabled=${!ready}>Submit</button>
</div>`, container);
const items = ['Apple', 'Banana', 'Cherry'];
render(html`<ul>${items.map(i => html`<li>${i}</li>`)}</ul>`, container);
import { html, unsafeHTML, render } from 'almostnojs';
render(html`<div>${unsafeHTML('<em>trusted markup</em>')}</div>`, container);
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>');
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.
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);
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>`; }
}
const el = document.querySelector('my-counter');
el.state.count = 42;
await el.updateComplete;
// DOM is now updated
$('div').text('Hello, World!');
$('#box').css('color', 'red').class('highlight');
$('#btn').on('click', () => alert('Clicked!'));
$.emit('app:ready', { ts: Date.now() });
$.listen('app:ready', data => console.log(data));
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>
$.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>
$.get('/api/data').then(console.log);
$.post('/api/submit', { name: 'Jane' });
$.get('/api/slow', { timeout: 3000 });
| 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) |
| Function | Description |
|---|---|
morph(target, newHTML) | Reconcile live DOM to match new HTML string |
| 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 |
$(selector) – Select elements.$.extend(name, func, force) – Extend AlmostNo.js..each(fn) – Iterate over matched elements..get(index) – Get an element by index..clone(deep) – Clone an element..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..id(value) – Get/set the id attribute..attr(name, value) – Get/set attributes..removeAttr(name) – Remove an attribute..serialize() – Serialize a form..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.$.emit(event, data) – Emit a global event.$.listen(event, handler) – Listen for a global event.$.forget(event, handler) – Remove a global event listener..next() / .prev() – Adjacent siblings..parent() – Parent element..children() – Direct children..siblings() – All siblings..closest(selector) – Closest matching ancestor..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..animate(styles, duration, easing) – Animate CSS properties..fade(opacity, duration) – Fade to a specific opacity..fadeIn(duration) / .fadeOut(duration) – Fade in/out..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.$.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.$.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..click(cb) / .change(cb) / .submit(cb) / .keydown(cb) / .keyup(cb) / .mouseover(cb) / .mouseout(cb) – Event shortcuts.This project is licensed under the MIT License — see the LICENSE file for details.
FAQs
A minimalist, dependency-free JavaScript framework featuring tagged template rendering, DOM morphing, custom elements, state management, event handling, animations, and HTTP requests.
We found that almostnojs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.