newX 1.3 — islands to disk, server-mode islands, image proxy

Islands

Islands architecture

The server renders your full page as HTML, then only the pieces you mark as islands hydrate in the browser. Everything else ships zero JavaScript.

Why islands

A page full of interactive widgets doesn't need to ship one giant bundle. Each island is a small, self-contained hydration entry: it imports only what it needs, hydrates in place, and nothing on the page outside an island is ever re-rendered on the client. That keeps first paint fast and the JS budget predictable.

Creating an island

Wrap a component in <Island> and register it on the same page or layout with export const islands. Only registered islands get a hydration bundle, so an unregistered component never ships client JS even if you wrap it.

src/components/like-button.tsx
import { useState } from "react";export default function LikeButton() {  const [count, setCount] = useState(0);  return (    <button onClick={() => setCount((c) => c + 1)} className="rounded-full border px-4 py-2">      Like {count}    </button>  );}
src/pages/blog/[slug].tsx
import { Island } from "@thexjs/core";import { LikeButton } from "../../components/like-button";export const islands = { LikeButton };export default function BlogPost({ post }) {  return (    <article>      <h1 className="text-3xl font-bold">{post.title}</h1>      <div>{post.body}</div>      <Island name="LikeButton" client="visible">        <LikeButton /> >      </Island>    </article>  );}

Hydration triggers

The client prop picks when the island hydrates:

  • client="visible" — hydrate when the island scrolls into view. Good for content below the fold.
  • client="idle" — hydrate when the browser goes idle. Good for widgets the user isn't waiting on.
  • client="load" — hydrate immediately on page load. Use for the first thing the user interacts with.

How hydration works

At build time x bundles each island separately, server-renders the page to static HTML with the island's markup inline, and drops in a small loader script. In the browser the loader fetches the island's chunk on demand and hydrates only that subtree. Islands can be nested and reused across routes; each registered component gets exactly one entry per route.