Getting Started

Build your first Zoijs app in a few minutes — it runs straight in the browser.

Install#

With npm:

npm install @zoijs/core

Or with no install at all — load it from a CDN with an import map:

<!DOCTYPE html>
<html>
  <head>
    <script type=class="tok-string">"importmap">
      { "imports": { "@zoijs/core": "https://esm.sh/@zoijs/core@1" } }
    </script>
  </head>
  <body>
    <div id=class="tok-string">"app"></div>
    <script type=class="tok-string">"module" src=class="tok-string">"./app.js"></script>
  </body>
</html>
Pin a version (@zoijs/core@1) in production — never ship @latest to users.

Your first app#

Create app.js next to that HTML file:

import { html, mount, createState } from "@zoijs/core";

function Counter() {
  const count = createState(0);

  return html`
    <button onclick=${() => count.set(count.get() + 1)}>
      Clicked ${() => count.get()} times
    </button>
  `;
}

mount(Counter, "#app");

Open the HTML file in a browser. That's a complete, working counter.

Run it locally#

Any static file server works. The simplest:

npx serve .

Then open the printed URL. It runs the moment the page loads.

The three ideas#

That tiny app uses the whole core mental model:

FunctionWhat it does
html`...`Write real HTML in a tagged template. Parsed once.
createState(value)A reactive value with get() / set().
mount(component, target)Render a component into the page. Returns unmount().

The one rule#

Wrap a value in an arrow function to make it live:

${() => count.get()}   // live — updates when count changes
${count.get()}         // static — rendered once, never updates

Components run once; there is no re-render. The () => is how Zoijs knows a binding should react. That's the single most important concept.

Next: read the Core API for all seven functions, or jump to the Task Board example.