Getting Started
Create a Farm.js app, understand the files that matter, and run the development server.
Farm requires Node.js 22.13 or newer. This is the first Node 22 release that exposes
the built-in node:sqlite module without an experimental command-line flag.
Create an app
Farm keeps the first project small: an app directory, a config file, package metadata, and TypeScript. Vite config and platform config are optional escape hatches, not required setup.
pnpm create @farm.js/app my-app --template basic --typescript
cd my-app
pnpm devThis command explicitly selects the minimal Basic starter. Use pnpm create, not pnpm add: pnpm
resolves the @farm.js/app initializer name to the published @farm.js/create-app package. The
scaffolder installs React and all other starter dependencies automatically. Use --skip-install if
you only want it to generate the project files.
Right after a release, pnpm can still start the previous initializer: its create cache lasts a
day, and pnpm 11's default release-age policy holds back packages published in the last day. Set
both for the shell, then run the command again:
export PNPM_CONFIG_DLX_CACHE_MAX_AGE=0
export PNPM_CONFIG_MINIMUM_RELEASE_AGE_EXCLUDE='["@farm.js/*"]'
pnpm create @farm.js/app my-app --template basic --typescriptIn PowerShell:
$env:PNPM_CONFIG_DLX_CACHE_MAX_AGE = "0"
$env:PNPM_CONFIG_MINIMUM_RELEASE_AGE_EXCLUDE = '["@farm.js/*"]'
pnpm create @farm.js/app my-app --template basic --typescriptReact is the default renderer. The Basic starter can instead use Preact, Solid, Vue, or Svelte:
pnpm create @farm.js/app my-preact-app --template basic --renderer preact --typescript
pnpm create @farm.js/app my-solid-app --template basic --renderer solid --typescript
pnpm create @farm.js/app my-vue-app --template basic --renderer vue --typescript
pnpm create @farm.js/app my-svelte-app --template basic --renderer svelte --typescriptSee Renderers before choosing an adapter. Integration starters currently use React because their generated UI and provider packages are React-oriented.
Choose a starter
Use --list-templates to see the same catalog in the terminal. Provider templates include the
integration wiring, an app-owned UI feature, .env.example, and a minimal dark home page.
Every starter registers the DevTools plugin in farm.config.ts, so the
development workspace is available from the first farm dev. Remove devtools() from plugins
and drop the @farm.js/devtools dev dependency if you do not want it.
| Template | Included capability |
|---|---|
basic | Minimal Farm.js app |
react-compiler | Experimental React AOT compiler starter |
auth | Farm.js Auth |
better-auth | Better Auth |
ai | AI SDK chat |
auth0 | Auth0 |
authjs | Auth.js with GitHub OAuth |
autumn | Autumn billing |
clerk | Clerk |
jobs-inngest | Inngest jobs |
jobs-trigger | Trigger.dev jobs |
polar | Polar billing |
resend | Resend email |
stripe | Stripe billing |
supabase | Supabase Auth |
unkey | Unkey API keys |
workos | WorkOS AuthKit |
For example:
pnpm create @farm.js/app stripe-app --template stripe --typescriptThe generated README lists the required environment values and links to the provider guide.
To explore Farm's experimental React AOT compiler with the shared dark starter UI:
pnpm create @farm.js/app compiler-app --template react-compiler --typescriptThe same project is available as the standalone React Compiler Starter.
What you get
- File-based routes in src/app.
- Renderer-owned pages, layouts, loading, error, and not-found boundaries.
- Route types generated from the route tree.
- API routes and a generated client for api.users.get style calls.
- Deployment output powered by Farm config instead of extra root files.
Your first page
The default starter uses React. Preact, Solid, Vue, and Svelte projects should follow their dedicated renderer guide for the equivalent component file.
import type { PageProps } from "@farm.js/core";
export default function HomePage(_props: PageProps) {
return <h1>Hello from Farm.js</h1>;
}Add a layout
Every route can share chrome through layout.tsx. Start with a root layout, then add nested layouts only when a section needs its own navigation or data shell.
import type { LayoutProps } from "@farm.js/core";
import "./globals.css";
export default function RootLayout({ children }: LayoutProps) {
return (
<main>
<header>Farm.js</header>
{children}
</main>
);
}Add an API route
Farm API routes live beside pages and use the same route tree. Define an endpoint, add Zod input when needed, then call it through the generated API client.
import { createEndpoint } from "@farm.js/core/api";
import { z } from "zod";
export const POST = createEndpoint(
{
method: "POST",
body: z.object({
name: z.string().min(1),
}),
},
async ({ body }) => {
return Response.json({
message: `Hello ${body.name}`,
});
},
);Create the two callers once in a shared module. Farm generates the route types and path manifest; the endpoint handler is defined only in the route file above.
import { createApiClients } from "@farm.js/core/client";
import { apiRoutes, type APIRouter } from "./api.generated";
export const { api, apiClient } = createApiClients<APIRouter>({ routes: apiRoutes });Import api during server requests for local calls, or apiClient in the browser for HTTP calls.
See API Client for request context and middleware boundaries.
"use client";
import { apiClient } from "@/lib/api";
export function HelloButton() {
return (
<button
onClick={async () => {
const result = await apiClient.hello.post({
body: { name: "Ada" },
});
console.log(result.data?.message);
}}
>
Say hello
</button>
);
}Add authentication
For the default email/password flow, install the optional Farm Auth runtime and enable one config key:
pnpm add @farm.js/authexport default defineConfig({
auth: true,
});The Farm.js Auth Starter includes the complete forms, session UI, protected middleware, local SQLite setup, and production guidance.
Add integrations later
Keep the first app small. When a feature becomes provider-shaped, add it as an integration:
farm add integration stripe --ui
farm add integration unkeyIntegrations can contribute typed callers, routes, providers, middleware, database schemas, CLI registry components, config validation, and lifecycle hooks.
Use farm add integration better-auth --ui instead when the application needs to own a Better Auth instance, plugins, adapters, providers, or callbacks. The Better Auth integration guide and Better Auth starter document that explicit path.
Next steps
- Read Project Structure when you want the compact file layout.
- Read Renderers when choosing React, Preact, Solid, Vue, or Svelte for the component layer.
- Read Routing and Layouts when you start nesting pages.
- Read API Routes and API Client when you need typed server/client calls.
- Read Integrations when provider features should be packaged instead of copied route-by-route.