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().

Basic usage

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
, {
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
} from "ilha";
const
const MyIsland: Island<Record<string, unknown>, MergeState<Record<string, never>, "x", number>>
MyIsland
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.state<number, "x">(key: "x", init?: StateInit<Record<string, unknown>, number> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<string, never>, "x", number>, Record<string, never>>
state
("x", 1)
.
IlhaBuilder<Record<string, unknown>, MergeState<Record<string, never>, "x", number>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<string, never>, "x", number>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<string, never>, "x", number>>
render
(({
state: IslandState<MergeState<Record<string, never>, "x", number>>
state
}) =>
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<p>${
state: IslandState<MergeState<Record<string, never>, "x", number>>
state
.
x: SignalAccessor<number>
x
}</p>`);

Render context

The render function receives a RenderContext with everything declared in the builder chain:

{
  state: IslandState; // reactive state signals
  derived: IslandDerived; // derived value envelopes
  input: TInput; // resolved input props
}

All three are always present, even if not declared. An island with no state gets an empty state object, and so on.

Return type

The render function must return a string or a RawHtml object. In practice this means returning either a plain template literal or an html\`` tagged template:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
, {
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
,
const raw: (value: string) => RawHtml
raw
} from "ilha";
// Plain string — no escaping const
const A: Island<Record<string, unknown>, Record<string, never>>
A
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() => `<p>hello</p>`);
// html`` — safe interpolation with auto-escaping const
const B: Island<Record<string, unknown>, Record<string, never>>
B
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(({
state: IslandState<Record<string, never>>
state
}) =>
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<p>${
state: IslandState<Record<string, never>>
state
}</p>`);
// raw() — trusted markup inside html`` const
const C: Island<Record<string, unknown>, Record<string, never>>
C
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() =>
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<div>${
function raw(value: string): RawHtml
raw
("<em>trusted</em>")}</div>`);

Use html\`` whenever you interpolate dynamic values. Plain strings are fine for fully static markup.

Conditional rendering

Use standard JavaScript expressions inside the render function:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
, {
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
} from "ilha";
const
const Island: Island<Record<string, unknown>, MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.state<boolean, "loading">(key: "loading", init?: StateInit<Record<string, unknown>, boolean> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<string, never>, "loading", boolean>, Record<string, never>>
state
("loading", false)
.
IlhaBuilder<Record<string, unknown>, MergeState<Record<string, never>, "loading", boolean>, Record<string, never>>.state<string, "error">(key: "error", init?: StateInit<Record<string, unknown>, string> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, Record<string, never>>
state
("error", "")
.
IlhaBuilder<Record<string, unknown>, MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, Record<string, never>>.state<string[], "items">(key: "items", init?: StateInit<Record<string, unknown>, string[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>, Record<string, never>>
state
("items", [] as string[])
.
IlhaBuilder<Record<string, unknown>, MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>, Record<...>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
render
(({
state: IslandState<MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
state
}) => {
if (
state: IslandState<MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
state
.
loading: MarkedSignalAccessor
() => boolean (+1 overload)
loading
()) return
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<p>Loading…</p>`;
if (
state: IslandState<MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
state
.
error: MarkedSignalAccessor
() => string (+1 overload)
error
()) return
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<p>Error: ${
state: IslandState<MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
state
.
error: SignalAccessor<string>
error
}</p>`;
return
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`
<ul> ${
state: IslandState<MergeState<MergeState<MergeState<Record<string, never>, "loading", boolean>, "error", string>, "items", string[]>>
state
.
items: MarkedSignalAccessor
() => string[] (+1 overload)
items
().
Array<string>.map<RawHtml>(callbackfn: (value: string, index: number, array: string[]) => RawHtml, thisArg?: any): RawHtml[]

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: string
item
) =>
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<li>${
item: string
item
}</li>`)}
</ul> `; });

List rendering

Arrays of html\`` results are joined without commas. This is the canonical list rendering pattern:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
, {
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
} from "ilha";
const
const List: Island<Record<string, unknown>, MergeState<Record<string, never>, "fruits", string[]>>
List
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.state<string[], "fruits">(key: "fruits", init?: StateInit<Record<string, unknown>, string[]> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<string, never>, "fruits", string[]>, Record<string, never>>
state
("fruits", ["apple", "banana", "cherry"]).
IlhaBuilder<Record<string, unknown>, MergeState<Record<string, never>, "fruits", string[]>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<string, never>, "fruits", string[]>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<string, never>, "fruits", string[]>>
render
(
({
state: IslandState<MergeState<Record<string, never>, "fruits", string[]>>
state
}) =>
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`
<ul> ${
state: IslandState<MergeState<Record<string, never>, "fruits", string[]>>
state
.
fruits: MarkedSignalAccessor
() => string[] (+1 overload)
fruits
().
Array<string>.map<RawHtml>(callbackfn: (value: string, index: number, array: string[]) => RawHtml, thisArg?: any): RawHtml[]

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: string
fruit
) =>
const html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml
html
`<li>${
fruit: string
fruit
}</li>`)}
</ul> `, );

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<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, 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;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.derived<"user", any>(key: "user", fn: DerivedFn<Record<string, unknown>, Record<string, never>, any>): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never> & Record<"user", any>>
derived
("user", async () => {
const
const res: Response
res
= await
function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
fetch
("/api/user");
return
const res: Response
res
.
Body.json(): Promise<any>
json
();
}) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never> & Record<"user", any>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never> & Record<"user", any>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(({
derived: IslandDerived<Record<string, never> & Record<"user", any>>
derived
}) => {
if (
derived: IslandDerived<Record<string, never> & Record<"user", any>>
derived
.
user: DerivedValue<any>
user
.
DerivedValue<any>.loading: boolean
loading
) return `<p>Loading…</p>`;
return `<p>${
derived: IslandDerived<Record<string, never> & Record<"user", any>>
derived
.
user: DerivedValue<any>
user
.
DerivedValue<any>.value: any
value
?.name}</p>`;
}); // Async — waits for derived values const
const html: string
html
= await
const Island: Island
(props?: Partial<Record<string, unknown>> | undefined) => string | Promise<string>
Island
();
// Sync — derived renders in loading state const
const html2: string
html2
=
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
.
Island<Record<string, unknown>, Record<string, never>>.toString(props?: Partial<Record<string, unknown>> | undefined): string
toString
();

What .render() returns

Calling .render() produces an Island object with three 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.
  • 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().