Universal Build & Nitro Integration
Relevant source files
The following files were used as context for generating this wiki page:
The Universal Build system allows Farm.js to produce platform-agnostic server output by leveraging Web Standard APIs. It uses Nitro as the production engine to generate optimized adapters for targets like Vercel, Netlify, and Node.js.
This architecture ensures that user code remains decoupled from specific deployment environments. The framework builds Server-Side Rendering (SSR) bundles in memory to eliminate disk I/O and uses a virtual bundle plugin to expose these modules to Nitro.
Sources: packages/farm/UNIVERSAL_BUILD.md:3-9, ARCHITECTURE.md:100-105
Core Principles
The universal build pattern follows five central principles:
- Web Standard APIs: User code interacts only with
RequestandResponseobjects. - Build-time Adapters: Nitro converts standard code into platform-specific implementations.
- No Platform Leaks: Userland code contains zero environment-specific logic.
- In-Memory SSR: Vite builds the SSR bundle with
write: falseto improve build speed. - Virtual Module Exposure: A dedicated plugin resolves imports from the in-memory bundle for Nitro.
Sources: packages/farm/UNIVERSAL_BUILD.md:5-12
Architecture and Data Flow
The build process transitions from user-authored components through an in-memory Vite build into a Nitro-managed deployment package.
The diagram shows how user code using standard APIs is processed by Vite in memory before being wrapped by Nitro for final platform output.
Sources: packages/farm/UNIVERSAL_BUILD.md:14-45
Implementation Components
The integration utilizes several specialized files to manage the transition from development to production runtimes.
| Component | File Path | Description |
|---|---|---|
| Request Handler | nitro/request-handler.ts | Wraps Web Standard handlers with h3 context and provides AsyncLocalStorage. |
| Handler Factory | nitro/create-handler.ts | Creates standard handlers from callbacks and manages error conversion to Responses. |
| Server Entry | nitro/server-entry.ts | Default Farm.js handler that routes both API and SSR requests using the global registry. |
| Virtual Plugin | nitro/virtual-bundle-plugin.ts | Resolves module imports and source maps from the in-memory Vite bundle for Nitro. |
| Universal Build | nitro/universal-build.ts | Orchestrates the client build to disk and the in-memory SSR build. |
Sources: packages/farm/UNIVERSAL_BUILD.md:47-66
Nitro Configuration and Build Process
Nitro configuration is generated dynamically based on the resolved framework config and route managers. The system creates a temporary .farm/.nitro directory for processing before emitting the final deployable output to .farm/.output.
Catch-all Handlers
Nitro uses catch-all handlers to intercept requests and route them to the Farm.js internal managers:
- API Catch-all: Located at
server/api/[...].ts, this handler usescreateFarmLegacyRequestto process/api/*requests. - SSR Catch-all: Located at
server/routes/[...].ts, this handler manages page rendering, redirects, and static asset fallbacks.
Sources: packages/farm/src/nitro/index.ts:101-110, packages/farm/src/nitro/index.ts:210-220
Global Registry Initialization
Managers like the RouteManager and ServerRenderer are persisted in globalThis.__FARM_REGISTRY__. During a Nitro build, these are stored via a build:before hook to ensure they are available at runtime, especially in serverless environments where warm starts reuse the global scope.
// Example of registry initialization in Nitro hook
(farmRegistry as any).__INIT__ = () => {
farmRegistry.apiRouteManager = apiRouteManager;
farmRegistry.routeManager = routeManager;
farmRegistry.serverRenderer = serverRenderer;
farmRegistry.env = config.env || { server: {}, public: {} };
};
Sources: packages/farm/src/nitro/index.ts:470-485, packages/farm/UNIVERSAL_BUILD.md:94-98
Workflow and Task Integration
Farm.js integrates background jobs and scheduled tasks directly into the Nitro build. The prepareFarmWorkflowsForNitro function scans for workflows in directories like src/jobs or src/workflows and generates Nitro-compatible task wrappers.
The sequence shows the discovery of workflows by the CLI and their subsequent wrapping for Nitro's task execution system.
Sources: packages/farm/src/workflows.ts:255-280, packages/farm/src/nitro/index.ts:40-50
Deployment Targets and Presets
The system supports various Nitro presets, which can be configured in farm.config.ts. The default target is node-server.
| Target | Description |
|---|---|
vercel | Generates Vercel Functions and vercel.json configurations. |
netlify | Produces Netlify Functions and edge adapters. |
node-server | Standard standalone Node.js server. |
cloudflare-pages | Stable target for Cloudflare's edge platform. |
Sources: packages/farm/src/nitro/index.ts:526-530, AGENTS.md:58-65, README.md:180-185
Conclusion
Universal Build & Nitro Integration provides a high-performance, disk-less build pipeline that adheres to Web Standards. By using Nitro as the core engine, Farm.js achieves wide deployment compatibility while maintaining a fast developer feedback loop through in-memory SSR bundling.