Preact
Using Preact components as islands in Avalon.
Setup
Preact is Avalon's default SSR renderer and is always available. No extra configuration needed.
const plugins = await avalon({
integrations: ['preact'], // optional — included by default
});
Writing a Preact island
Use the /** @jsxImportSource preact */ pragma at the top of your file:
/** @jsxImportSource preact */
import { useState } from 'preact/hooks';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}
Using the island
import Counter from '../islands/Counter.tsx';
export default function Page() {
return (
<div>
<Counter island={{ condition: 'on:client' }} />
</div>
);
}
Signals
Preact Signals work inside islands for fine-grained reactivity:
/** @jsxImportSource preact */
import { signal } from '@preact/signals';
const count = signal(0);
export default function Counter() {
return (
<button onClick={() => count.value++}>
Count: {count}
</button>
);
}
Install signals with:
bun add @preact/signals
Why Preact for pages?
Avalon uses Preact for page and layout rendering (not just islands) because it's lightweight and fast on the server. Pages and layouts don't need a pragma — they use Preact's JSX transform automatically.