Farm.js

Renderers

Choose React, Preact, Solid, Vue, or Svelte for application UI while keeping FARMJS routing, server APIs, middleware, observability, and deployment. React remains the default; Preact, Solid, Vue, and Svelte are beta renderer adapters.

Choose a renderer

RendererSelect it withRoute componentsBest fit
ReactOmit renderer.tsx, .jsxComplete FARMJS client API and integration UI support.
Preactrenderer: preact().tsx, .jsxSmall React-compatible runtime with streaming SSR.
Solidrenderer: solid().tsx, .jsxFine-grained interactive UI with FARMJS server features.
Vuerenderer: vue().vueVue SFCs, SSR, hydration, and FARMJS server features.
Svelterenderer: svelte().svelteSvelte 5 components, runes, SSR, and FARMJS server features.

The renderer controls component compilation, element creation, server rendering, and browser hydration. FARMJS continues to control route discovery, layouts, API routes, middleware, cache and storage, integrations, observability, and deployment output.

Feature support

CapabilityReactPreactSolidVueSvelte
File pages and nested layoutsAvailableAvailableAvailableAvailableAvailable
Server rendering and browser hydrationAvailableAvailableAvailableAvailableAvailable
Streaming SSRNodeNode and WebNode and WebNode and WebBuffered today
Loading, error, not-found, and slot filesAvailableAvailableAvailableAvailableAvailable
Static metadata and favicon configurationAvailableAvailableAvailableAvailableAvailable
API routes and generated typed API clientsAvailableAvailableAvailableAvailableAvailable
Server functions, middleware, cache, and storageAvailableAvailableAvailableAvailableAvailable
Observability and production Node outputAvailableAvailableAvailableAvailableAvailable
Basic create-app starterAvailableAvailableAvailableAvailableAvailable
Better Auth create-app starterAvailableNativeNativeNativeNative
Router state and programmatic navigationAvailableThrough preact/compatSolid bindingVue bindingSvelte store
Callable actions and server queriesAvailableThrough preact/compatSolid bindingVue bindingSvelte store
Client theme and i18n stateAvailableThrough preact/compatSolid bindingVue bindingSvelte store
Renderer-specific Link and form componentsAvailableThrough preact/compatNot yetNot yetNot yet
Programmatic UI routesAvailableCompatibility surfaceReact-oriented todayReact-oriented todayReact-oriented today
Markdown/MDX visual routes and docs adapterAvailableCompatibility surfaceReact-oriented todayReact-oriented todayReact-oriented today
Generated JSX metadata imagesAvailableCompatibility surfaceReact-oriented todayReact-oriented todayReact-oriented today
React Server Components and optimized boundariesAvailable experimentallyNot applicableNot applicableNot applicableNot applicable
Other integration UI providers and startersAvailableProvider-specific compatibilityReact-oriented todayReact-oriented todayReact-oriented today

Preact resolves the React-shaped bindings through preact/compat. Solid exposes signal-backed getters, Vue exposes refs and computed values, and Svelte exposes readable stores. The underlying navigation, action, query-cache, theme, and i18n transports live in the renderer-neutral @farm.js/core/renderer-client entry.

Native client bindings

Import client bindings from the selected renderer rather than importing React hooks:

// Solid
import { useAction, useRouter, useServerQuery, useTheme } from "@farm.js/solid/bindings";

// Vue
import { useAction, useRouter, useServerQuery, useTheme } from "@farm.js/vue/bindings";

// Svelte
import {
  createAction,
  createRouter,
  createServerQuery,
  createTheme,
} from "@farm.js/svelte/bindings";

Actions remain normal typed RPC calls. Solid exposes action state through reactive properties, Vue through refs, and Svelte through the callable action's readable-store subscription. Server queries share FARMJS's existing browser cache, invalidation, deduplication, stale-while-revalidate, focus, and reconnect behavior across all bindings.

Renderer capability contract

Renderer packages advertise streaming support in their descriptor instead of relying on FARMJS to guess from optional runtime exports:

import { defineRenderer } from "@farm.js/core";

export const customRenderer = defineRenderer({
  name: "custom",
  vite: "@example/renderer/vite",
  server: "@example/renderer/server",
  client: "@example/renderer/client",
  capabilities: {
    streaming: {
      node: false,
      web: true,
    },
  },
});

FARMJS builds the production client and SSR graphs in parallel by default. If a renderer's compiler plugin uses process-global mutable caches, set buildConcurrency: "serial" on its descriptor. The official Vue renderer does this because @vitejs/plugin-vue shares SFC descriptor and script caches between plugin instances.

A renderer advertising node streaming must export renderToPipeableStream() from its server entry. A renderer advertising web streaming must export renderToReadableStream() returning a WHATWG ReadableStream. FARMJS validates those declarations when the server renderer starts and uses buffered renderToString() when neither capability is enabled. Descriptors without a capabilities field remain buffered for compatibility.

Renderer-neutral server code

Keep product and server behavior outside the component runtime whenever possible:

import { createEndpoint } from "@farm.js/core";
import { createServerFn } from "@farm.js/core/server-fn";
import { z } from "zod";

const input = z.object({ name: z.string().min(1) });

const greet = createServerFn({
  input,
  async handler({ input }) {
    return { message: `Hello, ${input.name}` };
  },
});

export const POST = createEndpoint(
  "/api/greeting",
  { method: "POST", body: input },
  async ({ body }) => greet(body),
);

React, Preact, Solid, Vue, and Svelte components can call this endpoint through the same generated client. Database access, secrets, validation, cache invalidation, middleware, and the server-function handler remain on the server.

Switch renderers deliberately

The renderer option is application-wide. Do not mix React, Preact, Solid, Vue, and Svelte route components in the same route tree. Share server modules, schemas, API clients, CSS, and plain TypeScript across renderers; rewrite component and client-state code using the selected renderer's native primitives.

The Basic and Better Auth templates support every renderer directly:

pnpm create @farm.js/app@beta my-auth-app --template better-auth --renderer vue --typescript

Other integration starter templates currently target React. Add their renderer-neutral server integration to a native Basic starter when using Preact, Solid, Vue, or Svelte.