跳到主内容
Autional 徽标
Vercel6 分钟#AI 改造#SSO#多用户#云存储#MarkText

MarkText:从桌面编辑器到多用户云端写作产品

部署平台
Vercel
框架
Next.js
技术栈
Next.js 15(App Router)· React 19 · muya(MarkText 编辑器内核)· Autional(身份)· Neon Postgres · Vercel

2026-11-04,我们把 MarkText 从一款 Electron 桌面编辑器,做成了可以直接在浏览器里使用的多用户写作产品:SSO 登录、文档按用户隔离、保存到云端数据库、支持 PWA 与独立笔记链接。改造与上线在同一天完成。

速览

项 值
上游应用 MarkText —— 开源 Markdown 编辑器(Electron 桌面端)
原项目仓库 github.com/marktext/marktext
原项目官网 marktext.app
改造结果 SSO 登录 · 按用户隔离 · 云端持久化 · 字段加密 · PWA · 独立笔记链接
技术栈 Next.js 15(App Router)· React 19 · muya(MarkText 编辑器内核)· Autional · Neon Postgres
部署平台 Vercel
用时 改造 + 上线当天完成
参考仓库 github.com/autional-demo/marktext
演示环境 marktext-web.vercel.app

关于 MarkText

MarkText 是一款开源(MIT 许可)的跨平台 Markdown 编辑器,基于 Electron 构建,主打「所见即所得」的写作体验。它支持 CommonMark 与 GFM,覆盖标题、列表、任务列表、表格、代码块、引用与脚注;也支持 KaTeX 数学公式、Mermaid 图表、代码高亮、焦点模式与快捷插入,桌面端的完成度很高。

但它有两个天然边界:只在桌面运行,以及数据只保存在本机。没有账号体系,也就没有「分享链接、换设备继续写、多人各用各的」这些能力。编辑体验很强,缺的是账号、云和多人。

为什么改造

对写作工具来说,桌面版的限制很具体:

  • 换一台电脑,文档不在;
  • 清一次缓存,历史归零;
  • 想分享一篇笔记,只能导出文件再发;
  • 没有账号,就无法区分「谁写了什么」。

因此这次改造定了四个目标:

  1. 搬上 Web:保留 MarkText 的编辑器体验,打开浏览器就能写;
  2. 加账号:支持 SSO,也保留邮箱密码登录;
  3. 上云并隔离:文档持久化到数据库,按用户隔离;
  4. 当天可用:改完即可上线,后续能持续迭代。

三个平台各自负责什么

改造没有把三件事混在一起,而是各交给一个平台:

平台 角色 具体负责
Autional 身份层 SSO(OAuth 2.0 + PKCE)、邮箱密码登录、令牌校验、提供租户与用户标识
Vercel 托管与运行时 构建与部署、Serverless API、同源 /bff 代理、GitHub push 自动发布
Neon 数据层 Postgres 持久化文档,按 tenant_id + user_id 归属,存储加密后的密文

需要说明的是:字段加密在应用层完成,Neon 里保存的是密文;解密密钥只放在服务端环境变量里。

改造步骤

整个过程拆成 10 个小目标,每个目标都有明确的验收点。

1. 把编辑器搬上 Web

目标:编辑器体验不打折。

做法:用 Next.js 15 搭 Web 应用,编辑器直接采用 MarkText 抽出的内核 muya(@muyajs/core)。渲染、工具栏、表格、公式、图表都沿用同一套内核,并补上自动保存。

结果:浏览器里获得与桌面版一致的写作体验,支持导入 / 导出 .md。

2. 接入账号与 SSO

目标:有账号体系,且默认走 SSO。

做法:接入 Autional。登录页提供「使用 Autional SSO 登录」,采用授权码 + PKCE 的公开客户端;同时保留邮箱密码登录,注册走身份服务。登录后由 SDK 管理会话,登出回到登录页。

结果:登录、注册、登出闭环;令牌过期会自动刷新,多标签页状态同步。

3. 用同源代理连接浏览器与身份服务

目标:浏览器调用身份接口时不受跨域限制。

做法:应用内提供 /bff 同源代理,把身份与 OAuth 请求转发到 Autional;OIDC discovery 也走同源。浏览器只与自己的域名通信。

结果:登录与换票稳定,不再依赖第三方域名的 CORS 配置。

4. 设计文档数据模型

