上一篇《腾讯云 Knocket 免费用:给博客加个聊天入口,手机就能回复》,先认识了网页聊天气泡、收件箱和 Telegram 各自的作用。这一篇把那条对话链路接到我的 Next.js 博客上。
这是 Knocket 系列的第二篇。我们从创建 Telegram 机器人开始,完成连接与激活、安装网页组件、排除后台和登录页,再用手机视口和正式站点验证消息收发。AI 助手和知识库留到第三篇。
目标很具体:访客看完文章或项目,可以直接在页面里提问;我在 Telegram 收到通知,对那条通知引用回复,回答回到访客的聊天窗口。博客上的开发咨询和文章反馈,就有了一个直接的沟通入口。
现在我的博客已经装好组件。公开页面右下角可以打开聊天窗口,后台和登录页不会出现。下面记录这次接入的完整过程。

这篇记录的是 2026 年 10 月 14 日的实际接入过程。Knocket 设置页和博客验收图使用现场截图;BotFather、激活路径和 Telegram 回复操作的补图,标有“教程示意 · 非现场截图”。示意图里的账号样例和凭据不能直接用于连接。
一 开始前准备什么
需要准备一个能登录的 Knocket 账号、一个能正常使用的 Telegram 账号,以及博客的源码和部署权限。Telegram Bot 由自己的账号创建和管理。
我这次接入的是 Next.js 15.0.7、App Router 项目,已有 AppChrome 统一管理页头、页脚和后台页面的布局。下面的组件代码按这套结构说明,其他版本可以对照对应版本的 Next.js 文档调整。
连接过程会遇到几个容易混淆的值:
| 内容 | 用在哪里 | 本文怎样展示 |
|---|---|---|
| Bot 用户名 | 在 Telegram 中找到机器人,如 @your_blog_demo_bot | 可以展示,示例用户名需要自行替换 |
| Bot Token | 授权 Knocket 操作你的机器人 | 凭据必须保密,图中全部遮挡 |
| Knocket identifier | SDK 识别你的 Knocket 配置 | 本来就会随网页脚本公开,代码中使用占位值 |
| 激活链接或命令 | 连接向导绑定通知接收账号 | 使用自己向导提供的内容,本文不展示真实绑定信息 |
Bot Token 和 identifier 是两回事。浏览器要加载的是带 identifier 的 SDK;Bot Token 填在 Knocket 的 Telegram 连接页面,不能写进前端组件、公开环境变量或博文代码。
这次接入没有给博客新增数据库表,也没有在博客服务器上单独部署 Telegram Bot 程序。
二 在 BotFather 创建机器人并拿到 Token
在 Telegram 中打开官方 @BotFather,发送:
/newbot按提示填写机器人的显示名称和用户名。显示名称可以按用途起名,例如 Blog Support;用户名需要唯一,并以 bot 结尾,例如 your_blog_demo_bot。这个示例不保证可注册,实际要选一个尚未使用的用户名。
完成后,BotFather 会返回 Bot Token。创建命令、用户名规则和 Token 的用途可对照 Telegram 官方 BotFather 文档。

如果已经创建过机器人,先找 BotFather 的原创建消息,Token 就在那条消息里。如果 Token 已丢失或泄露,可以按官方说明使用 /token 生成新值,然后重新更新 Knocket 中的连接凭据。不要把生成新 Token 当成普通的“查看”操作。
我这次连接的机器人用户名是 @mocha_server_bot。读者需要使用自己创建的机器人和对应 Token。
三 在 Knocket 连接 Telegram 并完成激活
登录 Knocket 控制台,在左侧找到:
管理 → 集成 → Telegram 机器人
进入后,向导分成“输入 Bot Token”“激活”“完成”三个阶段。把刚才的真实 Token 粘贴到输入框,再点击“连接”。

填完 Token 后还要完成激活。按照当前向导提供的 Telegram 链接或命令,到 Telegram 中操作,再回到 Knocket 确认连接完成。不要只看第一步提交成功就结束,也不要套用其他账号的激活链接。
Telegram 机器人给个人发消息,需要用户先与机器人建立交互;Knocket 的激活步骤也要按自己的连接向导完成。Telegram 的这一前置条件可参见 官方机器人教程的发送消息说明。

