这次我们来看一个开源项目:NextBlock CMS。它发布在 Show HN 上,定位是面向 Next.js 16 和 Supabase 的 full-stack CMS。简单说,它不是传统博客系统,也不是类似 WordPress 那种需要单独部署后端的 PHP 应用,而是把内容数据、用户认证、文件存储和接口能力全部收进 Next.js + Supabase 这套现代技术栈里。
如果你正在做 Next.js 项目,又需要一套可定制的内容后台,或者你在调研“Supabase 怎么真正落地到业务里”,这个项目值得拿来当参考。下面我会从项目定位、环境准备、启动方式、功能验证、API 接入、性能观察和常见排查这几个角度,带你完整过一遍。需要提前说明的是,这类开源项目迭代很快,文章里涉及的命令、表名、接口路径都是通用模板,实际使用时要先以项目仓库里的 README 和 package.json 为准。
1. 核心能力速览
从项目标题可以看出,NextBlock CMS 的核心组合是 Next.js 16 + Supabase。Next.js 负责页面渲染、路由和前后端一体化的开发体验,Supabase 负责 PostgreSQL 数据库、Auth 认证、Storage 存储和实时能力。下面这张表可以快速帮你判断这个项目值不值得继续往下看。
| 能力项 | 说明 |
|---|---|
| 项目类型 | 开源全栈 CMS,代码和文档以 GitHub 仓库为准 |
| 前端框架 | Next.js 16 |
| 后端基础设施 | Supabase,包含 Postgres、Auth、Storage、Realtime 等能力 |
| 内容管理 | 通常覆盖文章/页面的创建、编辑、发布、列表管理,具体内容模型由项目定义 |
| 用户认证 | 基于 Supabase Auth,支持邮箱密码、OAuth 等方式,需要看仓库配置 |
| 文件存储 | 基于 Supabase Storage,适合存放图片、附件、导入素材 |
| 接口能力 | 通过 Next.js Route Handlers 或 Supabase 服务端 API 提供数据接口 |
| 启动方式 | npm/pnpm 启动本地开发服务,接入远端 Supabase 或本地 Supabase |
| 是否支持批量任务 | 取决于项目实现,可通过脚本或 Supabase Edge Functions 补充 |
| 适合场景 | 个人博客、企业内容站、SaaS 后台、全栈项目脚手架参考 |
从这些能力看,NextBlock CMS 最值得关注的是“全栈”两个字。过去写 CMS,要么用 WordPress 这类成熟系统,要么用 headless CMS 再自己写前端。它的思路是把整个内容系统建在 Next.js 和 Supabase 上,数据库、认证、存储、管理界面和前端渲染都在一个工程里完成。这种模式对前端开发者来说,最大的好处是技术栈统一,不需要专门维护一套后端服务。
不过要提醒一句:项目目前的信息主要来自标题和公开定位,具体内置多少功能、支持哪些内容类型、管理界面长什么样,需要拉下代码或者看仓库的 README 才能确定。下面的内容,我会基于“Next.js + Supabase 全栈 CMS”这个通用方向来展开,给你一套可落地的调研和验证方案。
2. 适用场景与使用边界
2.1 适合什么人用
如果你是前端开发者,或者小规模全栈团队,NextBlock CMS 这类项目会很容易上手。你不需要单独学习一套后端框架,因为 Next.js 已经解决了页面和接口两部分,Supabase 又帮你把数据库、认证、存储这些原本很重的后端能力变成了可以调用的服务。用它来搭个人博客、团队内容站,甚至客户项目的后台,开发节奏会比传统方案快不少。
如果你正在做 Next.js 商业化项目,打算给客户交付一个内容可维护的站点,这类 CMS 的参考价值也很高。它展示了一条可以复用的路线:内容模型怎么建、接口怎么暴露、管理后台怎么和前端共享代码、资源文件怎么放到 Supabase Storage、权限怎么通过 Supabase Auth 控制。
2.2 不适合什么场景
它不适合完全没有技术背景的内容编辑。虽然 CMS 一般是给运营人员用的,但 NextBlock CMS 这类开发者向项目,通常默认使用者能看懂 Next.js 目录结构,至少能跑命令行。如果需要一个开箱即用的可视化编辑器,或者需要大量插件生态,还是应该考虑 WordPress、Strapi、Directus 这类更成熟的内容管理系统。
如果你的内容量极大,比如千万级文章、复杂的全文检索、多语言工作流,就需要谨慎评估。Supabase 底层是 PostgreSQL,数据规模和查询能力不错,但 CMS 本身往往没有针对海量内容做专项优化,很可能需要你自行设计分页、索引、缓存和搜索方案。
2.3 使用边界与合规提醒
不管用的是 NextBlock CMS 还是其他 CMS,内容平台的合规问题都不能省。
- 文章、图片、视频、音频素材必须有合法授权,不能直接拿未授权资源上传到 Supabase Storage。
- 如果系统支持用户注册和评论,需要做好用户协议、隐私政策、内容审核和敏感词过滤。
- Supabase Storage 里的文件如果设置为公开读,要注意版权内容是否允许公开分发;如果设置为私有读,要注意服务端鉴权是否到位。
- 涉及用户实名信息时,必须遵守相关隐私保护法律法规,不要过度采集。
- 不要用 CMS 搭建违反平台规则、传播违法信息或侵害他人权益的站点。
技术本身是中性的,但上线前一定要把内容安全和授权问题提前设计进去。
3. 环境准备与前置条件
3.1 本地开发环境
在安装 NextBlock CMS 之前,建议先确认本地环境满足以下条件。具体 Node.js 版本要以后项目的 engines 字段为准,但基于 Next.js 16 的常见要求,建议使用 Node.js 20 或更高版本。
node -v npm -v git --version docker --version上面的命令会输出你当前的 Node、npm、Git 和 Docker 版本。如果其中某项没有安装,需要先去对应官网安装。
- Node.js:提供 JavaScript 运行环境,Next.js 项目运行的基础。
- npm / pnpm:依赖包管理器,项目锁文件里一般能看到推荐用哪个。如果仓库里有
pnpm-lock.yaml,建议优先用 pnpm。 - Git:拉取项目代码、查看版本记录。
- Docker:不是必须,但如果你不想用远程 Supabase,而是打算在本地完整启动一套 Supabase,就需要 Docker。
3.2 Supabase 环境
NextBlock CMS 使用了 Supabase,所以你需要有一个可用的 Supabase 项目。有两种方式:
第一种,使用 Supabase 云服务。前往 Supabase 官网创建一个新项目,拿到的项目 URL 和 anon key 可以用于本地开发配置。第二种,使用 Supabase CLI 自托管。在本地跑一套 Supabase 环境,适合不想把数据放在外部服务、或者离线开发的情况。
supabase init supabase startsupabase start会在本地启动 Supabase 的核心服务,包括 Postgres、Auth、Storage 和 Studio 管理面板。这种方式需要 Docker,而且首次启动会拉取 Docker 镜像,耗时取决于网络环境。
3.3 环境变量配置
大多数 Next.js + Supabase 项目都会读取.env.local文件中的环境变量。如果你用的是远程 Supabase,至少要配置这两个值:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key注意,NEXT_PUBLIC_前缀开头的变量会暴露给浏览器端,所以只能放 anon key 这类公开密钥。服务端操作需要的 service_role key 只能放在服务端环境变量里,绝不能写进前端代码。
如果项目自带数据库迁移脚本,还需要在启动前把表结构同步到你的 Supabase 项目。
supabase db push这一步很关键。很多项目拉下来直接npm run dev,结果启动时报表不存在,就是因为数据库迁移没有执行。
4. 安装部署与启动方式
4.1 克隆项目
先把 NextBlock CMS 仓库克隆到本地。仓库地址需要以实际项目为准,下面只给通用示例。
git clone https://github.com/yourname/nextblock-cms.git cd nextblock-cms4.2 安装依赖
安装依赖前,先看仓库里有没有package-lock.json、pnpm-lock.yaml或yarn.lock,以锁文件为准选择包管理器。如果锁文件是 pnpm,就统一用 pnpm。
npm install # 或者 pnpm install # 或者 yarn install安装过程如果出现网络超时,可以考虑在 npm 配置中临时切换镜像源,但镜像源属于环境相关的调整,建议按实际情况处理,不要盲目更改。
4.3 配置环境变量
创建.env.local文件,把 Supabase 的信息填进去。如果项目有.env.example文件,直接复制它再修改。
cp .env.example .env.local然后编辑.env.local,填入你的 Supabase 项目信息。不要把这个文件提交到 Git,尤其不能提交任何 secret key。
4.4 启动开发服务
依赖安装完成、环境变量配置好后,执行下面命令启动开发服务器:
npm run dev启动成功后,终端会输出本地访问地址,一般是http://localhost:3000。打开浏览器访问这个地址,你应该能看到 CMS 的前台页面或引导安装界面。如果页面直接报错,优先回去检查环境变量和数据库迁移是否完成。
4.5 生产构建与部署
开发环境没问题后,如果要部署到线上,建议先在本地验证生产构建是否通过:
npm run build npm start生产构建会执行 TypeScript 类型检查、ESLint 检查和静态优化,报错信息会比开发模式更明显。确认构建通过后,可以部署到 Vercel、Netlify 或自己的 Node.js 服务器。部署时记得在平台上配置相同的环境变量。
5. 功能测试与效果验证
无论 NextBlock CMS 具体实现了哪些模块,只要它定位为 CMS,下面几个功能点就值得优先测试。测试时不要只盯着页面是否显示,还要结合 Supabase Dashboard 里的数据表、日志和网络请求,看数据链路是否完整。
5.1 内容创建与发布
测试目的:确认 CMS 的核心能力是否打通,即管理界面能创建内容,前台页面能展示内容。
操作步骤:
- 打开 CMS 管理后台,通常在
/admin或/dashboard路径下。 - 创建一个新文章或新页面,填写标题、正文、摘要等内容。
- 选择发布状态,点击保存。
- 打开前台页面,刷新列表,确认内容出现。
预期结果:
- 后台提示保存成功。
- 前台页面能看到刚刚创建的内容。
- Supabase 中对应的表新增了一条记录,
created_at时间正常。
失败排查:
- 如果没有保存成功,打开浏览器开发者工具的 Network 面板,查看提交请求的响应状态。500 通常表示数据库表结构或权限有问题。
- 如果保存成功但前台不显示,可能是页面使用了缓存或静态生成,需要等待重新验证,或者手动触发刷新。
- 如果前台报错,查看 Next.js 服务端日志,重点看 Supabase 查询是否被权限拦截。
5.2 用户认证与权限控制
测试目的:验证登录注册流程,以及后台内容操作是否需要登录。
操作步骤:
- 访问用户注册页面,用新邮箱注册一个账号。
- 退出登录,尝试直接访问管理后台地址。
- 未登录时,后台是否跳转到登录页。
- 登录后再次访问后台,确认可以正常操作。
预期结果:
- 注册成功后,Supabase Auth 用户列表中新增该用户。
- 未登录用户不能访问管理界面,匿名请求被重定向到登录页。
- 登录用户可以通过中间件或路由守卫进入后台。
失败排查:
- 注册邮件一直发不出去,检查 Supabase Auth 的邮件模板和 SMTP 配置。
- 登录成功但跳转失败,检查重定向 URL 白名单是否包含本地地址
http://localhost:3000。 - 如果项目里配置了行级安全策略(RLS),还要确认登录用户在数据库表中是否拥有对应权限。
5.3 文件上传与存储
测试目的:验证图片、附件是否正确上传到 Supabase Storage,并且前台能正常访问。
操作步骤:
- 在后台编辑内容时,插入一张图片。
- 查看上传请求的目标地址,确认指向 Supabase Storage。
- 打开 Supabase Dashboard 的 Storage 页面,查看 Bucket 是否出现文件。
- 在前台页面访问图片 URL,确认图片能正常加载。
预期结果:
- 文件上传成功后返回可访问的 URL。
- Storage Bucket 存在对应文件,大小和元数据正确。
- 图片在页面中的展示正常。
失败排查:
- 图片加载失败,首先判断 Bucket 是公开还是私有。如果是私有 Bucket,需要服务端生成带签名的 URL。
- 如果上传请求返回 403,检查 Storage 的权限策略,以及登录用户的角色是否允许写入。
- 如果文件太大上传失败,检查 Supabase 的请求体大小限制,必要时调整前端压缩逻辑。
5.4 API 数据接口
测试目的:确认 CMS 的接口能返回结构化数据,方便后面接前端或第三方系统。
操作步骤:
- 查看项目中 route handler 或 API 目录,找到文章列表接口。
- 在浏览器访问
/api/articles之类地址,或使用 curl 请求。 - 确认返回 JSON 中包含文章列表。
通用 curl 示例:
curl http://localhost:3000/api/articles预期结果:
- 返回 JSON 数组或包含 data 字段的对象。
- 文章字段和数据库表字段一致。
- 未登录或权限不足时,返回 401 或 403,而不是泄露全部数据。
失败排查:
- 404 表示接口路径不对,去代码里确认实际路由。
- 401/403 表示接口鉴权拦截,查看中间件或 API 处理函数中的权限判断逻辑。
- 500 表示服务端查询出错,查看 server 日志,大概率是 Supabase 表名或 RLS 策略问题。
5.5 响应式与页面渲染
测试目的:确认 CMS 前台在不同设备上表现正常,同时观察页面渲染模式是否符合预期。
操作步骤:
- 打开一篇文章页面,分别用浏览器响应式模式和手机真机访问。
- 查看 Next.js 页面的渲染模式,是静态生成(SSG)、服务端渲染(SSR)还是客户端渲染(CSR)。
- 打开页面源码,确认搜索引擎能否抓取到正文内容。
预期结果:
- 移动端布局不溢出,图片自适应。
- 关键页面源码中包含内容,而不是空壳 JS。
- 页面加载速度能接受。
失败排查:
- 如果整站都是客户端渲染,SEO 会受影响。这时可以按需改成 SSR 或 ISR。
- 如果图片加载慢,检查是否接入了图片优化组件和 CDN。
- 如果页面包体积很大,检查是否引入了不必要的客户端依赖。
6. 接口 API 与批量任务
6.1 Next.js API 与 Supabase 的协作
在 Next.js 14 之后的 App Router 中,接口通常写在app/api目录下。NextBlock CMS 这类项目大概率也沿用这个模式。你可以通过一个 route handler 把 Supabase 的数据暴露成 JSON 接口。
下面的代码是一个常见的模板,实际表名、权限和鉴权逻辑需要按项目调整:
// app/api/articles/route.js import { createClient } from '@supabase/supabase-js' export async function GET() { const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.SERVICE_ROLE_KEY ) const { data, error } = await supabase .from('articles') .select('id, title, slug, created_at') .order('created_at', { ascending: false }) .limit(20) if (error) { return Response.json({ error: error.message }, { status: 500 }) } return Response.json({ data }) }这里强调一下,SERVICE_ROLE_KEY只能在服务端使用,绝对不能出现在客户端代码中。如果有中间件或者前端页面直接请求这个接口,接口侧要做好校验,避免任何人都能读取全量数据。
6.2 curl 调用示例
启动开发服务后,可以用 curl 验证接口是否可用:
curl -H "Content-Type: application/json" \ http://localhost:3000/api/articles如果接口要求登录,还需要带上 Authorization 头,把 Supabase 返回的 access token 传给服务端。
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ http://localhost:3000/api/articles6.3 批量导入内容
CMS 上线时,经常需要把旧站内容迁移到新系统。这时候可以写一个 Node.js 脚本,通过 Supabase 服务端客户端批量插入数据。
// scripts/import-articles.js import { createClient } from '@supabase/supabase-js' import fs from 'fs/promises' const supabase = createClient( process.env.SUPABASE_URL, process.env.SERVICE_ROLE_KEY ) const raw = await fs.readFile('./articles.json', 'utf-8') const articles = JSON.parse(raw) const BATCH_SIZE = 50 async function importArticles() { for (let i = 0; i < articles.length; i += BATCH_SIZE) { const batch = articles.slice(i, i + BATCH_SIZE) const { data, error } = await supabase.from('articles').insert(batch) if (error) { console.error('批量插入失败,起始位置:', i, error) process.exit(1) } console.log('已插入', data.length, '条') } } importArticles()运行脚本前,先确认articles.json的字段和数据库表结构一致。批量任务最好分批执行,避免一次性插入过多数据导致内存或数据库连接压力过大。生产环境建议加上日志记录和失败重试逻辑,比如插入失败的记录落到本地文件,方便二次处理。
6.4 定时发布与自动化
CMS 平台经常会遇到定时发布的需求。除了在应用内写定时器,更推荐使用 Supabase Edge Functions 的定时触发器。
一个简单的思路是:在数据库中新增scheduled_at字段,定时任务每隔一段时间查询scheduled_at <= now()且status = 'draft'的文章,把它们置为published。这样可以把发布逻辑集中到数据库层面,页面读取时直接按published状态过滤,避免设计复杂的任务队列。
批量任务的稳定关键是幂等。比如重复执行定时发布任务,不会重复插入内容或错误修改状态。实现时可以通过update ... where status = 'draft'这样的条件更新来保证只处理一次。
7. 资源占用与性能观察
7.1 本地开发的资源占用
NextBlock CMS 是 Node.js 应用,资源占用主要体现在 CPU 和内存上,不涉及 GPU。开发模式启动后,Node 进程会持续占用内存。如果你通过 Dock 运行 Supabase 本地方案,还需要额外占用 Docker 容器的资源。建议用top或系统监控工具观察整体情况:
top -o %MEM重点看几类进程:
node:Next.js 开发服务进程。docker:本地 Supabase 依赖容器,包括 postgres、auth、storage 等。chrome:如果你同时打开浏览器调试,浏览器本身也会很占内存。
很多项目启动慢、页面刷新卡,不一定是代码不行,而是同时启动了多个服务,内存不够。本地开发时建议先关闭不用的应用。
7.2 页面性能观察
CMS 页面的性能主要看两个阶段:数据查询和页面渲染。
用浏览器开发者工具的 Network 面板,可以看到每个请求的时间。如果/api/articles请求耗时很长,优先检查 Supabase 查询有没有走索引。低频文章表数据量少时问题不明显,但到了几万条数据,没有索引的分页查询会比较慢。
Next.js 的渲染模式同样影响性能:
- SSG 适合内容不频繁变化的公开页面,构建时生成 HTML,访问速度快。
- ISR 适合有内容更新但容忍延迟的场景,可以设置
revalidate时间。 - SSR 适合个性化内容,但每次访问都会执行服务端逻辑,需要控制查询次数。
- CSR 开发简单,但 SEO 和首屏性能不如服务端渲染。
CMS 的前台页面建议优先采用 SSG 或 ISR,配合 Supabase 的 webhook 或手动重新验证,在更新内容时触发页面重新生成。
7.3 降低资源占用的常用手段
- 数据库查询限制返回字段,不一次
select *。 - 列表页分页,不要一次性拉全量数据。
- 图片上传时做压缩和格式转换,避免大量大图保存到 Storage。
- 给频繁查询的字段加索引,例如
slug、status、created_at。 - 前端全局状态不要塞太多内容数据,能静态化就静态化。
- 开发环境中本地 Supabase 如果不用,就关掉 Docker 容器,避免长期占用内存。
8. 常见问题与排查方法
8.1 问题排查表格
下面是 Next.js + Supabase CMS 项目上线前后最容易遇到的问题,直接整理成表格。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| npm install 失败 | Node 版本过旧或网络问题 | 执行node -v,查看报错日志 | 升级 Node,或切换网络环境后重试 |
| 页面启动后 404 | 路由路径或环境变量错误 | 查看 Next.js 路由目录,确认路径 | 按项目实际路由访问,核对.env.local |
| Supabase 连接超时 | 本地网络不通,或项目地址填错 | 在浏览器直接访问项目 URL | 确认 Supabase 项目可用,检查 URL 格式 |
| 数据库表不存在 | 未执行数据库迁移 | 查看supabase目录和迁移文件 | 执行supabase db push |
| 内容保存失败 | RLS 策略禁止写入 | 检查 Supabase 表权限和 RLS 策略 | 为服务端角色或登录用户开放权限 |
| 登录后无法访问后台 | 中间件鉴权或重定向配置错误 | 查看中间件代码,检查 Auth 重定向 URL | 配置白名单路径,修正重定向 |
| 图片上传失败 | Storage Bucket 未创建或权限不足 | 打开 Storage 页面检查 Bucket | 创建 Bucket,设置合适的访问权限 |
| API 返回 401 | 接口鉴权未通过 | 检查请求头是否携带 token | 在客户端请求中补充 Authorization |
| API 返回 500 | 服务端数据库查询异常 | 查看服务端日志和 Supabase 日志 | 检查表名、字段名、RLS 策略 |
| 构建失败 | TypeScript 类型错误或依赖缺失 | 查看构建日志的完整报错 | 修复类型错误,重新安装依赖 |
| 内容更新但前台不刷新 | SSG/ISR 缓存未失效 | 查看页面缓存策略 | 调低revalidate时间或手动触发重新验证 |
| 后台编辑卡顿 | 数据量过大或请求过多 | 打开 Network 面板看请求耗时 | 分页加载,减少单次数据量 |
8.2 重点问题展开
第一类是环境变量错误。所有 Next.js 全栈项目里,环境变量配错都是最高频的问题。建议在项目启动前,写一个简单的环境变量检查脚本,把必填变量打出来,避免进入页面后才暴露错误。
第二类是 Supabase RLS 策略。很多开发者本地开发时没有开启 RLS,一切正常;一旦开启行级安全,匿名请求会读取不到数据。此时需要明确:前台公开内容是否允许匿名读,后台写操作是否需要登录用户才能执行。不要图省事直接disable row level security,这会破坏数据安全边界。
第三类是 Next.js 的缓存问题。CMS 前台页面做了静态生成后,内容更新不会立刻展示。遇到这类问题,先不要急着怀疑代码,看一下页面是 SSG、ISR 还是 SSR,根据模式决定是否需要重新验证缓存。
9. 最佳实践与使用建议
9.1 环境与配置管理
- 把
.env.local加入.gitignore,不要让密钥进入版本库。 - 生产环境的 Supabase URL、anon key 写在部署平台的 Environment Variables 中。
- service_role key 只用于服务端脚本,不允许出现在前端包中。
- 建议准备
.env.example,把需要配置的变量名和用途列清楚,方便新成员加入。
9.2 内容模型设计
使用 CMS 前,先认真规划内容模型。文章、页面、分类、标签、作者这些概念,应该设计成独立表还是字段,决定了后续扩展的灵活性。建议参考经典 CMS 设计,把公共字段抽象出来,例如slug、title、content、status、published_at、updated_at,避免每个内容类型都重复造轮子。
如果站点内容以技术博客为主,还可以设计excerpt摘要字段、cover_image封面图字段和tags标签关系表。后续要加搜索,基于这些字段会方便很多。
9.3 权限和内容安全
Supabase 的 RLS 是一种很灵活的安全机制。建议至少实现三类规则:
- 公开内容:匿名用户可读。
- 作者内容:登录用户可以创建和编辑自己的内容。
- 管理员内容:仅管理员角色可以删除或修改他人内容。
Supabase 的 Custom Claims 或 profiles 表可以存角色信息。接口层也要配合校验,不能只依赖前端隐藏按钮来保障权限。
9.4 批量任务和日志
批量导入、定时发布、历史内容清理都属于高危操作。建议所有批量任务都分别记录日志,包括执行时间、处理条数、失败条数和失败原因。插入操作一定要分批执行,不要在一个事务里锁死太多数据。
9.5 备份与恢复
Supabase 提供数据库备份能力,但本地自建项目要额外做好备份计划。内容数据是 CMS 的核心资产,建议每天备份一次数据库,定期把 Supabase Storage 中的图片同步到其他存储位置。上线前在测试环境演练一次恢复流程,不要等到数据丢了才临时想办法。
9.6 SEO 和页面优化
CMS 全栈项目可以充分利用 Next.js 的 SEO 能力:
- 每个内容页设置独立的
title、description、canonical。 - 生成带
og:前缀的 Open Graph 标签。 - 使用 Next.js 的
generateStaticParams在构建时生成静态内容页。 - 为列表页和搜索页添加分页链接。
- 为图片设置 alt 文本和响应式尺寸。
如果站点是国际化的,要尽早考虑多语言 URL 结构,不要在内容量大了以后再做迁移。
10. 总结与下一步
NextBlock CMS 最值得尝试的地方,不是“又一个 CMS”,而是把 Next.js 16 和 Supabase 的组合真正用起来。如果你之前只在 demo 里用 Supabase 做过登录和数据库读写,这个项目可以让你看到一条完整的内容产品路径:怎么规划数据库表、怎么暴露接口、怎么做后台认证、怎么把内容渲染到前台。
拿到项目后,建议按以下顺序验证:
- 先把项目跑起来,确认本地能访问。
- 创建一篇测试文章,走一遍后台写入、数据库落盘、前台展示的全流程。
- 打开 Supabase Dashboard,确认数据表和 Storage 文件是否正确。
- 测试登录和权限控制,看未登录用户是否被拦住。
- 检查接口和批量导入脚本,准备内容迁移方案。
最容易踩的坑是环境变量和 RLS 权限。遇到页面 500 或者读不到内容,优先检查这两个地方。数据库迁移没跑完、环境变量没填对、RLS 策略限制过严,都是新手最容易忽略的问题。
后续可以扩展的方向很多。你可以给它加 Markdown 编辑器、添加评论区、接入全文搜索、设计多语言内容模型,或者把内容发布流程改成 Webhook 触发的自动构建。基于 Next.js + Supabase 这套组合,上层能力完全可以按业务需求继续生长。如果你正在选型,建议把这份代码当作全栈参考,而不是固定依赖。真正决定 CMS 是否好用的,还是内容模型、权限设计和你自己的业务逻辑。