cd ..
$ cat indie-dev-journey-id-watermark.md

独立开发者出海:从零上线一个证件照水印工具

从想法到上线,从 Web 到 Chrome 扩展,从免费到 Creem 支付接入——记录 ID Watermark 的完整开发历程和踩坑经验。

decong20772026/07/132 min read

今年我开始做一个证件照水印工具,后来它变成了一个完整的出海产品。这篇文章记录整个过程。

为什么做这个工具?

想法很简单:国内办很多业务需要上传身份证、护照照片,但直接传原图不安全。加水印是刚需,但市面上没有好用的在线工具——要么要注册,要么会上传图片到服务器。

核心原则:所有处理在浏览器本地完成,不上传任何图片。

技术选型

技术 选择原因
Next.js 15 熟悉,SSR 对 SEO 友好,静态导出成本低
Canvas 2D 纯前端图片处理,不需要后端
Tailwind CSS 够快,够轻
WXT Chrome 扩展框架,开发体验好
Creem.io 海外支付,支持 License Key 模式

Canvas 2D 水印引擎

核心是 Canvas 渲染。单点模式直接计算文字位置即可,平铺模式的关键是间距控制:

// 简化示意:遍历网格,在每个交点绘制水印文字
const step = fontSize + gap;
for (let r = -rows / 2; r < rows / 2; r++) {
  for (let c = -cols / 2; c < cols / 2; c++) {
    ctx.fillText(text, c * step, r * step);
  }
}

实际实现还要处理旋转角度、透明度、对齐方式等,但核心逻辑就这么几行。

支付接入:Creem.io

海外支付是最头疼的一环。Stripe 门槛高,Paddle 审核慢。最后选了 Creem.io:

  • License Key 模式,不需要自己管理用户系统
  • API 简单,验证和激活只需要几个接口
  • 5 美金/月,定价灵活

SEO:真正的坑

这是花时间最多的地方。独立站没人看,SEO 必须做好,但每一步都在踩坑:

坑 1:Sitemap 里写了错的 URL

因为用了 next-intllocalePrefix: 'as-needed',默认中文 locale 的 sitemap 写了 /zh,但 /zh 实际返回 307 跳转到 /。Google 跟着 sitemap 爬到一个跳转页,然后 canonical 又指回 /zh——陷入死循环。

修复:默认 locale 的 URL 不加前缀,/zh 改为 /

坑 2:CSP 拦住了自己的 GA4

配了 Content Security Policy,但在控制台发现 GA4 数据一直为零。查了半天发现 connect-src 只写了 google-analytics.com,但 GA4 新版本用的是 analytics.google.com

坑 3:子域名不被信任

主站 902077.xyz 和工具站 id-watermark.902077.xyz 是不同站点。Google 不会自动把主站的权重给子域名,必须在 Search Console 分别提交验证。

Chrome 扩展

Web 版做完后,我又用 WXT 做了 Chrome 扩展。技术实现上最有趣的部分是 Shadow DOM 样式隔离:

const shadow = container.attachShadow({ mode: 'open' });
const root = ReactDOM.createRoot(shadow);
root.render(<App />);

不这么做的话,扩展的样式会污染用户正在浏览的页面。

一些数据

  • 一个 full-stack 开发者独立完成全部工作
  • 从想法到上线 Web 版:约 3 周
  • 再加 Chrome 扩展:1 周
  • 基础设施成本很低(Vercel Hobby 额度足够)

总结

出海独立开发最大的挑战不是写代码,而是让产品被看到。SEO 配置、站点结构、外链建设——这些比功能本身花的时间还多。

工具地址:id-watermark.902077.xyz

$ echo "EOF"

评论交流