v1.2.0 · stable

Azox
The Sound of Future Web

A web framework built from scratch. No Virtual DOM, no diffing, no runtime dependencies. Every binding compiles to a signal that writes to exactly one DOM node.

$npx azoxjs create my-app

0

dependencies

2.2 KB

runtime, gzipped

408

tests passing

MIT

licence

01 — Live

See it work

The counter below is a real Azox page, compiled with the same compiler you install. Clicking updates one text node — nothing else on this page is touched.

0

No Virtual DOM was consulted. The effect bound to that number is the only thing that ran.

pages/index.azox
<script>
  import { signal } from 'azox/reactivity';

  const count = signal(0);
</script>

<span class="readout">{count()}</span>

<button on:click={() => count.set(count() + 1)}>
  Add one
</button>

02 — Comparison

The same idea, two ways

Most frameworks re-run your component and compare the result. Azox compiles the comparison away entirely.

React — re-run and diff
function Counter() {
  const [n, setN] = useState(0);

  // This whole function runs again on
  // every click. React then compares
  // the returned tree with the last one
  // to work out what changed.
  return (
    <button onClick={() => setN(n + 1)}>
      Count: {n}
    </button>
  );
}
Azox — write to the node
<script>
  import { signal } from 'azox/reactivity';
  const n = signal(0);
</script>

<!-- Compiles to one effect holding a
     reference to one text node. On a
     click, that node is assigned to.
     Nothing is re-run or compared. -->
<button on:click={() => n.set(n() + 1)}>
  Count: {n()}
</button>

Read why this matters for the reasoning, or the reactivity docs for the mechanics.

03 — Design

Why it is different

Six decisions that shape everything else about the framework.

01

Fine-grained by default

Each binding becomes its own effect, holding a direct reference to the text node or attribute it owns. A signal change writes to that node and stops.

02

Components vanish at build time

A component is inlined into its caller. There is no component instance at runtime, no lifecycle, and nothing to reconcile — the output matches hand-written markup.

03

Zero dependencies

The CLI, the compiler and the runtime are plain JavaScript against the standard library. Nothing is pulled in behind your back.

04

Its own syntax

.azox files are HTML with {expr} interpolation and on:event bindings. Not JSX, and no template DSL to memorise.

05

Server-rendered first

Every page ships real HTML. The client module then wires up the bindings on top of it, so content is there before JavaScript runs.

06

Static output, anywhere

A build is plain HTML, JS and assets with clean URLs. It works on any static host with no rewrite rules or adapters.

04 — Structure

What a project looks like

The file layout is the routing table, and there is no configuration file to learn.

project
my-app/
├── pages/
│   ├── index.azox      →  /
│   ├── about.azox      →  /about
│   └── blog/
│       ├── index.azox  →  /blog
│       └── first.azox  →  /blog/first
├── components/
│   └── Card.azox
└── public/
    └── style.css       →  /style.css
components/Card.azox
<script>
  const { title, body } = props();
</script>

<article class="card">
  <h2>{title}</h2>
  <p>{body}</p>
</article>

05 — Next

Where to go next