# @brandlab-digital/site-next 中文文档

规范地址：https://npmcn.com/package/%40brandlab-digital/site-next/

版本：4\.2\.2
npm 元数据更新时间：2026-11-06T10:03:55.679Z
中文译文更新时间：2026-11-08T14:01:10.545Z
软件包许可：UNLICENSED

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

原始 npm 页面：https://www.npmjs.com/package/%40brandlab-digital/site-next
原文对照：https://npmcn.com/package/%40brandlab-digital/site-next/?lang=original
项目主页：https://github.com/RomieDandan/brandlab#readme
源码仓库：https://github.com/RomieDandan/brandlab

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

- 包体积（解压后）：1.4 MB，230 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：5 个
- peer 依赖：next \>=16，react \>=19，resend \>=6
- 首次发布：2026-05-26T03:28:47.162Z
- 最新版本发布：2026-11-06T10:03:55.483Z
- 近 30 天下载量：8094（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：118（近 12 个月 118 个）

## 中文简介

专有软件 Brandlab Digital Marketing. 版权所有。 为Brandlab客户端网站发布.

## 安装

```sh
npm install @brandlab-digital/site-next
```

也可以使用：`pnpm add @brandlab-digital/site-next`、`yarn add @brandlab-digital/site-next`、`bun add @brandlab-digital/site-next`

## README

# `@brandlab-digital/site-next`

专有软件 Brandlab Digital Marketing. 版权所有。 为Brandlab客户端网站发布.

## 审查:变化时刷新,不是每天(3.13.0)

共享评论获取(`getBusinessProfileReviews`, (中文(简体) ), `./google-business-reviews/server`) 携带标记 `brandlab-reviews` 财务报告和审定财务报表 `brandlab-reviews:<site>`。默认情况下,它仍然保持一个成功的答案一天 (单位:千美元)`BUSINESS_PROFILE_REVIEWS_REVALIDATE_SECONDS`),因此一个基于另一个原因安装了3.13.0的站点每天进行评论.

站点在更改时选择刷新通过 `refresh: 'on-change'`在同一通电话中 网站已经命名, 一旦它拥有以下秘密部署的路线,并在每日审查检查员登记:

```ts
// src/lib/reviews.ts
getBusinessProfileReviews({ site: 'hr-kitchens', refresh: 'on-change' })
```

然后,答复保留了7天(第3段)`BUSINESS_PROFILE_REVIEWS_ON_CHANGE_REVALIDATE_SECONDS`仅作为安全网. 一天一次 检查员把每个网站的种子 和当评论真的改变, 呼叫网站的签名 重新验证路由, 这将刷新标签 。 新的评论在一天之内仍会显示; 页面仅在 真正的改变。 如果呼叫失败, 页面将在一周内刷新 。 选择就坐在这里,而不是在 brandlab.config.ts,因为获取是构建时下一个读取的地方,而一个站点的配置文件没有被导入 在运行时间.

路线,在 `src/app/api/brandlab/reviews-revalidate/route.ts`数字 :

```ts
import { createBrandlabReviewsRevalidateRoute } from '@brandlab-digital/site-next/google-business-reviews/server'

export const { POST } = createBrandlabReviewsRevalidateRoute({ site: 'hr-kitchens' })
```

设定 `BRANDLAB_REVALIDATE_SECRET` (至少32个字符) 在网站的Vercel项目和检查器上;从未在 gi. 电话合同:

