---
name: nojs
metadata:
version: 1.11.0
description: Expert-level knowledge of the No.JS HTML-first reactive framework for building dynamic web applications using only HTML attributes. Use this skill whenever the user mentions No.JS, NoJS, "no javascript framework", HTML-first framework, or is writing HTML with reactive attributes like bind, state, get, each, on:click, model, route, store, computed, watch, if/else, show/hide, foreach, validate, animate, drag, drop, t (i18n), class-*, style-*, or bind-*. Also use when the user asks about declarative HTML frameworks, zero-JS frameworks, or wants to build a web app without writing JavaScript. Even if the user doesn't mention No.JS by name, activate this skill when you see HTML attributes that match No.JS directive patterns.
---
# NoJS-Skill
No.JS is an HTML-first reactive framework with zero dependencies that replaces JavaScript with declarative HTML attributes. CSP-compliant via a custom expression parser (no eval). Include one `
```
No `app.mount()`, no `createApp()`, no build step. It just works.
## When to use
Use this skill when:
- The user mentions **No.JS**, **NoJS**, or the **HTML-first reactive framework**
- The user is writing HTML with No.JS directive attributes (`bind`, `state`, `get`, `each`, `on:click`, `model`, `route`, `store`, `foreach`, `validate`, `animate`, `drag`, `drop`, `t`, `class-*`, `style-*`, `bind-*`)
- The user asks about **declarative HTML frameworks** or wants to build a **web app without writing JavaScript**
- The user needs to **scaffold**, **validate**, or **debug** No.JS templates
- You see HTML attributes that match No.JS directive patterns, even without explicit mention
## Instructions
### 1. Understand the framework architecture
No.JS works by walking the DOM on `DOMContentLoaded`, matching HTML attributes to directives, and executing them by priority:
| Priority | Directives | Purpose |
|----------|-----------|---------|
| 0 | `state`, `store` | Initialize reactive data first |
| 1 | `get`, `post`, `put`, `patch`, `delete`, `error-boundary`, `i18n-ns`, `page-title`, `page-description`, `page-canonical`, `page-jsonld` | Fetch data, error/i18n setup, head management |
| 2 | `computed`, `watch` | Derive values and observe changes |
| 5 | `ref` | Element references |
| 10 | `if`, `else-if`, `else`, `switch`, `each`, `foreach`, `use`, `drag-list` | Structural (add/remove DOM) |
| 15 | `drag`, `drop` | Drag and drop setup |
| 16 | `drag-multiple` | Multi-select drag |
| 20 | `bind`, `bind-*`, `bind-html`, `model`, `class-*`, `style-*`, `on:*`, `show`, `hide`, `t`, `call`, `trigger`, `page-title`, `page-description`, `page-canonical`, `page-jsonld` | Rendering, events, i18n, actions, head management |
| 30 | `validate` | Form validation side effects |
Data lives in Proxy-backed reactive contexts that inherit from parent elements (like lexical scoping). When data changes, every bound element updates automatically.
### 2. Know the core directives
**Data Fetching** - `get="/url"` with `as="varName"`, `loading`, `error`, `empty`, `success`, `refresh`, `cached`, `into`, `debounce`, `headers`, `params`, `skeleton` (CLS-prevention: hides an existing DOM element during fetch). URLs support interpolation: `get="/users/{userId}"` re-fetches reactively. Mutation verbs: `post`, `put`, `patch`, `delete`. Static `get=` URLs automatically get a `` hint injected at init time; cross-origin URLs also get ``. Route templates with `src=` get `` at router startup.
**State** - `state="{ key: value }"` (local), `store="name"` (global via `$store.name`), `computed="name" expr="expr"`, `watch="prop" on:change="handler"`, `persist`/`persist-fields`. Note: stores created via `NoJS.config({ stores })` won't be overwritten by later `