接着打开左侧“管理 → 通知”,检查 Telegram 推送是否开启。为了从 Telegram 直接回复访客,我选择的是:
完整消息与引用回复同页底部的 Telegram 机器人状态应显示“已连接”。

“已连接”说明配置已完成,消息能否走完链路还要实测。后面会从博客里发一条消息,再从 Telegram 引用回复。
四 取到 SDK 嵌入代码
在 Knocket 控制台的“安装接入”页面,复制网页小组件的嵌入代码。官方 Web Widget 说明 给出的基本形式是:
<script
src="https://trtc.io/knocket-sdk/sdk.js?identifier=YOUR_KNOCKET_IDENTIFIER"
async
></script>把 YOUR_KNOCKET_IDENTIFIER 换成自己控制台生成的 identifier。普通 HTML 页面可以把脚本放在 </body> 前;我的 Next.js 博客还需要处理共享布局和路由切换,所以把它封装成了一个客户端组件。
网页小组件的外观和欢迎语可以在 Knocket 控制台配置。我这次验收截图中的欢迎语仍是英文,读者可以按博客的语言和接待方式设置自己的文案。
五 接入 Next.js 并排除后台和登录页
这次改动集中在两个文件:新增 src/components/knocket-widget.tsx,然后在已有的 src/components/app-chrome.tsx 中挂载它。
延后加载并同步组件可见性
下面是接入组件的完整代码。代码中的 identifier 使用占位值,复制后要先替换。
"use client";
import { useEffect } from "react";
import { usePathname } from "next/navigation";
import Script from "next/script";
const SDK_URL =
"https://trtc.io/knocket-sdk/sdk.js?identifier=YOUR_KNOCKET_IDENTIFIER";
type KnocketWindow = Window & {
contactWidget?: {
show?: () => void;
hide?: () => void;
};
};
function isExcludedPath(pathname: string) {
return ["/admin", "/login"].some(
(path) => pathname === path || pathname.startsWith(`${path}/`),
);
}
function synchronizeVisibility() {
const widget = (window as KnocketWindow).contactWidget;
if (isExcludedPath(window.location.pathname)) {
widget?.hide?.();
} else {
widget?.show?.();
}
}
export function KnocketWidget() {
const pathname = usePathname();
const excluded = !pathname || isExcludedPath(pathname);
useEffect(() => {
synchronizeVisibility();
return () => (window as KnocketWindow).contactWidget?.hide?.();
}, [excluded]);
return (
<>
<style id="knocket-route-style">{`
#contact-widget-auto {
--contact-widget-right: max(20px, env(safe-area-inset-right));
--contact-widget-bottom: max(20px, env(safe-area-inset-bottom));
}
@media (max-width: 767px) {
#contact-widget-auto {
--contact-widget-right: max(12px, env(safe-area-inset-right));
--contact-widget-bottom: max(12px, env(safe-area-inset-bottom));
}
}
${excluded ? "#contact-widget-auto { display: none !important; }" : ""}
`}</style>
{excluded ? null : (
<Script
id="knocket-sdk"
src={SDK_URL}
strategy="lazyOnload"
onReady={synchronizeVisibility}
/>
)}
</>
);
}lazyOnload 把 SDK 的加载安排在页面资源加载完成后的浏览器空闲时间,适合聊天这类辅助功能。共享布局中使用 next/script,也方便在客户端导航时管理同一条脚本。加载策略和布局用法可以对照 Next.js 15 脚本加载指南。
路由排除要考虑两种情况。访客直接打开 /login 或 /admin/* 时,不渲染 SDK 脚本;SDK 已在公开页面加载后,切换到排除路由时,调用 hide() 并用样式隐藏宿主节点。单纯从 React 树移除 <Script>,无法保证 SDK 已经插入的页面节点也一起消失。
异步加载完成时,onReady 再读取当前的 window.location.pathname,根据此刻所在页面同步显示状态。这样,加载过程中发生路由变化,也不会沿用开始加载时的路径判断。
这里用到的 window.contactWidget、#contact-widget-auto 和 CSS 变量,来自本次实际使用的 Knocket SDK。后续如果 SDK 调整这些接口或节点,需要重新检查适配。路由排除负责隐藏聊天入口,后台的登录认证仍由博客原有逻辑处理。
在共享布局中挂载一次
我的博客已经有 AppChrome,因此把 <KnocketWidget /> 放在它的最外层,和原来的公开页面布局分支并列。页头、页脚、微信分享等原有组件继续保留。
下面是挂载位置的结构示意,注释处代表已有布局,不是要删掉它:
import { KnocketWidget } from "@/components/knocket-widget";
// AppChrome 内部已有 pathname、isAdmin、isLogin 等判断。
return (
<>
<KnocketWidget />
{isAdmin || isLogin ? (
children
) : (
<div className="min-h-full flex flex-col">
{/* 保留已有的分享组件和 Header */}
<main className="flex-1">{children}</main>
{/* 保留已有的 Footer */}
</div>
)}
</>
);组件自身负责排除路由,因此要保持在共享层中,让它能接收路由状态变化。没有 AppChrome 的项目,可以在根布局中挂载这个客户端组件;不要在每篇文章页面重复加入它。
接入后,我从“关于”页切到文章列表,页面中仍只有一条 Knocket SDK 脚本和一个聊天宿主节点。