|  |  |
| --- | --- |
| 请求 | `POST /api/brandlab/reviews-revalidate`数字 `{"site":"<slug>","hash":"<64 hex>"}` (最多1个KB) |
| 签署 | `x-brandlab-timestamp: <Unix seconds>` 财务报告和审定财务报表 `x-brandlab-signature: v1=<hex HMAC-SHA256 of "<timestamp>.<body>">`; 站点核心 `createBusinessProfileReviewsRevalidateRequest` 两者都建起来 |
| 散开 | 站点核心 `hashBusinessProfileReviews(feed)`: 评分, 计数和每个评论的id, 评分, 文本, 作者, 时间和答复, 由 id 排序 |
| 谁决定 | 检查员保留每个站点最后的散列,接受200个,只有在今天的不同时才打电话. 路由还跳过它已经应用过的散列, 但每个服务器实例 |
| 200个 | `{ ok: true, revalidated: true }` 之后 `revalidateTag('brandlab-reviews:<site>', 'max')`,或 `revalidated: false, reason: 'unchanged'` |
| 错误 | 400具畸形尸体或另一站点的弹壳; 401具丢失或错误的签名,或一个超过5分钟的时间戳; 413具超过1KB; 429具带有 `Retry-After` 每个IP在10分钟内超过10个请求; 503 密件未设置; 500 刷新失败 。 检查器在200后才记录散列 |

拒绝请求的日志一行,没有秘密或签名,例如 `{"event":"brandlab_reviews_revalidate","site":"hr-kitchens","result":"refused","reason":"signature"}`。 。 。 .

### 地产段预设( E)`./estate-segment`(中文(简体) )

服务内子公司和子公司页导出 `revalidate = false`,字面上写,因为下一个读取了段配置 静态的,还有现场测试电话 `assertBrandlabEstateSegment(page)`部署和审查标记重写 A 类 显示评论的页面 `refresh: 'on-change'`。准备门 请检查access-date=中的日期值 (帮助) W3(full level, from 3.13.0) 一个比每7天更新更频繁的地产家庭失败,所以一个完整的地产家庭 显示审查通过的破产财产 `on-change` 路径,或记录家庭在 `siteSystem.refreshExceptions` 在 brandlab.config.ts 中: `{ family, revalidateSeconds, reason, decisionId }`。 。 。 .

## 联系方式:未接受(3.14.0)

当Resend接受询问时,它被排队,而不是交付. Resend仍然可以反弹,放弃是因为生意 收件箱在账户的压制列表中,或报告为垃圾邮件,而网站已经表示"同意". 那个 bL Roofing是如何丢失的询问. `contact_form` 保持其分析- v4意义(Resend接受询问)和火灾 现在正在追踪交货情况.

**发送前.** `createBrandlabContactRouteHandler` 询问 Resend 关于每个业务收件箱的压制列表 (单位:千美元)`GET /suppressions/{email}`,每个收件箱缓存5分钟,每次查询最多2.5秒). 仅检查 记录和提醒;它从不阻断发送。 当一个收件箱被压制时, 路径日志和提醒 `recipient_suppressed`,而询问仍然去客户端自己的收件箱(从未被重新定位,从未被复制到 Brandlab) 与正常的“同意”结果和 `contact_form` 和往常一样 保持收件箱及其电子邮件计费顺序是 客户的责任; 提醒让 Brandlab 在同一天告诉他们. 一个站点可以选择拒绝 而不是使用 `refuseWhenAllSuppressed: true`:当每个收件箱被压制时,访客就会得到表格的"无法发送", 请打电话"回答,没有转换火。 一个失败或被拒绝的查询从未停止过询问: 每5分钟一次记录为: `brandlab_contact_suppression_check_unavailable`检查需要 全取密钥: 设置 `RESEND_LOOKUP_API_KEY` 这样 `RESEND_API_KEY` 只能保留发送( 没有它, 查找用途) `RESEND_API_KEY`) (中文(简体) ). 拒绝只发送密钥 `restricted_api_key`,而警告行则表示缺失 权限( e)`"needs":"full-access key (RESEND_LOOKUP_API_KEY)"`) (中文(简体) ). `suppressionCheck: false` 关闭检查; a 将提供者替换为 `createResendSend` (合成测试) 它关闭,除非它通过一个.

