---
title: "Farm.js"
description: "The @fiducy/farm integration mounts the key routes and uses a Farm storage mount."
canonical_url: "https://fiducy.dev/docs/farm"
markdown_url: "https://fiducy.dev/docs/farm.md"
last_updated: "2026-11-03"
x_farming_labs_generated_preamble: true
---

# Farm.js
URL: /docs/farm
LLM index: /llms.txt
Description: The @fiducy/farm integration mounts the key routes and uses a Farm storage mount.

# Farm.js

On [Farm.js](https://farmjs.dev), `@fiducy/farm` replaces step 3 of the [Quickstart](/docs/quickstart): it mounts the key routes for you and reads handles from a Farm storage mount.

```bash
npm install @fiducy/sdk @fiducy/farm
```

## Server module

```ts title="src/lib/fiducy.ts"
import { auth } from '@farm.js/auth/server';
import { getStorage } from '@farm.js/core/storage';
import { createFiducy, keyValueStorage } from '@fiducy/sdk/server';

const { FIDUCY_GATEWAY_URL, FIDUCY_APP_SECRET } = process.env;
if (!FIDUCY_GATEWAY_URL || !FIDUCY_APP_SECRET) throw new Error('Set the Fiducy env vars');

export async function getUserID(request: Request) {
  const user = await auth.user({ request });
  return user?.id ?? null;
}

export const fiducyServer = createFiducy({
  gatewayURL: FIDUCY_GATEWAY_URL,
  appSecret: FIDUCY_APP_SECRET,
  storage: keyValueStorage({
    getItem: (key) => getStorage('fiducy').getItem(key),
    setItem: (key, value) => getStorage('fiducy').setItem(key, value),
    removeItem: (key) => getStorage('fiducy').removeItem(key),
    getKeys: (base) => getStorage('fiducy').getKeys(base)
  }),
  getUserID
});
```

Three Farm details:

- **Look the mount up on every call**, as above. This file is imported by `farm.config.ts`, which loads before Farm sets up its storage mounts, so `keyValueStorage(getStorage('fiducy'))` would capture a different store than your routes use, and `providerSettings` would return `null`.
- **Pass `request` to `auth.user`.** The integration's routes run outside Farm's page request, so `auth.user()` without it throws "No current request is available".
- **Set `FARM_AUTH_URL`** when your app is not on port 3000. Farm Auth signs cookies for `http://localhost:3000` in development, so on another port add `FARM_AUTH_URL=http://localhost:5173` to `.env`, or sign-in fails with "Invalid origin".

## Integration

```ts title="farm.config.ts"
import { defineConfig } from '@farm.js/core';
import { localStorage } from '@farm.js/core/storage';
import { fiducy } from '@fiducy/farm';

import { fiducyServer } from './src/lib/fiducy';

export default defineConfig({
  storage: {
    mounts: { fiducy: localStorage({ base: '.data/fiducy' }) }
  },
  integrations: {
    byok: fiducy({ instance: fiducyServer })
  }
});
```

Farm's `localStorage` driver writes files on your server under `.data/fiducy` (it is not the browser's localStorage). That is fine while developing; in production, point the mount at a database, for example `postgresStorage({ url: process.env.DATABASE_URL })` from `@farm.js/core/storage`.

The integration mounts `GET /api/fiducy/keys`, `POST /api/fiducy/keys` and `DELETE /api/fiducy/keys/:keyID`. Continue with steps 4 and 5 of the [Quickstart](/docs/quickstart#4-add-the-key-widget).

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
