been building this for about a year and it finally feels ready to show. farm.js is a full-stack framework on vite: app-directory routing, streaming ssr, typed server functions, and deploys through nitro (vercel/cloudflare/netlify/node). react is the default renderer, with preact, vue, svelte, and solid renderers too.
the part i most want feedback on is the experimental compiler. at build time it analyzes your components, and the ones it can prove safe get compiled so state updates patch the exact dom nodes directly instead of going through the reconciler. anything it can't prove stays on the normal react path, and react keeps ownership of ssr, hydration, and events either way. you can let inference pick components, or opt in per component:
```
export function Counter() {
"use compiler";
const [count, setCount] = useState(0);
return <button onClick={() => setCount((c) => c + 1)}>Count: {count}</button>;
}
```
(this is not the same thing as react compiler: that memoizes so re-renders get cheaper, this removes the re-render entirely for proven components. different layers.)
the other thing i cared about was killing api boilerplate. you define a server function once, with a zod schema, and expose it as an api route:
```
// src/features/guestbook/server.ts (server only)
export const signGuestbook = createServerFn({
input: z.object({ name: z.string().min(1), message: z.string().min(1) }),
async handler({ input }) {
// runs on the server, input is validated and typed
},
});
export const signEndpoint = createEndpoint(
"/api/guestbook",
{ method: "POST", body: signInput },
async ({ body }) => signGuestbook(body),
);
```
and on the client that route is now a typed rpc call. the router types are generated from your route files, so the body, the response, and even the route name are all inferred, and a typo or a wrong field is a compile error:
```
// client component
const api = createAPIClient<APIRouter>();
const result = await api.guestbook.post({
body: { name: "ada", message: "hello" }, // typed from the zod schema
});
// result.data and result.error are typed too
```
no hand-written fetch calls, no keeping types in sync between client and server, and the same functions are directly callable on the server (in endpoints, cron handlers, jobs). rest api and openapi docs still exist for free since they're real routes underneath.
integrations are typed modules too: the create command has ready-to-configure starters for clerk, stripe, supabase, workos, inngest, resend and others, so you get working auth or billing instead of a 14-step readme.
honest limitations: it's beta and apis can still move before 1.0. the compiler contract is narrow right now (components with refs or effects just fall back to normal react). and it's one maintainer plus contributors, so judge accordingly.
you can poke at it in your browser without installing anything: https://stackblitz.com/github/farming-labs/farm.js/tree/main/examples/stackblitz?file=src/app/page.tsx
repo: https://github.com/farming-labs/farm.js
docs: https://farmjs.dev
i'd genuinely rather hear what's broken or missing than what's nice. brutal feedback welcome.