# @bettercms-ai/next 中文文档

规范地址：https://npmcn.com/package/%40bettercms-ai/next/

版本：0\.39\.0
npm 元数据更新时间：2026-11-05T14:17:28.993Z
中文译文更新时间：2026-11-08T00:17:20.327Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40bettercms-ai/next
原文对照：https://npmcn.com/package/%40bettercms-ai/next/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：713 kB，43 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：7 个
- peer 依赖：next \>=14，react \>=18
- 首次发布：2026-06-30T11:08:12.423Z
- 最新版本发布：2026-11-05T14:17:28.678Z
- 近 30 天下载量：5106（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：61（近 12 个月 61 个）

## 中文简介

Next.js的BetterCMS适配器——已打入,缓存-意识内容已读取(getEntry/list Enteries),预览草稿,构建时间内容快照,以及App路由器的llms.txt生成. /块,/形式,/场,/搜索和/视频编辑条目为被框

## 安装

```sh
npm install @bettercms-ai/next
```

也可以使用：`pnpm add @bettercms-ai/next`、`yarn add @bettercms-ai/next`、`bun add @bettercms-ai/next`

## README

# @ bettercms-ai/ next (英语)

BetterCMS 适配器用于 **下一个.js** (App路由器). 输入,缓存 - 意识内容读取, 预览草稿,以及 `llms.txt` ——CMS下的定型地层.

