Alpha is live

Build modern UI, your way.

Ilha is a tiny island architecture library that renders to plain HTML on the server and hydrates on the client with zero flicker. The core is under 2,500 lines of code — small enough to paste into any AI prompt. And when you need more, the extras are included: routing, typed forms, and shared state management.

Small enough to think with.

At under 2,500 lines of code, the entire source fits in a single AI context window, so your assistant can reason about the whole framework, not just the docs.

Fully open-source.

Every line is free. No paywalls, no hidden tiers.

No build step. No JSX. No virtual DOM.

Runs from a single import — no transform, no toolchain to wrestle with.

Works with any backend.

TypeScript, PHP, Ruby, Elixir, Rust, Go — Ilha fits your stack regardless.

Renders anywhere.

Render to plain HTML on the server, hydrate on the client — with zero flicker. Edge rendering supported too.

import { mount } from "ilha";
import { Counter } from "./hero";

// Client side (lazy mount)
mount({ Counter });
// Server side (only initial state)
Counter.toString();
// Server side hydratable (execute derived)
await Counter.hydratable();

Signals, not a virtual DOM.

Fine-grained reactivity via alien-signals. No diffing, no overhead, no surprises.

const Search = ilha
  .state("query", "")
  .derived("results", async ({ state, signal }) => {
    const url = `/api/search?q=${state.query()}`;
    const res = await fetch(url, { signal });
    return res.json() as Promise<string[]>;
  })
  .effect(({ state }) => {
    const title = `Search: ${state.query() || ""}`;
    document.title = title;
  })
  .bind("[name=q]", "query")
  .render(({ state, derived }) => html`
    <input name="q" placeholder="Search…" />
    <!--Render results-->
  `);

Batteries included.

Ilha goes beyond UI templating. Get routing, typed form binding, and zustand-shaped state management out of the box — no extra setup required.

Install with:

// vite.config.ts
import { pages } from "@ilha/router/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [pages()],
});

// main.ts
// Add routes in src/pages/ and import registered routes
import { pageRouter } from "ilha:pages";

Start a new Ilha project

Open Sandbox