检查登录页和后台入口
我分别直接访问了 /login 和 /admin/articles。登录页没有加载 Knocket SDK,也没有聊天宿主节点;未登录访问后台时,原有认证逻辑将页面重定向到登录页,同样没有加载聊天组件。

/admin 及其子路径。六 检查手机端面板和输入框
组件用了 safe-area-inset-right 和 safe-area-inset-bottom 设置边距,以适应设备安全区。小屏边距设为 12px,桌面边距设为 20px。
这次我用浏览器模拟了两组手机视口:375 × 844 和 360 × 667 CSS 像素。检查了聊天入口能否点击、展开后的面板是否覆盖视口、输入框能否使用,以及页面有没有横向溢出。
两组视口都通过检查,聊天面板和输入框可见。这里验证的是网页聊天组件在手机尺寸下的响应式表现,没有接入原生 iOS 或 Android SDK,也还没有完成实体手机软键盘弹出后的测试。

如果准备长期使用,建议再用自己的手机浏览器跑一遍:弹出键盘输入、发送消息、收起键盘、关闭面板,再重新打开。这能补上桌面视口模拟覆盖不到的交互。
七 构建部署后从正式站点验证双向消息
上线前,这两个接入文件通过了 ESLint 和 TypeScript 检查:
pnpm exec eslint src/components/knocket-widget.tsx src/components/app-chrome.tsx
pnpm exec tsc --noEmit --incremental false随后完成了生产构建。项目的 build 脚本是 next build,常规执行方式是:
pnpm build我的线上服务器内存较小,这次先取线上源码,在独立目录中只叠加两个接入文件进行本机构建,没有把工作区的其他改动一并发布。独立目录实际运行的是 node node_modules/next/dist/bin/next build,同样执行 Next.js 生产构建。构建期间使用现有配置,没有执行数据库迁移或种子脚本。
发布顺序是先在服务器上启动独立预检服务,检查新版本能否正常运行,再备份旧构建、源文件和 Nginx 配置,最后切换正式服务。旧静态资源也保留了,方便已经打开页面的访客继续请求缓存中的资源。切换后,正式首页和 15 个页面脚本资源检查通过。
消息测试从正式域名发起,按下面的顺序进行:
- 打开正式博客,点开右下角聊天入口,再点击
Start a Chat。 - 发送一条带有明确标记的测试消息,方便在 Telegram 中找到。
- 到本次连接的 Telegram Bot 聊天中,找到对应通知。
- 对那条通知选择“回复 / Reply”,输入测试回复并发送。
- 回到博客,检查刚才的访客会话是否显示回复。
我发送的内容是:
Knocket 正式站点验收:来自 https://www.mocha.wang/ 的手机端消息。
请引用回复「正式站点验收成功」。Telegram 这一侧要使用引用回复。发送前,确认输入框上方已经出现对应的原消息引用。

这次正式站点的 Telegram 通知已收到,引用回复的内容是“正式站点验收成功”。回到博客,聊天窗口里也出现了这句话。

