---
title: Installation
description: Install ilha and start building with official templates for Vite, Hono, Nitro, and Elysia.
order: 102
---

import { MultiCopy } from "imprensa/components";

# Installation

ilha can be installed with your package manager of choice. For a beta project, start from a template when possible so SSR, mounting, and deployment wiring are already in place.

## Install

Install with your package manager:

<MultiCopy
  values={{
    npm: "npm install ilha",
    pnpm: "pnpm add ilha",
    bun: "bun add ilha",
  }}
/>

## Templates

If you want to start from a ready-made project instead of wiring everything manually, use one of the official templates.

| Template                                                            | Command                                            | Sandbox                                                                     |
| ------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------- |
| [Vite](https://github.com/ilhajs/ilha/tree/main/templates/vite)     | `npx giget@latest gh:ilhajs/ilha/templates/vite`   | [Open](https://stackblitz.com/github/ilhajs/ilha/tree/main/templates/vite)  |
| [Hono](https://github.com/ilhajs/ilha/tree/main/templates/hono)     | `npx giget@latest gh:ilhajs/ilha/templates/hono`   | [Open](https://stackblitz.com/github/ilhajs/ilha/tree/main/templates/hono)  |
| [Nitro](https://github.com/ilhajs/ilha/tree/main/templates/nitro)   | `npx giget@latest gh:ilhajs/ilha/templates/nitro`  | [Open](https://stackblitz.com/github/ilhajs/ilha/tree/main/templates/nitro) |
| [Elysia](https://github.com/ilhajs/ilha/tree/main/templates/elysia) | `npx giget@latest gh:ilhajs/ilha/templates/elysia` | —                                                                           |

Templates are the fastest way to get a working project structure for SSR, routing, and deployment targets without setting everything up from scratch.

## Requirements

ilha is designed for modern JavaScript and TypeScript projects.

- Use it in apps that can run ESM modules.
- Use TypeScript if you want the best editor support.
- Use a browser environment for mounting and hydration.
- Keep props and hydration snapshots JSON-serializable when rendering on the server.

## Import

```ts twoslash
import ilha, {
  html,
  raw,
  css,
  mount,
  from,
  context,
} from "ilha";
```

Use the default export for the builder chain, and named exports for helpers such as `html`, `raw`, and `mount`.

## Minimal example

```tsx twoslash
import ilha from "ilha";

const Counter = ilha
  .state("count", 0)
  .on("button@click", ({ state }) =>
    state.count(state.count() + 1),
  )
  .render(({ state }) => (
    <div>
      <p>Count: {state.count()}</p>
      <button>Increment</button>
    </div>
  ));
```

## Server-side rendering

Render the island to an HTML string with `toString()`:

```tsx twoslash
import ilha from "ilha";

const Counter = ilha
  .state("count", 0)
  .on("button@click", ({ state }) =>
    state.count(state.count() + 1),
  )
  .render(({ state }) => (
    <div>
      <p>Count: {state.count()}</p>
      <button>Increment</button>
    </div>
  ));
// ---cut---
const htmlOutput = Counter.toString();
```

If your island uses async derived values, you can also await the island itself:

```tsx twoslash
import ilha from "ilha";

const Counter = ilha
  .state("count", 0)
  .on("button@click", ({ state }) =>
    state.count(state.count() + 1),
  )
  .render(({ state }) => (
    <div>
      <p>Count: {state.count()}</p>
      <button>Increment</button>
    </div>
  ));
// ---cut---
const htmlOutput = await Counter();
```

## Client-side mounting

Mount the island into a DOM element:

```tsx twoslash
import ilha from "ilha";

const Counter = ilha
  .state("count", 0)
  .on("button@click", ({ state }) =>
    state.count(state.count() + 1),
  )
  .render(({ state }) => (
    <div>
      <p>Count: {state.count()}</p>
      <button>Increment</button>
    </div>
  ));
// ---cut---
const root = document.getElementById("app");
if (root) {
  const unmount = Counter.mount(root);
}
```

The returned function stops listeners, effects, and other active behavior. Call it when removing the host element manually or when integrating ilha into another router.
