@farm.js/strapi

中文文档
0.1.48发布于 2026/11/01MITTypeScriptES Module

Strapi CMS integration for Farm.js

原始使用文档
文档目录7 节
  1. Install
  2. Configure
  3. Read content
  4. Invalidate on publish
  5. Serve images
  6. Production notes
  7. Options

@farm.js/strapi

Strapi 5 CMS integration for Farm.js applications. It configures the official Strapi client, unwraps typed collection reads, builds responsive image props from generated upload variants, and receives authenticated webhooks so cached content can be refreshed after an editor publishes.

See Stability and Support for what this package guarantees.

Install

pnpm add @farm.js/strapi @strapi/client

@strapi/client is a peer dependency so the application and integration use one client version.

Configure

import { defineConfig } from "@farm.js/core";
import { strapi } from "@farm.js/strapi";

export default defineConfig({
  integrations: {
    cms: strapi(),
  },
});

With no options, values come from the environment:

VariablePurpose
STRAPI_API_URLStrapi Content API base URL, including /api.
STRAPI_MEDIA_URLOptional public media origin. Defaults to the API URL's origin.
STRAPI_API_TOKENOptional server-only API token for non-public content.
STRAPI_WEBHOOK_SECRETRequired once webhook invalidation is configured.

A missing API URL fails while configuration loads instead of on the first content request.

Read content

Build the client once and reuse it in the integration and application server code.

// src/lib/cms.server.ts
import {
  createStrapiClient,
  createStrapiCollection,
  resolveStrapiConfig,
  type StrapiDocument,
} from "@farm.js/strapi";

interface Article extends StrapiDocument {
  title: string;
  slug: string;
}

export const cms = createStrapiClient(resolveStrapiConfig({}));
export const articles = createStrapiCollection<Article>(cms, "articles");
// farm.config.ts
integrations: {
  cms: strapi({ instance: cms }),
}

Wrap collection reads in createServerQuery to validate and cache the result. The helper accepts the official client's populate, fields, filters, sort, pagination, locale, and status query options and unwraps the REST data envelope.

import { createServerQuery } from "@farm.js/core";
import { articles } from "./cms.server";

export const postsQuery = createServerQuery({
  key: () => ["strapi", "articles"],
  staleTime: "5m",
  handler: () =>
    articles.find({
      fields: ["title", "slug"],
      populate: ["cover"],
      sort: ["publishedAt:desc"],
      status: "published",
    }),
});

The generic describes the fields your application expects. Keep runtime validation on the server query boundary because Strapi's returned fields still depend on permissions and populate.

Invalidate on publish

Strapi can send a fixed header with every webhook. Farm verifies that shared secret before parsing the body and asks the application which cache entries the event affects.

strapi({
  instance: cms,
  webhook: {
    onChange(payload) {
      if (payload.model !== "article") return;
      const entry = payload.entry as { documentId?: string; slug?: string };
      return {
        keys: [
          ["strapi", "articles"],
          ...(entry.documentId ? [["strapi", "article", entry.documentId] as const] : []),
        ],
        paths: ["/articles", ...(entry.slug ? [`/articles/${entry.slug}`] : [])],
      };
    },
  },
});

In Strapi, create a webhook under Settings > Webhooks:

  • URL: https://your-app.example/api/strapi/webhook
  • Events: the entry and media events your mapping handles
  • Header name: x-farm-webhook-secret
  • Header value: the value of STRAPI_WEBHOOK_SECRET

You can change both webhook.path and webhook.secretHeader. Strapi does not sign or retry webhook deliveries, so use staleTime as the freshness fallback rather than relying on the webhook alone.

Serve images

getStrapiImageProps selects the smallest generated variant at least as wide as requested and builds a srcset from the real variants on that asset. It never invents a transformation URL.

import { getStrapiImageProps, type StrapiMediaAsset } from "@farm.js/strapi";

export function Cover({ asset }: { asset: StrapiMediaAsset }) {
  return (
    <img
      {...getStrapiImageProps(asset, {
        mediaUrl: process.env.STRAPI_MEDIA_URL ?? process.env.STRAPI_API_URL,
        width: 800,
        sizes: "100vw",
      })}
    />
  );
}

Absolute upload-provider URLs are preserved. Relative URLs are resolved against mediaUrl, which can differ from the Content API host.

Production notes

  • Keep STRAPI_API_TOKEN and the official client in server-only modules. Do not import them from a browser entry.
  • Farm's default data cache is in memory per process. Configure a distributed cache adapter when a webhook must invalidate every server instance.
  • Strapi 5's draft status requires an API token that can read the content type. Do not make draft selection depend on an untrusted query parameter; gate it behind application-owned preview auth.

Options

OptionDefaultNotes
apiUrlSTRAPI_API_URLContent API base URL, including /api.
mediaUrlAPI originPublic origin for relative upload URLs.
tokenSTRAPI_API_TOKENServer only.
instanceExisting StrapiClient; skips API URL validation.
webhook.secretSTRAPI_WEBHOOK_SECRET
webhook.path/api/strapi/webhook
webhook.secretHeaderx-farm-webhook-secretConfigure the same custom header in Strapi.
webhook.onChangeMaps a payload to { keys?, paths? }.
logIntegration lifecycle logger.

版本与发布记录

@farm.js/strapi 共发布 52 个版本,首次发布于 2026/10/05;过去 12 个月发布了 52 个版本。

版本发布日期距今
0.1.48latest2026/11/012 天前
0.1.472026/10/313 天前
0.1.462026/10/313 天前
0.1.452026/10/313 天前
0.1.442026/10/313 天前
0.1.432026/10/304 天前

其他发布通道:beta → 0.1.3-beta.0。

关于 @farm.js/strapi 的常见问题

@farm.js/strapi 是什么?

为Farm.js集成Strapi CMS

如何安装 @farm.js/strapi?

在项目目录运行 npm install @farm.js/strapi,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@strapi/client(^1.6.2)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@farm.js/strapi 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@farm.js/strapi 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@farm.js/strapi 可以商用吗?

@farm.js/strapi 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@farm.js/strapi 还在维护吗?

最新版本 0.1.48 发布于 2026/11/01(2 天前);至今共发布 52 个版本,其中过去 12 个月发布了 52 个;首次发布于 2026/10/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。