Render

Finalizes the builder chain and returns a callable Island. This is always the last method in the chain — every other builder method must be called before .render().

JSX setup

ilha ships its own JSX runtime. For TypeScript projects, set jsxImportSource to "ilha":

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "ilha"
  }
}

For individual examples or files, you can use a file pragma instead:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Hello: Island<Record<string, unknown>, Record<never, never>>Hello =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => <IntrinsicElements[string]: anyp>Hello, ilha!IntrinsicElements[string]: anyp>);

JSX is the recommended authoring style for islands. The lower-level html`` helper is still available and is useful for no-build environments or places where you do not want JSX tooling. For example, you can drop a "userInput = ''; <IntrinsicElements[string]: anyp>{const userInput: ""userInput}IntrinsicElements[string]: anyp>; //

null and undefined render as empty strings. Arrays are flattened and rendered without commas.

<IntrinsicElements[string]: anyp>{["a", null, var undefinedundefined, "b"]}IntrinsicElements[string]: anyp>
//

ab

Use raw() only for trusted markup you control:

import { const raw: (value: string) => RawHtmlraw } from "ilha";

const const icon: "\"true\">…"icon = ``;

<IntrinsicElements[string]: anybutton>{function raw(value: string): RawHtmlraw(const icon: "\"true\">…"icon)} SaveIntrinsicElements[string]: anybutton>;

Signals in JSX

