@erickxavier/no-js
v1.0.2
Published
The HTML-first reactive framework — build dynamic web apps with just HTML attributes, no JavaScript required
Maintainers
Readme
No.JS
The HTML-First Reactive Framework
Build dynamic, reactive web applications using nothing but HTML attributes. No build step. No virtual DOM. No transpiler. No JSX. Just HTML.
<div get="/users/1" as="user">
<h1 bind="user.name">Loading...</h1>
<p bind="user.email"></p>
</div>Zero JavaScript written. Fully reactive. Real API data.
Features
- Declarative HTTP —
get,post,put,patch,deleteas HTML attributes - Reactive Binding —
bind,bind-*,modelfor one/two-way data binding - Conditionals & Loops —
if,else-if,show,hide,each,foreach,switch - State Management —
state(local),store(global),computed,watch - SPA Routing —
route,route-view, guards, params, nested routes - Forms & Validation — Built-in validators +
$formcontext - Animations —
animate,transitionwith stagger support - i18n —
tdirective with pluralization - Filters —
uppercase,currency,date,truncate, 30+ built-in pipes - Custom Directives — Extend with
NoJS.directive() - ~11 KB gzipped — Zero dependencies
Quick Start
CDN
<script src="https://unpkg.com/@erickxavier/no-js@latest/dist/iife/no.js"></script>NPM
npm install no-js// ESM
import NoJS from 'no-js';
await NoJS.init();
// CommonJS
const NoJS = require('no-js');
await NoJS.init();Example
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@erickxavier/no-js@latest/dist/iife/no.js"></script>
</head>
<body base="https://jsonplaceholder.typicode.com">
<!-- Fetch & display data -->
<div get="/users" as="users" loading="#skeleton">
<div each="user in users">
<h2 bind="user.name"></h2>
<p bind="user.email"></p>
</div>
</div>
<!-- Local state + events -->
<div state="{ count: 0 }">
<button on:click="count++">Clicked <span bind="count"></span> times</button>
</div>
<!-- Form with validation -->
<form post="/posts" validate success="#ok">
<input name="title" required minlength="3" />
<button type="submit" bind-disabled="!$form.valid">Submit</button>
</form>
<template id="skeleton"><p>Loading...</p></template>
<template id="ok" var="res"><p>Created: <span bind="res.title"></span></p></template>
</body>
</html>No app.mount(). No createApp(). No NgModule. It just works.
Documentation
Full documentation is available in the docs/ folder:
| Guide | Description |
|-------|-------------|
| Getting Started | Installation, core concepts, how it works |
| Data Fetching | get, post, put, patch, delete, caching, polling |
| Data Binding | bind, bind-html, bind-*, model |
| Conditionals | if, else-if, show, hide, switch/case |
| Loops | each, foreach, loop variables, nested loops |
| Templates | Reusable fragments, slots, remote templates |
| State Management | state, store, into, computed, watch |
| Events | on:*, modifiers, lifecycle hooks |
| Dynamic Styling | class-*, style-* |
| Forms & Validation | validate, $form, custom validators |
| Routing | SPA navigation, guards, nested routes |
| Animations | animate, transition, stagger |
| i18n | Translations, pluralization, formatting |
| Filters | Built-in filters, chaining, custom filters |
| Actions & Refs | call, trigger, ref, $refs |
| Custom Directives | Extend No.JS |
| Error Handling | Error boundaries, global handler |
| Configuration | Global settings, interceptors, template caching, security |
| Cheatsheet | Every directive at a glance |
| Full SPA Example | Complete app with routing, auth, i18n |
How It Works
- Parse — On
DOMContentLoaded, No.JS walks the DOM for known attributes - Resolve — Each attribute maps to a directive, executed by priority
- React — Data lives in Proxy-backed reactive contexts; changes auto-update the DOM
- Scope — Contexts inherit from parents, like lexical scoping
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
