---
title: Introduction
description: An introduction to ilha, a tiny isomorphic UI library with signal reactivity and no virtual DOM.
---

import { example } from "./introduction.examples";

ilha is a tiny, isomorphic UI library for building reactive components.

You render on the server and mount in the browser with signal-based updates. There is no virtual DOM and no compiler. Markup stays close to HTML.

## What ilha is

A **component** is a function, async function, or generator that returns a view. The same component produces HTML through `renderToString()` and activates in the browser through `mount()`.

You write a function component. You declare `atom()` values inside it. Reads during render subscribe that component; writes rerun it and morph the host.

## Why it exists

Most UI stacks force you to choose between simplicity and interactivity. ilha keeps both close together: a small API, direct DOM updates, and one component for server and client.

This makes ilha a good fit when you want:

- Server-rendered markup.
- Small interactive regions.
- Explicit state.
- No virtual DOM.

## How it feels to use

A typical component reads like a small HTML-aware module:

<Preview code={example} />

The same function can render to a string on the server and mount into the DOM on the client.

## Choose the smallest component form

| Start with | Use it when |
| --- | --- |
| `const View = () => JSX` | Reusable markup inside a parent component |
| `const View = function*` | You need `yield Stream.map(...)` or `yield* when(...)` |
| `mount(el, View)` | The function is the root you hydrate or mount |

Start plain:

```tsx twoslash
const Status = () => <p>Ready</p>;
```

Add local state with `atom()`:

```tsx twoslash
import { atom } from "ilha";

const Status = () => {
  const message = atom("Ready");
  return <p>{message}</p>;
};
```

A nested function without its own `mount()` / `renderToString()` belongs to the parent component.

## Core ideas

### Isomorphic rendering

You produce HTML on the server and activate the same function in the browser.

### Fine-grained reactivity

Atoms keep updates local. Changing one value does not rerender an entire application tree.

### Function components

You write functions that return JSX. Generators `yield` streams and `yield*` Effects. Async functions can await before they return a view.

### JSX-first authoring

Prefer JSX. It escapes interpolations. Use `h()` when you cannot use JSX.

## When to use ilha

Use ilha when you want server HTML plus a few interactive regions, not a full client app by default.

## Basic mental model

1. Write a component that returns JSX.
2. Declare `atom()` values you read in the view.
3. Call `renderToString(component)` on the server.
4. Call `mount(element, component, { hydrate: true })` in the browser.