目标:一个人一份数据,能排序、能软删除。

做法:在 Neon 建 documents 表:id、tenant_id、user_id、title、content、rev、deleted_at、创建 / 更新时间;按「租户 + 用户 + 更新时间」建索引。

结果:列表按最近更新排序,删除是软删除,历史数据可保留。

5. 提供文档读写 API

目标:前端只通过一套 REST 接口操作文档。

做法:提供列表、新建、读取、保存、删除五个接口;单文档正文上限 2 MB,列表上限 500 条;新建允许客户端带上 id,用于把本机旧数据上传。

结果:文档的完整生命周期都在服务端完成,前端不直接接触数据库。

6. 数据隔离与字段加密

目标:跨用户读不到,密文也搬不走。

做法:所有查询强制带 tenant_id + user_id;标题与正文用 AES-256-GCM 加密,并把「租户 + 用户 + 文档 + 字段」作为附加认证数据(AAD)绑定到密文上。

结果:换一个账号登录,看不到别人的文档;把密文复制到另一条记录也无法解密。

7. 给 API 加会话门

目标:没有登录就不能读写。

做法:文档 API 要求 Bearer 令牌,服务端先检查有效期,再向身份服务 /me 做权威校验(结果缓存 60 秒)。校验通过才拿到可信的用户与租户。

结果:无 token、伪造 token 一律 401;正常会话下接口才返回数据。

8. 同步、冲突与离线

目标:写起来像本地应用,数据却在云上。

做法:本地保留缓存,输入停止约 1.6 秒后写云端;每条文档带 rev 版本号,保存时做乐观锁,冲突返回 409 并带回云端版本,由用户选择「载入云端」或「用本机覆盖」。同时提供 PWA,可安装、可离线打开。

结果:刷新页面、换设备都能恢复;网络恢复后自动同步;冲突不会静默覆盖。

9. 独立笔记链接

目标:每条笔记都有自己的地址。

做法:新增 /d/<id> 路由,打开即定位到对应文档,支持刷新、深链和浏览器前进后退。

结果:笔记可以被收藏、被分享,链接直接落到内容。

10. GitHub → Vercel 上线

目标:发布流程可重复。

做法:代码托管在 GitHub,Vercel 项目绑定仓库的 main 分支,push 即自动构建与发布;环境变量在 Vercel 项目里配置,函数区域固定为 sin1。

结果:改造当天上线,后续每次 push 自动更新,不再手工部署。

最终成果

线上:marktext-web.vercel.app 代码:github.com/autional-demo/marktext

能力 结果
登录 SSO + 邮箱密码,登出干净回落
多用户 按租户 + 用户隔离,互不可见
云端 Neon 持久化,清本地缓存可恢复
加密 字段级 AES-256-GCM,密文绑定归属
并发 rev 乐观锁,冲突二选一
多端 PWA 可安装,独立笔记链接
发布 GitHub → Vercel,push 即上线

可核验的结果:

  • 构建通过;
  • 身份集成测试 8/8(discovery、注册、登录、资料、令牌、登出、吊销、认证配置);
  • SSO 预检 2/2(authorize 302 回指回调、CORS 204);
  • 授权码全链路(authorize → code → token → userinfo)全部 200;
  • 云端文档端到端 13/13(创建、列表、读取、保存、冲突、密文校验、删除);
  • 生产接口:带令牌 200,无令牌 401。

一句话总结这套结构:Autional 管「你是谁」,Vercel 管「在哪跑」,Neon 管「存在哪」,编辑器继续做它最擅长的事。

发起 prompt(逐字存档)

2026-11-04 发起改造时交给 AI 编码助手的 prompt 原文:

1. 帮我下载marktext, 并安装。   2.  参考 https://www.autional.com/cases/nextchat 把 marktext 发布到我的 vercel 。 3. 请读取 https://www.autional.cn/ai/skill.md,并据此为当前项目接入 Autional 登录。
若打不开,改用国内镜像:
https://cdn.autional.cn/ai/latest/SKILL.md

自己试一遍

把同样的 prompt 换成你的项目地址,交给 AI 编码助手(Claude Code、Cursor 等)即可。想直接开始,看 AI 接入指南。

想给自己的项目做同样的改造?

把你的项目交给 AI 编程助手:一句 prompt 接入 Autional 登录与多用户能力,每个阶段先与你确认。