**发后.** 一个签名的Wehook路由记录了商业副本的出事情况. 添加 `src/app/api/brandlab/resend-webhook/route.ts`数字 :

```ts
import { createBrandlabResendWebhookRoute } from '@brandlab-digital/site-next/contact/server'
import { contactContract } from '@/config/contact'

export const { POST } = createBrandlabResendWebhookRoute({ projectId: contactContract.projectId })
```

然后,在平坦的步骤:

1.  部署路线.
2.  在Resend中,打开 Webhooks并添加一个终点: `https://<the site's domain>/api/brandlab/resend-webhook`。 。 。 .
3.  勾选电子邮件事件:发送,发送延迟,弹出,抱怨,压制和失败.
4.  打开新 Webhook 并复制其签名密钥( 它开始于 `whsec_`) (中文(简体) ).
5.  在现场的Vercel项目中,加上 `RESEND_WEBHOOK_SECRET` 带有生产值(如果预览) ”)。 千万别放入胶片里 `.env.example` 数值.
6.  重新部署,发出测试询问`?bl_test=1`),并检查日志显示 `brandlab_contact_delivery_status` 线条 与 `"state":"delivered"`。 。 。 .

重新发送 Webhooks 覆盖整个账户,所以每个网站的路由只记录发送的电子邮件本身的联系路由(the `project_id` 和回答200到其余。 正在检查签名的 Svix 方式 重新发送文档 (HMAC-SHA256 完毕) `<svix-id>.<svix-timestamp>.<raw body>`, 5分钟的时钟容忍度); 差的签名得到401, a 失踪的秘密503。 失败的尝试受费率限制 `x-real-ip` (10分钟,然后429分钟) `Retry-After`· ; `rateLimit` 调整它或 `false` 关闭); 正确的签名请求永远不会算数 。 重试与 `svix-id` 页:1 实例已记录的答案 200 `duplicate: true` 不再进行伐木;该清单是小的,每个实例, 所以,这是最好的努力, 显示器仍然是去复制.

两半都接受 `onDeliveryFailure(failure)`,同一天的警报钩(电子邮件、Slack或耐用商店)。 它会得到 代码、源、查询引用和重新发送电子邮件 id,从不设置地址或格式值。 如果它扔在网球赛上 路由响应了500, 因此 Resend 重试事件 .

| 环境变量 | 何处 | 什麽 |
| --- | --- | --- |
| `RESEND_API_KEY` | Vercel, 制作和预览 | 发送询问; 可以保留只发送的密钥 |
| `RESEND_LOOKUP_API_KEY` | Vercel, 制作和预览( 可选) | 仅用于压制检查的全访问密钥;没有它,则检查用途 `RESEND_API_KEY` |
| `RESEND_WEBHOOK_SECRET` | Vercel, 生产 | 网瘾 `whsec_` 签名秘密 |
| 合同内容 `delivery.recipientEnv` | Vercel, 制作和预览 | 业务收件箱 |

**每日交货监测器(P26).** 从网站日志中读取这些JSON行:

| 线条 | 含义 | 行动 |
| --- | --- | --- |
| `{"event":"brandlab_contact_delivery_failed",…,"code":"recipient_suppressed","source":"pre-send","recipients":"all"}` | 收件箱被压制;询问仍被发送(Resend will drop it),访客看到"同意"(除非网站选择进入) `refuseWhenAllSuppressed: true`,当它没有被发送, 并要求来访者打电话) | 同一天:告诉客户端修补收件箱,从Resend → Puters中取出,告诉Romie |
| 同样, `"recipients":"some"` | 数个收件箱中的一个被压制,另一个被压制 | 同一天:修复或去除收件箱 |
| `…"code":"recipient_bounced"/"recipient_complained"/"recipient_suppressed"/"provider_failed","source":"webhook"` | Resend接受了,但业务副本未到(`detail` 给出Resend的弹出类型,压制类型或故障原因) | 同日:查询算作a `contact_form` 但企业从来没有见过它 `submission` (确认id的前16个字符)或 `emailId` 重新发送并转发 |
| `{"event":"brandlab_contact_delivery_status","state":"delivered"}` 编号 : `"state":"delayed"` | 已交付, 否则Resend正在重试软弹出 | 无;a `delayed` 以后也不会 `delivered` 或一天之内失败需要检查 |
| `brandlab_contact_suppression_check_unavailable` | 预发送检查无法要求 Resend ()`code` 说为什么; `needs` 名称缺少权限) | 设置全程访问 `RESEND_LOOKUP_API_KEY`; 问询仍然发送 |
| `brandlab_contact_delivery_alert_failed` | 提醒钩钩失败 | 检查钩子 |

