newX 1.3: islands to disk, server-mode islands, and an image proxy

Packages

@thexjs/hooks

SSR-safe React hooks for X apps. Every hook is safe inside renderToString / renderToReadableStream; none of them touch window, document, localStorage, or navigator during the server render pass. DOM access only happens in effects, after hydration.

terminal
bun add @thexjs/hooks

Requires React 18 or 19. For the dev UX in a new app, choose the Hooks feature from create-thexjs-app to get it pre-installed.

Hooks

HookPurpose
useDebounce(value, delayMs)Debounced value for search inputs, resize logic, etc.
useLocalStorage(key, initial)localStorage-backed state, syncs across tabs via the storage event
useMediaQuery(query)Boolean from matchMedia; false on the server, hydrates on mount
useIntersectionObserver(ref, options)Intersection entry for lazy-loading, infinite scroll, on-view analytics
useEventListener(event, handler, target?)Typed addEventListener with automatic cleanup
useClickOutside(ref, handler)Pointer-down outside a ref (dropdowns, modals)
usePrevious(value)Value from the previous render
useCopyToClipboard()[copiedText, copy]; async Clipboard API + execCommand fallback
useOnlineStatus()navigator.onLine + online/offline listeners
useServerAction(fn){ data, error, isPending } + run over a server-function client
useForm(initialValues, validate)Lightweight form state + validation (zod, valibot, or hand-written)

Example

search.tsx
import { useDebounce, useServerAction } from "@thexjs/hooks";function Search() {  const [query, setQuery] = useState("");  const q = useDebounce(query, 300);  return <input value={query} onChange={(e) => setQuery(e.target.value)} /> >;}function LikeButton() {  // `like` is a server function from the generated client  const [{ isPending, error }, run] = useServerAction(like);  return <button onClick={() => run()}>{isPending ? "..." : "Like"}</button>;}

Server actions

useServerAction expects an async function that talks to your server function endpoint, usually one from the client generated by @thexjs/core's build step (generateServerFunctionClient output). It adds the mutation-hook ergonomics: { data, error, isPending } plus a run(...args) trigger.