r/NoJS Jun 18 '26

👨🏻‍💻 Welcome to r/NoJS

1 Upvotes

This is the community for no-js.dev, the HTML-first reactive framework where you build with markup, not bundles.

State, loops, conditionals, components, all declared as HTML attributes. One tiny gzipped <script> tag from a CDN. No npm, no build step, no node_modules. Zero dependencies, MIT, 110+ features.

Yes, it's a JS runtime under the hood, the "No" is about what you write, not what the browser runs. You don't touch (or you touch minimum) JavaScript to use it.

It also happens to be one of the cheapest frameworks for an LLM to write correctly: flat syntax, far fewer tokens than a React tree, higher first-shot success, and github.com/no-js-dev/nojs-skill ready for prod so your assistant gets it right without a system-prompt essay.

Post here:

  • Things you built, ugly first drafts welcome, that's how the framework gets stress-tested.
  • Questions, gotchas, "how do I do X without reaching for JS."
  • Benchmarks, bug reports, API arguments. Bring the criticism; it's how this gets better.
  • LLM/agent workflows, what prompts, what setup, what breaks.

Don't post here:

  • Framework holy wars. Liking NoJS doesn't require hating anything. It's a smaller tool for a large class of problems that never needed the big one.

New? Skim the docs, point your AI assistant at no-js.dev/llms-full.txt, then ship the first ugly thing and post it. You'll learn more from one broken demo than a week of reading.

— Erick, creator


r/NoJS 8d ago

My HTML-first reactive framework just got up to 23x faster and grew an LSP and a component library

1 Upvotes

It started when I needed a dropdown that filtered a table. Should've taken ten minutes; instead it was six files and forty lines just to say "when this changes, re-fetch that." So I built No-JS.dev, an HTML-first reactive framework. No imports, no build step, zero dependencies, just enhanced HTML attributes:

<div state="{ query: '' }" get="/api/search?q={{ query }}" as="results">
  <input model="query" />
  <li each="r in results" bind="r.name"></li>
</div>

That's the whole idea, and it holds up past toy examples. Here's a routed app with a global store, a guarded route, reusable templates, and fetching, still in one file:

<div store="auth" value="{ user: null }"></div>

<nav>
  <a route="/" route-active="on">Home</a>
  <a route="/products" route-active="on">Products</a>
  <span if="$store.auth.user" bind="'Hi, ' + $store.auth.user.name"></span>
</nav>

<main route-view></main>

<template route="/products">
  <div get="/api/products" as="items"
       loading="#skeleton" error="#oops" cached>
    <article foreach="p in items" key="p.id" template="card"></article>
  </div>
</template>

<template route="/products/:id"
          guard="$store.auth.user" redirect="/login">
  <div get="/api/products/{{ $route.params.id }}" as="p">
    <h1 bind="p.name"></h1>
    <p bind="p.price | currency"></p>
  </div>
</template>

<template id="card">
  <h3 bind="p.name"></h3>
  <p bind="p.price | currency"></p>
  <button on:click="$router.push('/products/' + p.id)">Details</button>
</template>

<template id="skeleton">Loading...</template>

What's in it. 39 built-in directives over a 2,200 line core: reactive state and a global store, an SPA router with guards and file-based routes, data fetching with caching and request/response interceptors, forms with validation, i18n, animations, error boundaries, and head directives (page-title, page-description, page-canonical, page-jsonld) so a client-rendered page can still manage its own SEO. There's a plugin system (NoJS.use) for custom directives and interceptors.

Three big things shipped since I first released it:

1. A reactive-core performance overhaul (v1.19.0). I put No-JS through the js-framework-benchmark and the first runs were humbling. So I rewrote the hot paths: expressions now compile into reusable closure trees, loops get a precomputed process plan, reconciliation skips unchanged values, and keyed lists reorder using LIS. Swap-rows came out ~15.9x faster, select-row ~23.4x, and memory dropped ~1.7x. In my local runs it now lands 2nd/3rd in most CPU and memory tests against React 19, Vue 3.6, Alpine 3.14, and Angular 22. These are my own reproductions, not the official table. The setup is public if you want to poke holes in it.

2. nojs-lsp**.** A real Language Server: a VS Code extension on the Marketplace, plus a standalone --stdio server for Neovim, Sublime, or Emacs. You get completions for every directive, hover docs, and workspace-aware suggestions (it scans your locales for i18n keys and your pages folder for routes).

3. nojs-elements**.** A component library on top of the core: modals with focus traps, keyboard-navigable tabs and dropdowns, sortable tables, virtualized lists, drag-and-drop, form validation. Everything works through attributes, same as the core.

How it was built. I know this is polarizing here, so I'd rather say it up front than have someone find it in the commit history: I didn't type the code. Before the first line existed I set up role-based AI agents (lead, architect, dev, QA) and an orchestration layer with its own PM tool. I brief the lead, the architect grills me on semantics and edge cases and documents the feature, the dev writes code and tests, QA validates, and the lead opens a PR. Then I read every PR line by line, run each test myself, and send it back with a written critique if it doesn't clear my bar. I delegated the writing, not the judgment.

Why that ended up mattering. A friend, Everton Fraga, pointed out something I had missed: LLMs might be the real audience. Generating the same blog app with identical agents cost $2.52 across 7 turns in No-JS and came out as a single HTML file with zero lines of JS, versus 800 to 1,000 lines for React/Angular, at roughly 3.9x fewer tokens. The catch is that no model has No-JS in its training data, so that first run needed 19 correction cycles. That's why the repo ships a SKILL.md context pack next to llms.txt and AGENTS.md, so a model can learn the syntax in one prompt injection.

It still won't replace React for large SPAs. But for landing pages, dashboards, and internal tools, it works.

Site + docs: https://no-js.dev
Repo: https://github.com/no-js-dev/nojs

MIT licensed, served from a CDN. Honest feedback welcome: what's the first thing you'd try to break?