取消复制的网约车线路 `webhookId` (续取一事件同名id. 比较每一天 `contact_form` 在GA4中计数 `delivered` 线条:每个接受的查询应完全以一个结束 `delivered` 或一个 失败。 发射前检查相同的收件箱: 一个真正的发送者,MX记录, 在 Resend 中验证发送器域,而收件箱没有被压制。 运行 `brandlab-ready --launch` 带有收件箱变量 和全通密钥`RESEND_LOOKUP_API_KEY`)设置在外壳中用于该运行,从未写入文件. 没有他们 H13 报告“不运行”和要设置的名称:在不屏蔽分级的普通运行中 `--launch` 它失败了.

## 联系途径:共享垃圾邮件过滤器(4.1.0)

共享接触处理器上的每一站点都屏蔽验证后和交付前的销售投放查询. 一个被封锁的询问得到了正常的无声成功: 访客看到了通常的感谢, 没有寄给Resend, `contact_form` 不开火,服务器只记录一条与站点和信号相匹配的线条: `{"event":"brandlab_contact_spam_blocked","site":"abloom","signals":["pitch-marketing","foreign-suburb"]}`。 。 。 .

-   **强烈信号 :** (SEO和排名,谷歌审查销售或删除,起飞和估计,), "通过电子邮件联系我"诱惑,网站审核和重新设计,wa.me / WhatsApp / Telegram链接,外观类似Unicode 字母,以及已知的垃圾邮件发送者(已修剪的,小写地址的SHA-256;原始地址从未被存储).
-   **弱信号 :** 信息中的任何链接,文本中一个海外电话号码,和一个显然是郊区 外来或随机字符 ("IN","Dhaka","cvsfewf"). Typos,缩写("Nth Ryde","St Ives"),邮政编码和 州际地方很好 只有键是 `suburb` ; 街道地址字段从不记分.
-   **规则:** 屏蔽时只显示至少两个信号,其中至少有一个信号很强。 同一发球的第二发球 类别算作另一个信号。 弱信号从不单独或一起阻断 过滤故障总是 送货.
-   **填充时间 :** 共享表格邮票 `formStartedAt` 当它使。 3秒后提交的划界案被删除 静默地( s)`signals:["fill-time"]`) (中文(简体) ). 没有印章的表格永远不会及时掉入. 脚本活性或预览测试 询问必须在页面装入后至少3秒后发送.

站点覆盖通过 `spamFilter` 打开 `createBrandlabContactRouteHandler`数字 : `extraPhrases`, (中文(简体) ), `knownSenderHashes`, (中文(简体) ), `ignoreSignals`, (中文(简体) ), `minFillMs`,或 `false` 关闭过滤器。 没有绕行字;真正的测试询问通过 其措辞.

## 联系方式: 预览测试询问仅到达 Brandlab (4. 2. 0)

