Skip to content
Ilha
Esc
↑↓navigate↵open⌘Jpreview
On this page

Astro

Astro integration that renders and hydrates Ilha components as Astro islands.

@ilha/astro is an Astro integration for Ilha. You register it once, then import any component into an .astro page and hydrate it with a client directive.

It is a separate package from ilha. Add it when you build with Astro.

Install

npm install @ilha/astro
pnpm add @ilha/astro
yarn add @ilha/astro
bun add @ilha/astro
nub add @ilha/astro
aube add @ilha/astro

astro and ilha are peer dependencies.

Quick start

// astro.config.mjs
import { function defineConfig<const TLocales extends Locales = never, const TDriver extends SessionDriverName | SessionDriverConfig = never, const TFontProviders extends Array<FontProvider> = never>(config: AstroUserConfig<TLocales, TDriver, TFontProviders>): AstroUserConfig<TLocales, TDriver, TFontProviders>
See the full Astro Configuration API Documentation https://astro.build/config
defineConfig
} from "astro/config";
import function ilha(options?: IlhaIntegrationOptions): AstroIntegrationilha from "@ilha/astro"; export default defineConfig<never, never, never>(config: AstroUserConfig<never, never, never>): AstroUserConfig<never, never, never>
See the full Astro Configuration API Documentation https://astro.build/config
defineConfig
({
AstroUserConfig<TLocales extends Locales = never, TDriver extends SessionDriverName | SessionDriverConfig | undefined = never, TFontProviders extends Array<FontProvider> = never>.integrations?: (false | AstroIntegration | (false | AstroIntegration | null | undefined)[] | null | undefined)[] | undefined
@docs@nameintegrations@typeraw{AstroIntegration[]}@descriptionExtend Astro with custom integrations. Integrations are your one-stop-shop for adding framework support (like Solid.js), new features (like sitemaps), and new libraries (like Partytown). Read our [Integrations Guide](https://docs.astro.build/en/guides/integrations/) for help getting started with Astro Integrations. ```js // astro.config.mjs import { defineConfig } from 'astro/config'; import react from '@astrojs/react'; import mdx from '@astrojs/mdx'; export default defineConfig({ // Example: Add React + MDX support to Astro integrations: [react(), mdx()] }); ```
integrations
: [function ilha(options?: IlhaIntegrationOptions): AstroIntegrationilha()],
});

Set jsxImportSource to ilha — see Render and hydrate:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "ilha"
  }
}
// src/islands/counter.tsx
import { const atom: AtomFnatom } from "ilha";

export const 
const Counter: ({ start }: {
    start?: number;
}) => View
Counter
= ({ start: numberstart = 0 }: { start?: number | undefinedstart?: number }) => {
const const count: AtomHandle<number>count = atom<number>(init: number | Atom<number> | Effect<number, unknown, AtomRegistry> | Stream<number, unknown, AtomRegistry>, options?: AtomOptions<number> | undefined): AtomHandle<number>atom(start: numberstart); return ( <JSX.IntrinsicElements.button: ButtonHTMLAttributesbutton type?: string | undefinedtype="button" EventProps<HTMLButtonElement>.onclick?: ((event: Targeted<HTMLButtonElement, MouseEvent>) => void) | undefinedonclick={() => const count: AtomHandle<number>count.AtomHandle<number>.update: (f: (current: number) => number) => voidupdate((value: numbervalue) => value: numbervalue + 1)}> {const count: AtomHandle<number>count} </JSX.IntrinsicElements.button: ButtonHTMLAttributesbutton> ); };
---
import { Counter } from "../islands/counter";
---

<Counter client:load start={10} />

How it works

Phase What happens
Server The renderer calls renderToString(), which wraps output in a [data-ilha] host with a state snapshot.
Client The client entry finds that host inside Astro’s <astro-island> and calls mount(..., { hydrate: true }).
server                              client
──────────────────────────────────  ────────────────────────────────────
.renderToStaticMarkup(component)        @ilha/astro/client
  → renderToString(component)             → find [data-ilha] inside <astro-island>
  → data-ilha-state snapshot          → mount(host, component, { hydrate: true })
                                      → astro:unmount → unmount()

Client directives

Directive Behavior
client:load Hydrate as soon as the page loads.
client:idle Hydrate when the browser is idle.
client:visible Hydrate when the island enters the viewport.
client:media Hydrate when a media query matches.
client:only Skip SSR. Mount fresh in the browser.
---
import { Counter } from "../islands/counter";
---

<Counter client:only="@ilha/astro" start={0} />

When you mix JSX frameworks, pass include globs:

ilha({ include: ["**/ilha/**"] });

Import paths

Import path Use it for
@ilha/astro Integration (default export / getRenderer()).
@ilha/astro/client Client hydration entry (registered by Astro).
@ilha/astro/server Server renderer entry (registered by Astro).

Notes

  • Ilha components do not support Astro <slot /> forwarding. Pass data through props.
  • client:only mounts with mount(element, component) against an empty host.
  • Peer ranges: astro ^7.2.9, ilha ^0.14.0.
Topic Guide
Core ilha API ilha
SSR and hydrate Render and hydrate
Multi-page SPA routing Router

Was this page helpful?