与 [`@bettercms-ai/codegen`](https://npmcn.com/package/%40bettercms-ai/codegen): 生成 `BetterCMSSchema` 从你的 内容模型,然后获得完整类型 `getEntry`编号 :`listEntries` 自动完成.

## 安装

```bash
npm install @bettercms-ai/next
# peers: next >= 14, react >= 18
```

## 快开始

```ts
// lib/cms.ts
import { createBetterCMS } from "@bettercms-ai/next";
import type { BetterCMSSchema } from "./bettercms.generated"; // from @bettercms-ai/codegen

export const cms = createBetterCMS<BetterCMSSchema>({
  workspace: "acme",
  apiKey: process.env.BETTERCMS_API_KEY,
  // baseUrl defaults to https://api.bettercms.ai/api/v1/delivery
  revalidate: 60, // default ISR window (seconds); false = always fresh
});
```

```tsx
// app/blog/[slug]/page.tsx
import { cms } from "@/lib/cms";
import { notFound } from "next/navigation";

export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const entry = await cms.getEntry<{ title: string; body: string }>(slug, {
    revalidate: 300,
    // The exact tags the revalidation webhook sends on publish (see "Caching & revalidation").
    tags: ["bcms:acme:all", `bcms:acme:entry:${slug}`],
  });
  if (!entry) notFound();
  return <article><h1>{entry.fields.title}</h1>{/* ... */}</article>;
}
```

```tsx
// app/blog/page.tsx — list, typed by your model registry
const { items, hasNextPage } = await cms.listEntries("blog", { page: 1, perPage: 20 });
```

## 环境变量

`createBetterCMS`, (中文(简体) ), `createDraftModeRoute`, (中文(简体) ), `createRevalidateRoute` 财务报告和审定财务报表 `<VisualEditing>` 读取 **没有** 环境变量。 你传递每个值作为选项, 所以这些例子中的名称 只是一个公约。 套件在两个地方读出:

| 变量 | 阅读者 | 含义 |
| --- | --- | --- |
| `BETTERCMS_API_KEY` | `bettercms-snapshot` 国 际 | 能够读取模型和条目的工程密钥( 需要) |
| `BETTERCMS_WORKSPACE` | `bettercms-snapshot` 国 际 | 工作空间弹片( 需要) |
| `BETTERCMS_API_URL` | `bettercms-snapshot` 国 际 | API 基础, 默认 `https://api.bettercms.ai/api/v1` |
| `BETTERCMS_PREVIEW` | `getContent()` | `1` 读取活字代替 `bcms-content.json` (审查楼) |

**复次密语.** 该值是项目重新验证的 Webhook 秘密(项目 −) 设置 – 调整 。 存储为 `BCMS_REVALIDATE_SECRET`数字 : `createRevalidateRoute()` 读取 当没有时 `secret` 通过。 没有两者之一,该路线接受未经签名的请求.

**更好的CMS生成的部署工作流程** (连通回波). 重案组的秘密是 `BCMS_API_KEY` (只给内容-牵引步骤,从不给构建) 工作空间是repo 变量 `BCMS_WORKSPACE_SLUG`。建设步骤得到 `PUBLIC_BCMS_API_URL`, (中文(简体) ), `PUBLIC_BCMS_WORKSPACE`, (中文(简体) ), `PUBLIC_BCMS_PROJECT_ID` 财务报告和审定财务报表 `PUBLIC_SITE_URL`此软件包为零 他们为你。 让他们进去 `createBetterCMS` 你自己来 除非 你用一个 `NEXT_PUBLIC_` 前缀.

## API 密码

### `createBetterCMS<Schema>(config)`

-   `workspace` ——工作空间弹(需要)
-   `apiKey` ——交付 API 密钥(按: `Authorization: Bearer`(中文(简体) )
-   `baseUrl` 编号 : `previewBaseUrl` ——覆盖 API 基础
-   `revalidate` ——默认的IRS窗口(秒)或 `false`

### `getEntry<TFields>(slug, opts?)` → `BetterCMSEntry<TFields> | null`

由内容 swit 单独发布的条目. `null` 404号公路. 选项 : `revalidate`, (中文(简体) ), `tags`, (中文(简体) ), `depth` (0至2回水合), `select` (外地预测) 结果是 `Partial<TFields>`, (中文(简体) ), `preview` + 键 `previewToken`。 。 。 .

### `listEntries(model, opts?)` → `EntryList<Fields>`

发布一个模型的条目,被标注. **掷出** `BetterCMSError` (CONTENT NOT FOUND) (法语) 对于未知的工作空间/模型;空模型返回空页. 选项 : `page`, (中文(简体) ), `perPage`, (中文(简体) ), `revalidate`, (中文(简体) ), `tags`, (中文(简体) ), `depth`, (中文(简体) ), `select`。 。 。 .

### 缓存重新验证( R)

读取流经 `fetch`,下一个补丁到数据缓存中。 过 `tags` 打电话 `revalidateTag(tag)` 发表. `revalidate: false` **与** 标记 = 缓存-直到-tag; 无标签 = `no-store` (总是新鲜的).

重新验证的 Webhook 为每个已公布或未公布的资源发送了两个标记, 财务报告和审定财务报表 `createRevalidateRoute` 电话 `revalidateTag` 各页:

-   `bcms:{workspace}:all`: 工作空间中的一切
-   `bcms:{workspace}:{type}:{slug}`时 `type` 实值 `entry` 或者说 `page`

标记用这些字符串读取( T)`bcms:acme:entry:${slug}`, (中文(简体) ), `bcms:acme:page:${slug}`, (中文(简体) ), `bcms:acme:all` 页:1 客户端不为您添加, 以及其它形状的标签 绝不作废.

以“ 重新验证” 模式部署的目标( 在其他地方托管的网站) 可能指向同一路线: 它 刷新调用名称的路径和标记, 或整个站点没有命名时的标记 .

### 转换的页面的值, live (`bcmsPage`(中文(简体) )

一个网站 `@bettercms-ai/convert` 转换读取每页的值 `bcms-content/<slug>.json`。 。 。 . `bcmsPage` 读同页直播,形状相同,所以帮助者 `bcms()` 原文不变:

```tsx
// app/page.tsx (Server Component)
import { bcmsPage } from "@bettercms-ai/next";
import { BcmsPage } from "@bettercms-ai/next/page";
import bcmsHomeSnapshot from "../bcms-content/home.json";

export default async function Page() {
  const bcmsHome = await bcmsPage("home", bcmsHomeSnapshot);
  return <BcmsPage value={bcmsHome}>{/* … */}</BcmsPage>;
}

// a "use client" file under it
import { useBcmsPage } from "@bettercms-ai/next/page";
const page = useBcmsPage();
```

在“草稿模式”中,它读取预览(`/api/v1/preview/<slug>`,无斑. 否则它会读到 从送出时已公布行, 缓存到公布名称(`bcms:{ws}:all`, (中文(简体) ), `bcms:{ws}:entry:{slug}`, (中文(简体) ), `bcms:{ws}:page:{slug}`),因此页面保持静态 `createRevalidateRoute` 刷新它。 当读取失败( 离线建筑) 时, 它会倒回 已发布的内容文件( e)`BCMS_CONTENT_FILE`),然后到你通过的快照。 客户端组件获得 同一对象通过 `useBcmsPage()`,因此服务器 HTML 和水合页面显示相同的副本.

### CMS的图像(`next.config`(中文(简体) )

CMS 图像为远程 URL `cdn.bettercms.ai`,哪个 `next/image` 拒绝直到 `images.remotePatterns` 允许它。 环绕配置 :

```ts
// next.config.ts
import { withBetterCMS } from "@bettercms-ai/next/config";

export default withBetterCMS(nextConfig);
```

它增加了媒体主持人(和 `NEXT_PUBLIC_BCMS_MEDIA_URL`,当网站服务媒体从它的 之后的图案,一次, 并留下其余的配置是.

### 预览草稿

草稿只来自签名的预览端点,通过 `getEntry`数字 :

```ts
// app/api/draft/route.ts — validates the dashboard's preview token, enables Draft Mode,
// stores the token in a cookie, then redirects
import { createDraftModeRoute } from "@bettercms-ai/next";
export const { GET } = createDraftModeRoute({ apiUrl: "https://api.bettercms.ai" });
```

```ts
import { isDraftEnabled, getPreviewToken } from "@bettercms-ai/next";
const previewToken = (await isDraftEnabled()) ? await getPreviewToken() : null;
const entry = previewToken
  ? await cms.getEntry(slug, { preview: true, previewToken }) // uncached
  : await cms.getEntry(slug, { tags: [`bcms:acme:entry:${slug}`] });
```

`getPage` 已经 **无选项草稿**。它总是返回已公布的页面。 显示草稿 标记范围 `getEntry` 预览见上文。 对于视觉编辑器画布, 包裹 页面的块 `<BcmsDraftBridge>` (单位:千美元)`@bettercms-ai/next/draft-bridge`改为 `<BcmsBlocks>`编辑将块树草稿推向它 `postMessage`,所以页面 什么都拿不出来 打开 `<BcmsDraftMarker />` 在“草稿模式”的根布局中.

### 静态导出( N)`output: "export"`(中文(简体) )

运行 `bettercms-snapshot` **在此之前** `next build`,并读取内容 `getContent(config)`数字 :

```json
{ "scripts": { "build": "bettercms-snapshot && next build" } }
```

无 `bcms-content.json`,读取回 活 `no-store` 获取。 这条路就是这样 动态,以及 `output: "export"` 悄悄地放下它们,留下一空 `out/`。 。 。 . `getContent` 转弯 声入人心 `SNAPSHOT_MISSING` 构建错误。 设定 `BETTERCMS_PREVIEW=1` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}读到生活 相反,预览构建.

### `llms.txt`

```ts
// app/llms.txt/route.ts
import { llmsTxtRoute } from "@bettercms-ai/next";
export const GET = llmsTxtRoute({ models, title: "Acme", workspace: "acme" });
```

`generateLlmsTxt(models, opts)` (纯)和 `fetchModels({ apiUrl, apiKey })` 也被导出. 作者控制的值被逃脱,所以内容不能伪造文档结构.

### 表单

在内容快照中填表飞船( E)`bcms-content.json` → `forms`,由建筑物写成 行动。 土生土长的 `<BcmsForm>` ——真正的输入,没有iframe,你自己的风格. 它处理有条件 `showIf` 字段、 URL- query 预填充、 蜂蜜壶、 可选 旋转部件、 校验错误和提交 。 没有 API 密钥( 端点是 转弯相接.

```tsx
// app/contact/page.tsx — a Server Component reads the Action's snapshot...
import { getForm } from "@bettercms-ai/next";
import { ContactForm } from "./contact-form";

export default function ContactPage() {
  const form = getForm("Contact"); // by name or id, from bcms-content.json
  return form ? <ContactForm form={form} /> : null;
}
```

```tsx
// ./contact-form.tsx — <BcmsForm> ships from its own "use client" entry.
import { BcmsForm } from "@bettercms-ai/next/form";
import type { DeliveryForm } from "@bettercms-ai/sdk";

export function ContactForm({ form }: { form: DeliveryForm }) {
  return <BcmsForm form={form} turnstileSiteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY} />;
}
```

不在反应上? 从任何地方提交框架不可知核心:

```ts
import { submitForm } from "@bettercms-ai/sdk";
await submitForm({ formId, data: { email: "a@b.com" }, turnstileToken });
```

仪表板的复制版嵌入片段仍然是非CMS站点的零积分倒计时.

### 页块( E)`<BcmsBlocks>`——表格放入页面构建器

当你在BetterCMS仪表板上建出一个页面并放下一个 **窗体块** 打开它 表格将它完全排入您放置的位置。 调整页面的块 `<BcmsBlocks>` 并将表格从 `readForms()` a 包括: `form` 块解析其 `formId` 对付他们,使他们 `<BcmsForm>` 给你的 其它区块类型 (标题、文字、图像、按钮、空间器、视频、列) 标记可以样式.

> 🔴 **过 `components={readComponents()}` 我也一样.** 以章节形式撰写的页面—— 仪表板的"添加一款"采取器和AI两种产品——都是列表 `component` 块. A 类 `component` 未交付定义的块 **无**,所以一个页面可以 建立绿色并返回时只显示您的版面导航和页脚。 两个读者都从 同样的 `bcms-content.json` 所以这需要多打一个电话.

```tsx
// app/[slug]/page.tsx
import { createBetterCMS, readForms, readComponents } from "@bettercms-ai/next";
import { BcmsBlocks } from "@bettercms-ai/next/blocks"; // its own "use client" entry

const cms = createBetterCMS({ workspace: "my-workspace", apiKey: process.env.BETTERCMS_API_KEY! });

export default async function Page({ params }: { params: { slug: string } }) {
  // The page's blocks come from the delivery API (`entry.blocks`); forms from the snapshot.
  const page = await cms.getPage(params.slug);
  const { forms, turnstileSiteKey } = readForms();
  return (
    <BcmsBlocks
      blocks={page.blocks}
      forms={forms}
      // 🔴 NOT optional in practice. A page built out of SECTIONS is a list of `component`
      // blocks, and a `component` block with no matching definition renders NOTHING. Omit
      // this and such a page builds green, returns 200, and shows only your nav and footer.
      components={readComponents()}
      turnstileSiteKey={turnstileSiteKey ?? undefined}
    />
  );
}
```

### CMS顺序中的章节( :`<BcmsSections>`(中文(简体) )

页面的章节被写在自己的文件中,使其按其CMS页面列表的顺序排列 他们。 服务器组件( 没有客户端 JavaScript), 包含自己的条目 :

```tsx
import { sectionsFor } from "@bettercms-ai/next";
import { BcmsSections, BcmsSection } from "@bettercms-ai/next/sections";

export default function Home() {
  return (
    <main>
      <BcmsSections {...sectionsFor("home")}>
        <BcmsSection bind="hero">{(root) => <Hero rootProps={root} />}</BcmsSection>
        <BcmsSection bind="code:sec1"><LogoStrip /></BcmsSection>
        <BcmsSection bind="features"><section className="features">…</section></BcmsSection>
      </BcmsSections>
    </main>
  );
}
```

-   一个被捆绑在一区块的区块 使它在区块的位置。 一个DOM元素得到 `data-bcms-block`, (中文(简体) ), `data-bcms-style` 和块的风格克隆到它。 一个组成部分的孩子是: 给定函数代替: 展开 `root` 在它制造的元素。 没有函数 a 组件被标记在一个框上: `display:contents` 街坊没有风格,有一个 `display:flow-root` 框中,如果样式已经存在,则随行(在弹性或网格母框中,区域是 (然后是一个项目).
-   编辑器中添加的一节( 一个块,没有绑定)通过 `<BcmsBlocks>`。 。 。 .
-   无块名称的一节 : `code:<bind>` 总是让你写的地方。 一个赤裸的 `<bind>` 已经 直到列表中指定页面的一栏;然后是已删除的一栏.
-   `blocks` 无效( 无快照 ) , 使每个孩子都处于源头顺序, 不受影响 .

页面路由器:页面也在浏览器中制作,所以列表必须是页面道具: `export const getStaticProps = sectionsStaticProps("home")`,则 `<BcmsSections {...bcmsSections}>` 在页中需要 `{ bcmsSections }`。带有数据的页面 其功能通过: `sectionsStaticProps("home", pageStaticProps)` (或 `sectionsServerSideProps`) 调用并添加 `bcmsSections` 对道具 它回答. `npx @bettercms-ai/convert --sections` 写这个包裹给你.

### 带有国家代码拾取器的电话字段

作者启用的电话字段 **国家代码拾取器** 在建设者中使一个国家 控制在号码旁边 不管访客选什么 球场还是呈递 **一个值**, (中文(简体) ), e.164(在自己的密钥下)`+14155550123`)——没有第二把钥匙可以处理.

两个班是你的风格:

| 类 | 元素 |
| --- | --- |
| `bcms-phone` | 国家控制周围的包装和数字 |
| `bcms-phone-country` | 国家控制自己 |

`@bettercms-ai/next` 格式化输入的数字。 主题及其电话元数据 (~80KB)生活在一个 **单独块, 只有在表单有取取器时才装入** a 包括: 没有一艘飞船 直到那个块到达 田地是平地 `tel` 投入 里面一样 `bcms-phone` 包装,所以你的CSS应用前后.

## SEO——每页 `<head>` 与 `generateMetadata`

`getPage()` 返回页面 `metaTitle`, (中文(简体) ), `metaDescription`有钱人 `metaJson` (OG / Twitter / canonical / JSON-LD)在仪表板的SEO面板上编辑. 让他们进入 路线 `<head>` 与 `buildMetadata` – 网页默认值的每页值层 (同一页面翻页优先 `*.bettercms.site` 渲染器用途:

```tsx
// app/[slug]/page.tsx
import type { Metadata } from "next";
import { createBetterCMS, buildMetadata, resolveSeo, type SiteSeoDefaults } from "@bettercms-ai/next";

const cms = createBetterCMS({ workspace: "my-workspace", apiKey: process.env.BETTERCMS_API_KEY! });

// Your project-wide fallbacks (optional). Per-page meta always wins.
const siteDefaults: SiteSeoDefaults = {
  metaDescription: "Selected work, experience, and contact information.",
  ogImage: "https://example.com/og-default.png",
  twitterHandle: "@acme",
};

export async function generateMetadata(
  { params }: { params: { slug: string } },
): Promise<Metadata> {
  const page = await cms.getPage(params.slug);
  if (!page) return {};
  return buildMetadata(page, siteDefaults);
}
```

`buildMetadata` 覆盖 `<title>`、描述、神话、开放图和推特. JSON -LD不是下一个的一部分 `Metadata`,所以从页面组件中用 `resolveSeo(...).jsonLd`数字 :

```tsx
export default async function Page({ params }: { params: { slug: string } }) {
  const page = await cms.getPage(params.slug);
  if (!page) return null;
  const { jsonLd } = resolveSeo(page, siteDefaults);
  return (
    <>
      {jsonLd.map((node, i) => (
        <script
          key={i}
          type="application/ld+json"
          dangerouslySetInnerHTML={{ __html: JSON.stringify(node) }}
        />
      ))}
      {/* …render page.blocks… */}
    </>
  );
}
```

### 在发布时保持 SSO 新鲜

阅读内容为:`revalidate`,默认为60s),所以在窗口后出现 SEO 编辑 e. 对于 **即时** 发布后刷新, 配置工程的 **重新验证 网点** (项目 —— 设置) `createRevalidateRoute` 处理器,通过 网络隐藏为 `secret`标记您的读取 `bcms:{workspace}:…` 标签来源 (原始内容存档于2012-10-10). Caching & revalidation. ``cms.getPage(slug, { tags: [`bcms:acme:page:${slug}`] })`` 这是 页面表单。 没有了网页浏览器,编辑仍然在传播,但是在IRS的间隔上而不是 马上.

## 许可证

UNLICENSED——内部BetterCMS包.

## 常见问题

### @bettercms-ai/next 是什么？

Next\.js的BetterCMS适配器——已打入,缓存-意识内容已读取\(getEntry/list Enteries\),预览草稿,构建时间内容快照,以及App路由器的llms\.txt生成\. /块,/形式,/场,/搜索和/视频编辑条目为被框

### 如何安装 @bettercms-ai/next？

在项目目录运行 npm install @bettercms-ai/next，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 bettercms-snapshot，可以用 npx bettercms-snapshot 直接运行。

### @bettercms-ai/next 支持 TypeScript 吗？

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

### @bettercms-ai/next 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @bettercms-ai/next 可以商用吗？

@bettercms-ai/next 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @bettercms-ai/next 的下载量有多少？

根据 npm 官方下载统计，@bettercms-ai/next 在 2026/10/08 – 2026/11/06 这 30 天内被下载 5,106 次，日均约 170 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @bettercms-ai/next 还在维护吗？

最新版本 0\.39\.0 发布于 2026/11/05（2 天前）；至今共发布 61 个版本，其中过去 12 个月发布了 61 个；首次发布于 2026/06/30。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