预览部署`VERCEL_ENV` (除生产外)标记测试查询(`bl_test=1`仅发送给 `BRANDLAB_PREVIEW_TEST_RECIPIENT` (单位:千美元)[brandlabdigital.com.au 互联网档案馆的存檔,存档日期2013-12-22](mailto:info@brandlabdigital.com.au)无论部署如何 `CONTACT_EMAIL` 说,与 "\[试. \]"题中"并默而成. 它在预览中工作, 没有接收者集; 真正的询问仍然存在 失败,直到一个是。 标记不是垃圾邮件-过滤器绕道:查询必须像其他任何一样通过共享过滤器. 预览的每个联系途径的答案都包含 `x-brandlab-contact-mode: preview; test-inbox=brandlab` (单位:千美元)`BRANDLAB_PREVIEW_CONTACT_HEADER`);生产从不发送. 生产保持3.1.0行为:标记 向配置的收件人询问“\[试 ”。 发送符合要求的释放测试 `brandlab-preview-enquiry`在它发出任何消息之前检查那个信头.

## 联系途径:滥用限制和测试标记(3.10.0)

`createBrandlabContactRouteHandler` 限制每个客户IP和每个查询的电子邮件地址进行不同的查询 交付(制作和预览):每IP10分10分,每个地址5分,默认为1小时 (单位:千美元)`BRANDLAB_CONTACT_RATE_LIMITS`),每个服务器实例内存中保存. 同一调查的重发从不计算 无法验证的询问永远不会算数 被拒绝的人会得到可重试的 `429` 与 `Retry-After` 永远不会 发送。 调整或关闭 `rateLimit: { perIp, perAddress } | false`。 。 。 .

内相受限为一相. 第二道是 Vercel防火墙费率限制规则 这条路线是 每一个实例。 模板(Vercel CLI,在链接的工程中运行;检查工程的防火墙标签 计划中的限速支持先行,并将限速控制在路线本身之上:

```bash
vercel firewall rules add "Contact form rate limit" \
  --condition '{"type":"path","op":"eq","value":"/api/contact"}' \
  --condition '{"type":"method","op":"eq","value":"POST"}' \
  --action rate_limit \
  --rate-limit-window 600 \
  --rate-limit-requests 20 \
  --rate-limit-keys ip \
  --rate-limit-action rate_limit --yes
```

Brandlab测试询问(发射证明或金丝雀)打开页面 `?bl_test=1` (记为分页; `?bl_test=0` 结束它。 然后每一次调查都带着 `bl_test=1`: 服务器将其发送给配置的收件人 `[Test]` 内 主题,在未确认的情况下从不将标记写入电子邮件和答案,所以浏览器从不发送 `contact_form` 或Ads的转换, 一个测试访问发送不 `lead_form_start` 或者说 `lead_form_error`加那利语Name 预览仅交付给 Brandlab 测试收件箱.

加那利和防发射运行对照每个地址的限制(每小时5个地址)进行计数,因此使用加地址测试 收件箱,每个运行一次或每个站点(`test+abloom-1@…`, (中文(简体) ), `test+abloom-2@…`并散布在他们之间。 拒绝 查询日志一行: `{"event":"brandlab_contact_rate_limited","rule":"address","retryAfterSeconds":1800}`。 。 。 .

## 常见问题

### @brandlab-digital/site-next 是什么？

专有软件 Brandlab Digital Marketing\. 版权所有。 为Brandlab客户端网站发布\.

### 如何安装 @brandlab-digital/site-next？

在项目目录运行 npm install @brandlab-digital/site-next，或使用 pnpm add / yarn add / bun add。

### @brandlab-digital/site-next 支持 TypeScript 吗？

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

### @brandlab-digital/site-next 支持 ESM 还是 CommonJS？

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

### @brandlab-digital/site-next 可以商用吗？

@brandlab-digital/site-next 使用 UNLICENSED 许可。作者声明为 UNLICENSED，即不授予公开使用许可（与公共领域的 Unlicense 不同）。使用前需获得作者授权。以上为概括，不构成法律意见，请以许可原文为准。

### @brandlab-digital/site-next 的下载量有多少？

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

### @brandlab-digital/site-next 还在维护吗？

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

