Farm.js

Project Structure

The compact file layout Farm expects, plus the optional files you add only when the app needs them.

Minimal shape

A Farm app can be as small as src, farm.config.ts, package.json, and tsconfig.json. The framework discovers pages, API routes, middleware, layouts, docs, markdown mirrors, and generated route types from there.

Minimal app
my-app/
  src/
    app/
      layout.tsx # Preact/Solid also use TSX; Vue/Svelte use their component extensions
      page.tsx
  farm.config.ts
  package.json
  tsconfig.json

Common folders

PathPurpose
src/appPages, nested layouts, API routes, route boundaries, middleware.
src/client.tsOptional typed browser lifecycle for HTML-first application enhancements.
src/libShared server and client utilities.
src/componentsReusable UI and client components.
layersOptional local Farm layers consumed through extends.
src/farm.d.tsGenerated project types for routes, env, and i18n.
farm.config.tsFramework config, integrations, docs, KV storage, databases, and deployment.

Optional files stay optional

Use vite.config.ts only when you need custom Vite behavior. Use platform files only when a deployment target requires provider-specific settings that Farm cannot infer.

Route files

FileUsed for
page.tsx / page.jsx / page.vue / page.svelteThe route UI for the selected renderer.
page.md / page.mdxReact-oriented Markdown-first app pages.
layout.tsx / layout.jsx / layout.vue / layout.svelteShared shell for every child segment.
loading.*Pending UI for async route work.
error.*Segment-level error UI.
not-found.*Segment-level 404 UI.
middleware.tsRequest behavior before the route renders.
route.tsAPI handlers for the current URL segment.

Use .tsx or .jsx with React, Preact, and Solid, .vue with Vue, and .svelte with Svelte. See Renderers for renderer-specific conventions and current feature boundaries.

Project
my-app/
  src/
    app/
      api/
        hello/
          route.ts
      dashboard/
        layout.tsx
        page.tsx
      about/
        page.mdx
      layout.tsx
      page.tsx
    components/
      account-menu.tsx
    lib/
      api.ts
      integrations.ts
  farm.config.ts
  package.json
  tsconfig.json

Keep framework configuration in farm.config.ts. Keep application helpers under src/lib, and keep UI that is reused across pages under src/components.

Reusable product areas can live under layers/<name> with their own optional farm.config.ts and src directory. The application enables them explicitly through extends; see Layers.

HTML-first client lifecycle

Add src/client.ts when server-rendered HTML needs small browser enhancements without turning a page or layout into a hydrated component tree. Farm discovers the file at build time, includes it in the existing client runtime, and invokes it on the initial document and fragment navigations.

import { defineClient } from "@farm.js/core/client/lifecycle";

export default defineClient({
  setup({ router }) {
    const controller = new AbortController();
    document.addEventListener(
      "click",
      (event) => {
        if (event.target instanceof Element && event.target.closest(".js-refresh")) {
          void router.refresh?.();
        }
      },
      { signal: controller.signal },
    );
    return controller;
  },
  close({ state }) {
    state.abort();
  },
});

The entry is ordinary typed TypeScript, not an inline script string. It does not hydrate the selected renderer unless the application imports and mounts that renderer itself. Serializable values in publicRuntimeConfig are provided as the typed public field of setup, so environment-derived public endpoints can stay in farm.config.ts.

Generated files

Farm keeps project-specific route, environment, and internationalization declarations in one generated src/farm.d.ts file. Static image and stylesheet declarations come from @farm.js/core, so global CSS side-effect imports and CSS Modules type-check without an application-owned declaration file. Generated API clients remain in src/lib/api.generated.ts because applications import that module directly.

After upgrading an older project, run farm generate once to record the current framework type references. Existing generated files that import only @farm.js/core/image remain compatible with the stylesheet declarations.

farm dev keeps generated types current as source files change; run the command manually when the dev server is not running.

farm generate

Generated route types narrow route component props and make the React Link API stricter. Generated API types make api.hello.post(...) match the route's body and query schemas in every renderer.

When to add root files

FileAdd it when
vite.config.tsYou need Vite plugins, aliases, or server settings Farm does not infer.
vercel.jsonYou need platform behavior outside Farm's deploy output.
tailwind.config.tsYour Tailwind version or design system requires an explicit config.
docs.config.tsA large docs configuration is easier to maintain outside the canonical docs property in farm.config.ts.