看到这条回信,才能确认网站发消息、Telegram 收通知、Telegram 回复、网站接收回信这几步都走通了。
八 这次遇到的问题和排查顺序
最开始,我用了 Knocket 收件箱里的“模拟会话”测试。消息能出现在收件箱中,Telegram 却没有收到通知。后来改用官方嵌入脚本创建的普通访客会话,Telegram 通知和引用回复都成功了,正式博客上线后也再次通过了验收。
这个结果只说明本次两种测试入口的表现不同,不能据此认定所有模拟会话都不会推送。排查时,我会先从实际安装了 SDK 的网页发送普通访客消息,避免仅凭后台的模拟会话判断 Telegram 是否连接成功。
| 现象 | 先检查什么 |
|---|---|
| 页面没有聊天入口 | identifier 是否替换正确;SDK 是否被网络或浏览器扩展拦截;当前是否在排除路由;延后加载是否完成 |
| 收件箱有消息,Telegram 没通知 | 是否完成激活;通知开关是否开启;是否使用真实网页访客会话测试 |
| Telegram 有通知,网页没回信 | 是否对对应通知使用了引用回复;是否选择了“完整消息与引用回复” |
| 页面切换后出现重复入口 | 是否在多个页面反复挂载组件;共享层是否只保留一份 SDK |
| 后台仍出现聊天入口 | 是否只判断了 /admin,遗漏子路径;是否处理了 SDK 已加载后的隐藏 |
| 桌面正常,手机输入困难 | 再用实体手机检查软键盘、输入区位置和安全区边距 |
本次最终验收结果如下:
| 检查项 | 结果 |
|---|---|
| ESLint、TypeScript、生产构建 | 通过 |
| 正式站点服务与页面脚本资源 | 正常 |
| 公开页面导航 | 一条 SDK 脚本、一个聊天宿主节点 |
| 登录页和未登录后台入口 | 不加载 Knocket SDK 和组件 |
| 两组手机视口 | 面板、输入框正常,无横向溢出 |
| 正式站点访客消息到 Telegram | 已收到 |
| Telegram 引用回复回到博客 | 已显示“正式站点验收成功” |
下一篇 让聊天入口回答博客里的问题
人工咨询已经接通,接下来我想解决另一个具体问题:访客问“你能做哪些 AI 应用?”或者“这篇文章里提到的 Agent 工作流该怎么搭?”时,聊天窗口能否先根据博客内容给出有依据的回答,再把需要沟通的咨询交给我。
Knocket 官网提供了 AI Agent 和知识库入口,说明支持上传文档、FAQ,并在需要时转交人工。这个能力会作为 下一阶段的接入方向,本篇还没有配置或验收 AI 自动回复。
下一篇会围绕这份博客做知识库:先整理开发服务范围、个人介绍、常见咨询问题和公开文章,再检查模型接入、回答依据,以及 AI 与 Telegram 人工回复如何衔接。
我会重点测试几种问题:资料里有答案的,能不能答准;资料里没写的,会不会编造;涉及报价、排期和具体项目方案的,能不能及时交给人工。
先把“访客能联系到我”做好,下一篇再让它读懂博客。
继续阅读
去 AI 味怎么改?11 个能定位到句子的信号,附完整提示词和 4 步核对
别再一句「帮我去掉 AI 味」整篇重写。本文整理开源项目 lieflat-less-ai-tone 的 v2 规则:先划掉 6 类测下来站不住的「伪 AI 味」,再按 11 个信号逐句定位,附可直接复制的改稿提示词和改后 4 步信息核对。
WorkBuddy资料库怎么用?把常用材料整理成一份可反复调用的FAQ
用三份虚构文档实测WorkBuddy内置资料库的添加、读取、FAQ生成、保存和新任务复用。含可复制提示词、真实截图及本次积分记录,明确未提供的信息和未验证的功能。
GEO是什么?当大家开始问AI,你的内容怎样被看见
GEO(生成式引擎优化)是什么,和SEO有什么区别?用一家咖啡馆的例子,讲清AI搜索如何参考内容,以及普通人能做的5件事。
WorkBuddy 电商应用指南:选品、内容、订单与售后
一个人经营网店,怎样用 WorkBuddy 分担选品、内容、订单和售后工作?本文结合商品示例梳理工作流程,并附可复制资料、文案指令与人工核对方法。