Skip to main content

Quickstart

This guide will walk you through building a working counter application with O!. You’ll learn the core concepts of components, state management, and rendering.

What You’ll Build

By the end of this tutorial, you’ll have a fully functional counter with increment and decrement buttons:
import { h, x, render, useState } from '@zserge/o';

const Counter = ({ name = 'Counter', initialValue = 0 }) => {
  const [value, setValue] = useState(initialValue);
  return x`
    <div className="counter">
      <h1>${name}</h1>
      <div>${value}</div>
      <div className="row">
        <button onclick=${() => setValue(value + 1)}>+</button>
        <button onclick=${() => setValue(value - 1)}>-</button>
      </div>
    </div>
  `;
};

render(h(Counter, { initialValue: 10 }), document.body);

Tutorial Steps

1

Create an HTML file

Start by creating a new counter.html file:
<!DOCTYPE html>
<html>
  <body></body>
  <script type="module">
    // Your code will go here
  </script>
</html>
The type="module" attribute enables ES module support in the browser.
2

Import O! functions

Import the necessary functions from O!:
import { h, x, render, useState } from 'https://unpkg.com/@zserge/o/o.mjs';
If you installed via npm, use:
import { h, x, render, useState } from '@zserge/o';
What each function does:
  • h() - Creates virtual DOM nodes (like React.createElement)
  • x - Tagged template for HTML-like syntax
  • render() - Renders components to the DOM
  • useState() - Manages component state
3

Define the Counter component

Create a functional component that accepts props:
const Counter = ({ name = 'Counter', initialValue = 0 }) => {
  // Component logic will go here
};
O! components are just JavaScript functions that:
  • Accept a props object as the first argument
  • Return virtual DOM nodes
  • Can use hooks like useState
4

Add state with useState

Use the useState hook to manage the counter value:
const Counter = ({ name = 'Counter', initialValue = 0 }) => {
  const [value, setValue] = useState(initialValue);
  // Return statement will go here
};
How useState works:
  • Takes an initial value (initialValue)
  • Returns an array: [currentValue, setterFunction]
  • Calling setValue() updates the state and triggers a re-render
5

Build the UI with template syntax

Use the x` ` tagged template to create your component’s HTML:
const Counter = ({ name = 'Counter', initialValue = 0 }) => {
  const [value, setValue] = useState(initialValue);
  return x`
    <div className="counter">
      <h1>${name}</h1>
      <div>${value}</div>
      <div className="row">
        <button onclick=${() => setValue(value + 1)}>+</button>
        <button onclick=${() => setValue(value - 1)}>-</button>
      </div>
    </div>
  `;
};
Template syntax notes:
  • Use className instead of class (like React)
  • Use onclick (lowercase) for event handlers
  • Embed JavaScript expressions with ${...}
  • Attribute values can be functions, strings, or numbers
6

Render to the DOM

Finally, render your component to the page:
render(h(Counter, { initialValue: 10 }), document.body);
How rendering works:
  • h(Counter, { initialValue: 10 }) creates a virtual node for your component
  • render(..., document.body) mounts it to the document body
  • Updates are automatically handled when state changes

Complete Example

Here’s the full working code:
<!DOCTYPE html>
<html>
  <body></body>
  <script type="module">
    import { h, x, render, useState } from 'https://unpkg.com/@zserge/o/o.mjs';

    const Counter = ({ name = 'Counter', initialValue = 0 }) => {
      const [value, setValue] = useState(initialValue);
      return x`
        <div className="counter">
          <h1>${name}</h1>
          <div>${value}</div>
          <div className="row">
            <button onclick=${() => setValue(value + 1)}>+</button>
            <button onclick=${() => setValue(value - 1)}>-</button>
          </div>
        </div>
      `;
    };

    render(h(Counter, { initialValue: 10 }), document.body);
  </script>
</html>

Try It Out

  1. Save the code above as counter.html
  2. Open it in your browser
  3. Click the + and - buttons to see the counter in action!

Key Concepts Learned

O! components are pure JavaScript functions that take props and return virtual DOM nodes. No classes or special syntax required.
The useState hook provides local component state. When you call the setter function, O! automatically re-renders your component with the new state.
The x` ` tagged template lets you write HTML-like markup in your JavaScript. It’s converted to h() function calls under the hood.
The h() function creates virtual DOM nodes - lightweight JavaScript objects representing your UI. O! diffs these and updates the real DOM efficiently.

Next Steps

Experiment Further

Try modifying the counter:
  • Add a reset button that sets the value back to initialValue
  • Create multiple counters with different starting values
  • Style your counter with inline styles: <div style="color: blue">
  • Add validation to prevent negative numbers

Build docs developers (and LLMs) love