State entries are signal accessors. You can call them explicitly:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Counter: Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>Counter =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<number, "count">(key: "count", init?: StateInit<Record<string, unknown>, number> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>state("count", 0) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>render(({ state: IslandState<MergeState<Record<never, never>, "count", number>>state }) => <IntrinsicElements[string]: anyp>{state: IslandState<MergeState<Record<never, never>, "count", number>>state.
count: MarkedSignalAccessor
() => number (+1 overload)
count
()}IntrinsicElements[string]: anyp>);

You can also pass the accessor itself as a child; ilha will read it and escape the value:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Label: Island<Record<string, unknown>, MergeState<Record<never, never>, "label", string>>Label =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<string, "label">(key: "label", init?: StateInit<Record<string, unknown>, string> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "label", string>, Record<never, never>>state("label", "safe") .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "label", string>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "label", string>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "label", string>>render(({ state: IslandState<MergeState<Record<never, never>, "label", string>>state }) => <IntrinsicElements[string]: anyp>{state: IslandState<MergeState<Record<never, never>, "label", string>>state.label: SignalAccessor<string>label}IntrinsicElements[string]: anyp>); //

safe

Attributes

JSX attributes are escaped. Boolean true renders as a boolean attribute, while false, null, and undefined omit the attribute.

<IntrinsicElements[string]: anybutton disabled: booleandisabled={true} title: stringtitle={'a"b'}>
  Save
IntrinsicElements[string]: anybutton>
//

Use class normally. className and htmlFor are also accepted and normalized to class and for.

<IntrinsicElements[string]: anylabel htmlFor?: string | undefinedhtmlFor="email" class?: string | unknown[] | Record<string, boolean> | undefinedclass="field">
  Email
IntrinsicElements[string]: anylabel>

class also accepts arrays and object maps:

const const active: trueactive = true;

<IntrinsicElements[string]: anydiv class?: string | unknown[] | Record<string, boolean> | undefinedclass={["tab", const active: trueactive && "is-active"]}>TabIntrinsicElements[string]: anydiv>;
<IntrinsicElements[string]: anydiv class?: string | unknown[] | Record<string, boolean> | undefinedclass={{ tab: truetab: true, "is-active": const active: trueactive }}>TabIntrinsicElements[string]: anydiv>;

Function event props such as onClick={...} are intentionally omitted from the generated HTML. Use .on() for behavior instead.

Events and re-rendering

Attach DOM events with .on(), then render JSX from .render():

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Counter: Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>Counter =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<number, "count">(key: "count", init?: StateInit<Record<string, unknown>, number> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>state("count", 0) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>.on<"button@click">(selectorOrCombined: "button@click", handler: (ctx: HandlerContextFor<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, "click", Record<never, never>>) => void | Promise<void>): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>on("button@click", ({ state: IslandState<MergeState<Record<never, never>, "count", number>>state }) => { state: IslandState<MergeState<Record<never, never>, "count", number>>state.
count: MarkedSignalAccessor
(value: number) => void (+1 overload)
count
(state: IslandState<MergeState<Record<never, never>, "count", number>>state.
count: MarkedSignalAccessor
() => number (+1 overload)
count
() + 1);
}) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>render(({ state: IslandState<MergeState<Record<never, never>, "count", number>>state }) => ( <IntrinsicElements[string]: anydiv> <IntrinsicElements[string]: anyp>Count: {state: IslandState<MergeState<Record<never, never>, "count", number>>state.
count: MarkedSignalAccessor
() => number (+1 overload)
count
()}IntrinsicElements[string]: anyp> <IntrinsicElements[string]: anybutton type: stringtype="button">+IntrinsicElements[string]: anybutton> IntrinsicElements[string]: anydiv> ));

When state.count changes, only this island re-renders and morphs its host DOM.

Conditional rendering

Use normal JavaScript control flow and ternaries:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Island: Island<Record<string, unknown>, MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>Island =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<boolean, "loading">(key: "loading", init?: StateInit<Record<string, unknown>, boolean> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "loading", boolean>, Record<never, never>>state("loading", false) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "loading", boolean>, Record<never, never>>.state<string, "error">(key: "error", init?: StateInit<Record<string, unknown>, string> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, Record<never, never>>state("error", "") .IlhaBuilder<Record<string, unknown>, MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, Record<never, never>>.state<string[], "items">(key: "items", init?: StateInit<Record<string, unknown>, string[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>, Record<never, never>>state("items", [] as string[]) .IlhaBuilder<Record<string, unknown>, MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>, Record<...>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>render(({ state: IslandState<MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>state }) => { if (state: IslandState<MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>state.
loading: MarkedSignalAccessor
() => boolean (+1 overload)
loading
()) return <IntrinsicElements[string]: anyp>Loading…IntrinsicElements[string]: anyp>; if (state: IslandState<MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>state.
error: MarkedSignalAccessor
() => string (+1 overload)
error
()) return <IntrinsicElements[string]: anyp>Error: {state: IslandState<MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>state.
error: MarkedSignalAccessor
() => string (+1 overload)
error
()}IntrinsicElements[string]: anyp>; return ( <IntrinsicElements[string]: anyul> {state: IslandState<MergeState<MergeState<MergeState<Record<never, never>, "loading", boolean>, "error", string>, "items", string[]>>state.
items: MarkedSignalAccessor
() => string[] (+1 overload)
items
().Array<string>.map<JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => (
<IntrinsicElements[string]: anyli>{item: stringitem}IntrinsicElements[string]: anyli> ))} IntrinsicElements[string]: anyul> ); });

List rendering

Arrays of JSX results are joined without commas. Do not call .join(""):

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const List: Island<Record<string, unknown>, MergeState<Record<never, never>, "fruits", string[]>>List =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<string[], "fruits">(key: "fruits", init?: StateInit<Record<string, unknown>, string[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "fruits", string[]>, Record<never, never>>state("fruits", ["apple", "banana", "cherry"]) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "fruits", string[]>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "fruits", string[]>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "fruits", string[]>>render(({ state: IslandState<MergeState<Record<never, never>, "fruits", string[]>>state }) => ( <IntrinsicElements[string]: anyul> {state: IslandState<MergeState<Record<never, never>, "fruits", string[]>>state.
fruits: MarkedSignalAccessor
() => string[] (+1 overload)
fruits
().Array<string>.map<JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((fruit: stringfruit) => (
<IntrinsicElements[string]: anyli>{fruit: stringfruit}IntrinsicElements[string]: anyli> ))} IntrinsicElements[string]: anyul> ));

Each item is escaped independently, so mapped user content stays safe.

Fragments

Use fragments when a render function needs to return siblings without an extra wrapper:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Form: Island<Record<string, unknown>, Record<never, never>>Form =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<> <IntrinsicElements[string]: anyinput name: stringname="email" /> <IntrinsicElements[string]: anybutton>SubmitIntrinsicElements[string]: anybutton> ));

Child islands

Render child islands as JSX components:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Child: Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>Child =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<number, "count">(key: "count", init?: StateInit<Record<string, unknown>, number> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>state("count", 0) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "count", number>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>render(({ state: IslandState<MergeState<Record<never, never>, "count", number>>state }) => <IntrinsicElements[string]: anybutton>{state: IslandState<MergeState<Record<never, never>, "count", number>>state.
count: MarkedSignalAccessor
() => number (+1 overload)
count
()}IntrinsicElements[string]: anybutton>); const const Parent: Island<Record<string, unknown>, Record<never, never>>Parent =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<IntrinsicElements[string]: anysection> <IntrinsicElements[string]: anyh1>ParentIntrinsicElements[string]: anyh1> <const Child: Island<Record<string, unknown>, MergeState<Record<never, never>, "count", number>>Child /> IntrinsicElements[string]: anysection> ));

Child islands render inline during SSR and mount independently on the client. A state change in the child does not re-render the parent.

Pass props with normal JSX attributes:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; import { import zz } from "zod"; const
const Badge: Island<{
    label: string;
} & Record<string, unknown>, Record<never, never>>
Badge
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.input<z.ZodObject<{
    label: z.ZodString;
}, "strip", z.ZodTypeAny, {
    label: string;
}, {
    label: string;
}>>(schema: z.ZodObject<{
    label: z.ZodString;
}, "strip", z.ZodTypeAny, {
    label: string;
}, {
    label: string;
}>): IlhaBuilder<{
    label: string;
} & Record<string, unknown>, Record<never, never>, Record<never, never>> (+1 overload)
input
(import zz.
object<{
    label: z.ZodString;
}>(shape: {
    label: z.ZodString;
}, params?: z.RawCreateParams): z.ZodObject<{
    label: z.ZodString;
}, "strip", z.ZodTypeAny, {
    label: string;
}, {
    label: string;
}>
export object
object
({ label: z.ZodStringlabel: import zz.
function string(params?: z.RawCreateParams & {
    coerce?: true;
}): z.ZodString
export string
string
() }))
.
IlhaBuilder<{ label: string; } & Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<{
    label: string;
} & Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<{
    label: string;
} & Record<string, unknown>, Record<never, never>>
render
(({
input: {
    label: string;
} & Record<string, unknown>
input
}) => <IntrinsicElements[string]: anystrong>{
input: {
    label: string;
} & Record<string, unknown>
input
.label: stringlabel}IntrinsicElements[string]: anystrong>); const const Page: Island<Record<string, unknown>, Record<never, never>>Page =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => <
const Badge: Island<{
    label: string;
} & Record<string, unknown>, Record<never, never>>
Badge
label?: string | undefinedlabel="New" />);

For keyed child islands in lists, create a keyed component before rendering it:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; import { import zz } from "zod"; const
const items: {
    id: string;
    label: string;
}[]
items
= [
{ id: stringid: "a", label: stringlabel: "A" }, { id: stringid: "b", label: stringlabel: "B" }, ]; const
const Item: Island<{
    label: string;
} & Record<string, unknown>, Record<never, never>>
Item
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.input<z.ZodObject<{
    label: z.ZodString;
}, "strip", z.ZodTypeAny, {
    label: string;
}, {
    label: string;
}>>(schema: z.ZodObject<{
    label: z.ZodString;
}, "strip", z.ZodTypeAny, {
    label: string;
}, {
    label: string;
}>): IlhaBuilder<{
    label: string;
} & Record<string, unknown>, Record<never, never>, Record<never, never>> (+1 overload)
input
(import zz.
object<{
    label: z.ZodString;
}>(shape: {
    label: z.ZodString;
}, params?: z.RawCreateParams): z.ZodObject<{
    label: z.ZodString;
}, "strip", z.ZodTypeAny, {
    label: string;
}, {
    label: string;
}>
export object
object
({ label: z.ZodStringlabel: import zz.
function string(params?: z.RawCreateParams & {
    coerce?: true;
}): z.ZodString
export string
string
() }))
.
IlhaBuilder<{ label: string; } & Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<{
    label: string;
} & Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<{
    label: string;
} & Record<string, unknown>, Record<never, never>>
render
(({
input: {
    label: string;
} & Record<string, unknown>
input
}) => <IntrinsicElements[string]: anyli>{
input: {
    label: string;
} & Record<string, unknown>
input
.label: stringlabel}IntrinsicElements[string]: anyli>); const const List: Island<Record<string, unknown>, Record<never, never>>List =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<IntrinsicElements[string]: anyul> {
const items: {
    id: string;
    label: string;
}[]
items
.
Array<{ id: string; label: string; }>.map<JSX.Element>(callbackfn: (value: {
    id: string;
    label: string;
}, index: number, array: {
    id: string;
    label: string;
}[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((
item: {
    id: string;
    label: string;
}
item
) => {
const
const KeyedItem: KeyedIsland<{
    label: string;
} & Record<string, unknown>>
KeyedItem
=
const Item: Island<{
    label: string;
} & Record<string, unknown>, Record<never, never>>
Item
.
Island<{ label: string; } & Record<string, unknown>, Record<never, never>>.key(key: string): KeyedIsland<{
    label: string;
} & Record<string, unknown>>
key
(
item: {
    id: string;
    label: string;
}
item
.id: stringid);
return <
const KeyedItem: KeyedIsland<{
    label: string;
} & Record<string, unknown>>
KeyedItem
label?: string | undefinedlabel={
item: {
    id: string;
    label: string;
}
item
.label: stringlabel} />;
})} IntrinsicElements[string]: anyul> ));

Slot wrapper — .as(tag)

Embedded child islands are wrapped in a host element so ilha can hydrate and morph them independently of the parent. By default that wrapper is a with a data-ilha-slot attribute:
…child markup…
Call .as(tag) on the child island builder (anywhere before .render()) to use a different HTML tag — for valid structure ( inside ), semantics, or styling:
import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Age: Island<Record<string, unknown>, MergeState<Record<never, never>, "age", number>>Age =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.as<"span">(tag: "span"): IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>as("span") .IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<number, "age">(key: "age", init?: StateInit<Record<string, unknown>, number> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "age", number>, Record<never, never>>state("age", 0) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "age", number>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "age", number>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "age", number>>render(({ state: IslandState<MergeState<Record<never, never>, "age", number>>state }) => <>{state: IslandState<MergeState<Record<never, never>, "age", number>>state.
age: MarkedSignalAccessor
() => number (+1 overload)
age
()});
const const Parent: Island<Record<string, unknown>, Record<never, never>>Parent =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => <IntrinsicElements[string]: anyp>Age: {const Age: Island<Record<string, unknown>, MergeState<Record<never, never>, "age", number>>Age}IntrinsicElements[string]: anyp>); //

Age: 0

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const
const Row: Island<{
    label: string;
}, Record<never, never>>
Row
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.as<"li">(tag: "li"): IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>as("li") .
IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.input<{
    label: string;
}>(): IlhaBuilder<{
    label: string;
}, Record<never, never>, Record<never, never>> (+1 overload)
input
<{ label: stringlabel: string }>()
.
IlhaBuilder<{ label: string; }, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<{
    label: string;
}, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<{
    label: string;
}, Record<never, never>>
render
(({
input: {
    label: string;
}
input
}) => <>{
input: {
    label: string;
}
input
.label: stringlabel});
const const List: Island<Record<string, unknown>, Record<never, never>>List =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<IntrinsicElements[string]: anyul> {["a", "b"].Array<string>.map<JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((label: stringlabel) => (
<
const Row: Island<{
    label: string;
}, Record<never, never>>
Row
JSX.IntrinsicAttributes.key?: string | number | undefinedkey={label: stringlabel} label?: string | undefinedlabel={label: stringlabel} />
))} IntrinsicElements[string]: anyul> ));

For list items that keep local state across reorders, combine .as("li") with .key(id) on the child (see keyed child islands above):

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const
const Item: Island<{
    label: string;
}, MergeState<Record<never, never>, "n", number>>
Item
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.as<"li">(tag: "li"): IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>as("li") .
IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.input<{
    label: string;
}>(): IlhaBuilder<{
    label: string;
}, Record<never, never>, Record<never, never>> (+1 overload)
input
<{ label: stringlabel: string }>()
.
IlhaBuilder<{ label: string; }, Record<never, never>, Record<never, never>>.state<number, "n">(key: "n", init?: StateInit<{
    label: string;
}, number> | undefined): IlhaBuilder<{
    label: string;
}, MergeState<Record<never, never>, "n", number>, Record<never, never>>
state
("n", 0)
.
IlhaBuilder<{ label: string; }, MergeState<Record<never, never>, "n", number>, Record<never, never>>.on<"[data-bump]@click">(selectorOrCombined: "[data-bump]@click", handler: (ctx: HandlerContextFor<{
    label: string;
}, MergeState<Record<never, never>, "n", number>, "click", Record<never, never>>) => void | Promise<void>): IlhaBuilder<{
    label: string;
}, MergeState<Record<never, never>, "n", number>, Record<never, never>>
on
("[data-bump]@click", ({ state: IslandState<MergeState<Record<never, never>, "n", number>>state }) => {
state: IslandState<MergeState<Record<never, never>, "n", number>>state.
n: MarkedSignalAccessor
(value: number) => void (+1 overload)
n
(state: IslandState<MergeState<Record<never, never>, "n", number>>state.
n: MarkedSignalAccessor
() => number (+1 overload)
n
() + 1);
}) .
IlhaBuilder<{ label: string; }, MergeState<Record<never, never>, "n", number>, Record<never, never>>.render(fn: (ctx: RenderContext<{
    label: string;
}, MergeState<Record<never, never>, "n", number>, Record<never, never>>) => string | RawHtml): Island<{
    label: string;
}, MergeState<Record<never, never>, "n", number>>
render
(({
input: {
    label: string;
}
input
, state: IslandState<MergeState<Record<never, never>, "n", number>>state }) => (
<> {
input: {
    label: string;
}
input
.label: stringlabel}:{state: IslandState<MergeState<Record<never, never>, "n", number>>state.
n: MarkedSignalAccessor
() => number (+1 overload)
n
()}
<IntrinsicElements[string]: anybutton type: stringtype="button" data-bump: truedata-bump> + IntrinsicElements[string]: anybutton> )); const const List: Island<Record<string, unknown>, MergeState<Record<never, never>, "order", string[]>>List =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<string[], "order">(key: "order", init?: StateInit<Record<string, unknown>, string[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "order", string[]>, Record<never, never>>state("order", ["a", "b"] as string[]) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "order", string[]>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "order", string[]>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "order", string[]>>render(({ state: IslandState<MergeState<Record<never, never>, "order", string[]>>state }) => ( <IntrinsicElements[string]: anyul> {state: IslandState<MergeState<Record<never, never>, "order", string[]>>state.
order: MarkedSignalAccessor
() => string[] (+1 overload)
order
().Array<string>.map<JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((k: stringk) => {
const
const Keyed: KeyedIsland<{
    label: string;
}>
Keyed
=
const Item: Island<{
    label: string;
}, MergeState<Record<never, never>, "n", number>>
Item
.
Island<{ label: string; }, MergeState<Record<never, never>, "n", number>>.key(key: string): KeyedIsland<{
    label: string;
}>
key
(k: stringk);
return <
const Keyed: KeyedIsland<{
    label: string;
}>
Keyed
label?: string | undefinedlabel={k: stringk} />;
})} IntrinsicElements[string]: anyul> ));

The tag must be a non-empty name matching ilha’s rule: start with an ASCII letter, then letters, digits, or hyphens (same idea as built-in tags like span, li, section — not arbitrary strings). Invalid names throw at builder time.

.as() on the ilha builder is only for child island slot wrappers. List helpers such as each() (for example from Quando) use a separate .as((item, index) => …) API for mapping items to JSX — not the same method.

Function components

Small JSX helper components can return JSX or strings. They receive an object even when no props are passed, so destructuring is safe:

function 
function EmptyState({ label, }: {
    label?: string;
}): JSX.Element
EmptyState({ label: stringlabel = "Nothing here", }: { label?: string | undefinedlabel?: string; }) { return <IntrinsicElements[string]: anyp>{label: stringlabel}IntrinsicElements[string]: anyp>; } const const out: JSX.Elementout = <
function EmptyState({ label, }: {
    label?: string;
}): JSX.Element
EmptyState
/>;

For stateful, mountable UI, prefer an ilha island (ilha.render(...)) over a plain function component.

Template bindings

Inside JSX, use bind:property={signal} to create two-way bindings between form elements and signals. When the signal changes, the element updates. When the user interacts with the element, the signal updates.

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Name: Island<Record<string, unknown>, MergeState<Record<never, never>, "name", string>>Name =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<string, "name">(key: "name", init?: StateInit<Record<string, unknown>, string> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "name", string>, Record<never, never>>state("name", "Ada").IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "name", string>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "name", string>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "name", string>>render(({ state: IslandState<MergeState<Record<never, never>, "name", string>>state }) => (
<IntrinsicElements[string]: anydiv> <IntrinsicElements[string]: anyinput bind:value: SignalAccessor<string>bind:bind:value: SignalAccessor<string>value={state: IslandState<MergeState<Record<never, never>, "name", string>>state.name: SignalAccessor<string>name} /> <IntrinsicElements[string]: anyp>Hello, {state: IslandState<MergeState<Record<never, never>, "name", string>>state.
name: MarkedSignalAccessor
() => string (+1 overload)
name
()}IntrinsicElements[string]: anyp> IntrinsicElements[string]: anydiv> ));

Supported bindings

BindingElementBound propertyTrigger eventbind:value, , valueinputbind:valueAsNumbervalueAsNumberinputbind:valueAsDatevalueAsDateinputbind:checkedcheckedchangebind:group, checked / valuechangebind:openopentogglebind:filesfileschangebind:thisAny elementelement reference—

The element type is detected at runtime — no configuration needed.

Areia in nested child islands: use bind:checked={state.flag} on and bind:group={state.tab} on (recent areia mounts Switch.Root / Tabs.Root when bind props are present). Controlled checked + onCheckedChange or value + onValueChange still work.

Radio and checkbox groups

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Plan: Island<Record<string, unknown>, MergeState<Record<never, never>, "plan", string>>Plan =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<string, "plan">(key: "plan", init?: StateInit<Record<string, unknown>, string> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "plan", string>, Record<never, never>>state("plan", "pro").IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "plan", string>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "plan", string>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "plan", string>>render(({ state: IslandState<MergeState<Record<never, never>, "plan", string>>state }) => (
<> <IntrinsicElements[string]: anyinput type: stringtype="radio" name: stringname="plan" value: stringvalue="free" bind:group: SignalAccessor<string>bind:bind:group: SignalAccessor<string>group={state: IslandState<MergeState<Record<never, never>, "plan", string>>state.plan: SignalAccessor<string>plan} /> <IntrinsicElements[string]: anyinput type: stringtype="radio" name: stringname="plan" value: stringvalue="pro" bind:group: SignalAccessor<string>bind:bind:group: SignalAccessor<string>group={state: IslandState<MergeState<Record<never, never>, "plan", string>>state.plan: SignalAccessor<string>plan} /> )); const const Tags: Island<Record<string, unknown>, MergeState<Record<never, never>, string, string[]>>Tags =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<string[], string>(key: string, init?: StateInit<Record<string, unknown>, string[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, string, string[]>, Record<never, never>>state<string[]>("tags", ["ts"]) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, string, string[]>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, string, string[]>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, string, string[]>>render(({ state: IslandState<MergeState<Record<never, never>, string, string[]>>state }) => ( <> <IntrinsicElements[string]: anyinput type: stringtype="checkbox" name: stringname="tag" value: stringvalue="js" bind:group: SignalAccessor<string[]>bind:bind:group: SignalAccessor<string[]>group={state: IslandState<MergeState<Record<never, never>, string, string[]>>state.SignalAccessor<string[]>tags} /> <IntrinsicElements[string]: anyinput type: stringtype="checkbox" name: stringname="tag" value: stringvalue="ts" bind:group: SignalAccessor<string[]>bind:bind:group: SignalAccessor<string[]>group={state: IslandState<MergeState<Record<never, never>, string, string[]>>state.SignalAccessor<string[]>tags} /> <IntrinsicElements[string]: anyinput type: stringtype="checkbox" name: stringname="tag" value: stringvalue="rust" bind:group: SignalAccessor<string[]>bind:bind:group: SignalAccessor<string[]>group={state: IslandState<MergeState<Record<never, never>, string, string[]>>state.SignalAccessor<string[]>tags} /> ));

Nested fields with .select()

When state holds an object or array, bind to a nested slice with .select() instead of replacing the whole value on every keystroke:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const
const Profile: Island<Record<string, unknown>, MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>>
Profile
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<{
    name: string;
    role: string;
}, "user">(key: "user", init?: StateInit<Record<string, unknown>, {
    name: string;
    role: string;
}> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>, Record<never, never>>
state
("user", { name: stringname: "Ada", role: stringrole: "dev" })
.
IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "user", { name: string; role: string; }>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>>
render
(({
state: IslandState<MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>>
state
}) => (
<IntrinsicElements[string]: anydiv> <IntrinsicElements[string]: anyinput bind:value: MarkedSignalAccessor<string>bind:bind:value: MarkedSignalAccessor<string>value={
state: IslandState<MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>>
state
.
user: SignalAccessor<{
    name: string;
    role: string;
}>
user
.
MarkedSignalAccessor<{ name: string; role: string; }>.select<string>(selector: (state: {
    name: string;
    role: string;
}) => string): MarkedSignalAccessor<string>
select
((
u: {
    name: string;
    role: string;
}
u
) =>
u: {
    name: string;
    role: string;
}
u
.name: stringname)} />
<IntrinsicElements[string]: anyp>{
state: IslandState<MergeState<Record<never, never>, "user", {
    name: string;
    role: string;
}>>
state
.
user: MarkedSignalAccessor
() => {
    name: string;
    role: string;
} (+1 overload)
user
().name: stringname}IntrinsicElements[string]: anyp> IntrinsicElements[string]: anydiv> ));

In a list, select the item field you need inside .map():

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const
const Todos: Island<Record<string, unknown>, MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>>
Todos
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<{
    text: string;
    completed: boolean;
}[], "todos">(key: "todos", init?: StateInit<Record<string, unknown>, {
    text: string;
    completed: boolean;
}[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>, Record<never, never>>
state
("todos", [{ text: stringtext: "Learn ilha", completed: booleancompleted: false }])
.
IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "todos", { text: string; completed: boolean; }[]>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>>
render
(({
state: IslandState<MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>>
state
}) => (
<IntrinsicElements[string]: anyul> {
state: IslandState<MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>>
state
.
todos: MarkedSignalAccessor
() => {
    text: string;
    completed: boolean;
}[] (+1 overload)
todos
().
Array<{ text: string; completed: boolean; }>.map<JSX.Element>(callbackfn: (value: {
    text: string;
    completed: boolean;
}, index: number, array: {
    text: string;
    completed: boolean;
}[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((
todo: {
    text: string;
    completed: boolean;
}
todo
, index: numberindex) => (
<IntrinsicElements[string]: anyli JSX.IntrinsicAttributes.key?: string | number | undefinedkey={
todo: {
    text: string;
    completed: boolean;
}
todo
.text: stringtext}>
<IntrinsicElements[string]: anyinput type: stringtype="checkbox" bind:checked: MarkedSignalAccessor<boolean>bind:bind:checked: MarkedSignalAccessor<boolean>checked={
state: IslandState<MergeState<Record<never, never>, "todos", {
    text: string;
    completed: boolean;
}[]>>
state
.
todos: SignalAccessor<{
    text: string;
    completed: boolean;
}[]>
todos
.
MarkedSignalAccessor<{ text: string; completed: boolean; }[]>.select<boolean>(selector: (state: {
    text: string;
    completed: boolean;
}[]) => boolean): MarkedSignalAccessor<boolean>
select
(
(
t: {
    text: string;
    completed: boolean;
}[]
t
) =>
t: {
    text: string;
    completed: boolean;
}[]
t
[index: numberindex].completed: booleancompleted,
)} /> {
todo: {
    text: string;
    completed: boolean;
}
todo
.text: stringtext}
IntrinsicElements[string]: anyli> ))} IntrinsicElements[string]: anyul> ));

The selector must traverse nested state (for example (u) => u.name or (t) => t[i].completed). Writes update only that path — siblings and unrelated fields stay intact.

Element references

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Focus: Island<Record<string, unknown>, MergeState<Record<never, never>, "ref", HTMLInputElement | null>>Focus =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<HTMLInputElement | null, "ref">(key: "ref", init?: StateInit<Record<string, unknown>, HTMLInputElement | null> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "ref", HTMLInputElement | null>, Record<never, never>>state("ref", null as HTMLInputElement | null) .IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "ref", HTMLInputElement | null>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "ref", HTMLInputElement | null>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "ref", HTMLInputElement | null>>render(({ state: IslandState<MergeState<Record<never, never>, "ref", HTMLInputElement | null>>state }) => <IntrinsicElements[string]: anyinput bind:this: SignalAccessor<HTMLInputElement | null>bind:bind:this: SignalAccessor<HTMLInputElement | null>this={state: IslandState<MergeState<Record<never, never>, "ref", HTMLInputElement | null>>state.ref: SignalAccessor<HTMLInputElement | null>ref} />);

External signals

Any signal created with signal() works as a binding target, including nested slices via .select():

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha, { function signal<T>(initial: T): SignalAccessor<T>
Create a free-standing reactive signal that lives outside any island. Useful for sharing state across islands without prop drilling, or for binding form inputs to module-level state via the `bind:value=${signal}` template syntax. The returned accessor is a getter when called with no arguments and a setter when called with one. Reading it inside a `.derived()`, `.effect()`, or `.render()` automatically subscribes the surrounding reactive scope — so when the signal changes, dependents re-run as if it were local state.
signal
} from "ilha"; const const username: SignalAccessor<string>username = signal<string>(initial: string): SignalAccessor<string>
Create a free-standing reactive signal that lives outside any island. Useful for sharing state across islands without prop drilling, or for binding form inputs to module-level state via the `bind:value=${signal}` template syntax. The returned accessor is a getter when called with no arguments and a setter when called with one. Reading it inside a `.derived()`, `.effect()`, or `.render()` automatically subscribes the surrounding reactive scope — so when the signal changes, dependents re-run as if it were local state.
signal
("");
const const LoginForm: Island<Record<string, unknown>, Record<never, never>>LoginForm =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<IntrinsicElements[string]: anyinput bind:value: SignalAccessor<string>bind:bind:value: SignalAccessor<string>value={const username: SignalAccessor<string>username} placeholder: stringplaceholder="Username" /> )); const
const profile: SignalAccessor<{
    user: {
        name: string;
    };
}>
profile
=
signal<{
    user: {
        name: string;
    };
}>(initial: {
    user: {
        name: string;
    };
}): SignalAccessor<{
    user: {
        name: string;
    };
}>
Create a free-standing reactive signal that lives outside any island. Useful for sharing state across islands without prop drilling, or for binding form inputs to module-level state via the `bind:value=${signal}` template syntax. The returned accessor is a getter when called with no arguments and a setter when called with one. Reading it inside a `.derived()`, `.effect()`, or `.render()` automatically subscribes the surrounding reactive scope — so when the signal changes, dependents re-run as if it were local state.
signal
({
user: {
    name: string;
}
user
: { name: stringname: "Ada" } });
const const Settings: Island<Record<string, unknown>, Record<never, never>>Settings =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<IntrinsicElements[string]: anyinput bind:value: MarkedSignalAccessor<string>bind:bind:value: MarkedSignalAccessor<string>value={
const profile: SignalAccessor<{
    user: {
        name: string;
    };
}>
profile
.
MarkedSignalAccessor<{ user: { name: string; }; }>.select<string>(selector: (state: {
    user: {
        name: string;
    };
}) => string): MarkedSignalAccessor<string>
select
((
p: {
    user: {
        name: string;
    };
}
p
) =>
p: {
    user: {
        name: string;
    };
}
p
.
user: {
    name: string;
}
user
.name: stringname)}
placeholder: stringplaceholder="Name" /> ));

html`` interop

JSX and html`` values compose. You can render an html`` result inside JSX, and JSX returns the same RawHtml shape:

import { const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtmlhtml } from "ilha";

const const result: JSX.Elementresult = <IntrinsicElements[string]: anydiv>{const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtmlhtml`${"safe"}`}IntrinsicElements[string]: anydiv>;

This is useful when incrementally migrating older html`` templates to JSX, or when sharing small trusted fragments between the two authoring styles.

Async rendering

If the island uses async .derived() values, calling the island as a function awaits all of them before rendering:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha from "ilha"; const const Island: Island<Record<string, unknown>, Record<never, never>>Island =
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    ... 4 more ...;
    onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.derived<"user", any>(key: "user", fn: DerivedFn<Record<string, unknown>, Record<never, never>, any>): IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never> & Record<"user", any>>derived("user", async () => { const const res: Responseres = await function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch)
fetch
("/api/user");
return const res: Responseres.Body.json(): Promise<any>
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/json)
json
();
}) .IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never> & Record<"user", any>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never> & Record<"user", any>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(({ derived: IslandDerived<Record<never, never> & Record<"user", any>>derived }) => { if (derived: IslandDerived<Record<never, never> & Record<"user", any>>derived.user: DerivedAccessor<any>user.loading: booleanloading) return <IntrinsicElements[string]: anyp>Loading…IntrinsicElements[string]: anyp>; return <IntrinsicElements[string]: anyp>{derived: IslandDerived<Record<never, never> & Record<"user", any>>derived.user: () => any (+1 overload)user()?.name}IntrinsicElements[string]: anyp>; }); // Async — waits for derived values const const html: stringhtml = await
const Island: Island
(props?: Partial<Record<string, unknown>> | undefined) => string | Promise<string>
Island
();
// Sync — derived renders in loading state const const html2: stringhtml2 = const Island: Island<Record<string, unknown>, Record<never, never>>Island.Island<Record<string, unknown>, Record<never, never>>.toString(props?: Partial<Record<string, unknown>> | undefined): stringtoString();

What .render() returns

Calling .render() produces an Island object with these methods:

island(props?) // renders to string, async if derived values are async
island.toString(props?) // always renders synchronously
island.mount(host, props?) // mounts into a DOM element, returns unmount()
island.hydratable(props, options) // renders wrapped in hydration container

Notes

  • .render() must be called exactly once and always last in the chain.
  • JSX output follows ilha's escaping rules; use raw() only for trusted markup.
  • Use .on() for DOM events. JSX onClick-style function props are not how ilha attaches behavior.
  • The render function runs on every re-render triggered by a signal change. Keep it fast and free of side effects — use .effect() or .onMount() for side effects instead.
  • During SSR the render function runs synchronously. Avoid browser-only APIs (window, document) at the top level of the render function.
  • The render function does not receive host — if you need the host element, use .onMount() or .effect().