我做 ToolGarden 的起点很简单:很多日常小工具确实方便,但我不想为了格式化一段 JSON、压缩一张证件照、查看一个 JWT,或者合并一份 PDF,就把内容交给一个不知道怎么存储和转发数据的服务器。
开发时经常会遇到这种场景:接口返回里有用户信息,日志里有订单号,JWT 里有租户 ID,截图里有内部系统页面,PDF 里有合同或报名材料。它们未必都是最高等级的机密,但也不应该随手上传到第三方在线工具。于是我决定做一个在线工具站,但核心约束是:工具输入尽量只在用户自己的浏览器里处理。
这个网站不是把本地处理当成一句口号,而是把“不要把用户输入交给服务器”作为架构约束。
为什么一定要本地处理?
很多在线工具的风险不在于功能本身,而在于你很难知道数据上传之后发生了什么:有没有写入日志、有没有被临时缓存、有没有经过第三方队列、有没有被用于调试或训练。对开发者来说,一段 JSON 样本可能包含真实用户 ID;对设计和运营同学来说,一张图片可能包含尚未公开的活动素材;对普通用户来说,一个 PDF 可能就是证件、合同或报名表。
本地处理不能解决所有安全问题,但它能先消掉一个很大的暴露面:文件和文本不必离开设备。只要能力允许,我宁愿让浏览器多做一点工作,也不把处理过程搬到服务器上。
整体架构:静态站点加浏览器运行时
ToolGarden 用 Next.js App Router、TypeScript 和 Tailwind CSS 做界面,但部署形态尽量保持静态化。页面、脚本、模型资产和 WASM 文件可以被浏览器下载,真正的输入处理发生在客户端:解析、转换、渲染、压缩、合并、导出,都由浏览器里的 JavaScript、Web API、Worker 或模型推理完成。
Tool page
-> React state and user controls
-> lib/utils pure functions
-> Browser APIs, Web Workers, Canvas, Web Crypto, WASM, or local model inference
-> Blob, download, preview, copy
No API route receives the pasted text or uploaded file.这个结构有一个直接好处:服务端不需要接收用户粘贴的 JSON、不需要接收上传的图片、不需要接收 PDF 原文。服务器提供的是应用代码和静态资源,用户的数据留在浏览器进程里。
页面保持很薄,复杂逻辑放进纯函数
为了让“本地处理”不变成页面里到处散落的临时代码,我把工具页面压得很薄。页面主要负责 useState、输入框、按钮、预览和错误展示;真正的解析、转换、校验、压缩逻辑放在 lib/utils 里,按纯函数方式返回结果。
type Outcome =
| { ok: true; output: string; parsed?: unknown }
| { ok: false; message: string };这样做有两个目的。第一,工具逻辑可以独立理解和测试,不需要依赖 React 状态。第二,页面不会直接写 JSON.parse、文件解析、diff 算法或图片导出细节,避免每新增一个工具就复制一份隐性风险。
不同类型的数据如何留在浏览器里
| 类型 | 浏览器本地实现 | 隐私收益 |
|---|---|---|
| JSON / YAML / XML / CSV | 使用本地解析库和纯函数完成格式化、转换、修复和校验。 | 接口样本、配置片段和日志不需要上传。 |
| JWT / 编码解码 | Base64URL、URL、Unicode、Gzip、Hash 和 HS256 校验使用浏览器能力与 Web Crypto。 | Token 排查可以在本地查看 Header 和 Payload。 |
| 图片 | File、Blob、ImageBitmap、Canvas、OffscreenCanvas、Worker、WASM 和本地模型完成压缩、转换、编辑和导出。 | 截图、证件照、产品图和内部素材不离开设备。 |
| PDF / Office / 文档 | pdf-lib、pdfjs-dist、fflate、SheetJS 等在浏览器里读取、生成、拆分、合并或导出。 | 合同、报名材料和内部文档减少上传暴露。 |
| 文本和字幕 | diff、字数统计、LRC/SRT 解析和媒体预览都在前端完成。 | 临时文案、日志和字幕文件不必经过服务器。 |
AI 功能也尽量本地化
图片去背景、证件照抠图、图片去水印这类功能听起来天然像“要传到云端 AI 服务”。但在这个站里,我优先选择能在浏览器中运行的开源模型或本地算法。第一次使用时,浏览器可能需要下载模型资产;模型加载完成后,用户图片会在本地解码、归一化、推理、合成和导出。
这并不意味着本地模型永远比商业云服务更强。它的边缘处理、复杂背景鲁棒性和大批量稳定性都有边界。但对日常证件照、商品图、简单背景、截图修补来说,本地模型已经足够有用,而且换来了一个重要优势:图片不用上传。
发现入口也要诚实表达隐私定位
做工具站时,SEO、sitemap、JSON-LD、llms.txt、Open Graph 很容易变成“写给搜索引擎看的另一套文案”。我不想让这些入口和实际能力脱节,所以把 SEO 描述统一从 registry 和 messages 派生,再在生成层补充本地处理、无需上传和隐私友好的说明。
这件事看起来只是营销文案,实际上是工程约束的外显:如果一个工具没有接入 registry、没有对应页面、没有本地处理说明、没有进入 sitemap 和 AI 发现文件,它就不应该被当作正式能力发布。
本地处理不是没有代价
- 浏览器内存有限,大批量图片、超大 PDF 或几百个文件同时处理,可能会变慢甚至让标签页崩溃。
- 复杂 Office 文档的排版引擎和桌面软件不同,导出 PDF 后仍需要人工复查。
- AI 模型首次运行需要下载模型资产,弱网或离线状态下可能无法启动。
- 某些旧格式或加密格式并不适合浏览器内直接解析,需要明确标注限制,而不是假装支持。
- 本地处理减少上传风险,但用户仍然需要在可信网络、可信浏览器和 HTTPS 页面中使用工具。
我最后得到的原则
- 能在浏览器完成的,就不要传到服务器。
- 页面只负责交互,工具逻辑进入纯函数和 Worker。
- 文件处理要告诉用户边界,不夸大兼容性。
- SEO 和博客文案必须如实反映技术实现。
- 隐私不是最后加的一句标语,而是从架构开始就要守住的约束。
总结
我建立这个站,不是因为本地处理听起来更酷,而是因为它让我在使用在线工具时少一点不安。一个好用的工具站应该让人放心地粘贴一段数据、拖入一个文件、下载结果,然后关掉页面,而不是让用户反复猜测这些内容去了哪里。
ToolGarden 还会继续扩展工具数量,但我希望它一直保持这个方向:把复杂处理尽量放到浏览器里,把工具逻辑做清楚,把限制说清楚,让隐私安全成为默认体验的一部分。