项目简介:
一个用于让用户去按照不同需求去找相应的AI工具去完成自己的任务。
一个用于管理后台的页面
- 技术栈:Next.js 15 + React 19 + TypeScript + Tailwind CSS
- UI 组件:Radix UI + 自定义 components/ui/*
- 认证方案:Supabase Auth,已接入 @supabase/ssr 和 @supabase/supabase-js
项目经历:
一、用户界面开发:

技术栈:
`Next.js 15`
` React 19`
`TypeScript`
`Tailwind CSS`
`Supabase`
这个项目我选择了 Next.js 15 作为前端框架,因为它天然支持 App Router、服务端组件和路由组织。数据库和认证我选了 Supabase,这样我不需要额外搭一个传统后端,也能快速完成用户登录、数据库查询、对象存储和权限控制。
文字版架构图:
用户 -> Next.js 页面 -> Supabase Auth / Database / Storage
– `app/` 负责页面和路由
– `components/` 负责 UI 组件
– `lib/` 负责通用逻辑和 Supabase client 封装
– `docs/` 负责数据库和存储设计文档
数据库设计思路:
– `tool_categories`
– `ai_tools`
– `tool_submissions`
可以这样概括:
– `tool_categories`
管首页分类
– `ai_tools`
管正式发布的工具
– `tool_submissions`
管用户投稿和审核过程
supabase RSL策略:
在权限设计上,我没有只依赖前端限制,而是把核心权限交给了 Supabase 的 RLS。比如已发布工具所有人都能看,但投稿记录只能用户本人查看,正式工具和分类的管理权限只开放给管理员。这种做法会让项目在扩展时更加安全和稳定。
二、管理员后台开发:

由于数据库采用supabase,相关sdk

首先,@supabase 创建一个admin.ts,使用@supabase/supabase-js,调用环境变量中SUPABASE_SERVICE_KEY初始化supabase,这是服务端私钥,以确保是service_role。
为什么要使用服务端私钥? 服务端私钥有最高权限,可以不受数据库中表的RLS策略的限制,这样能让我们的管理员更加方便的操作数据库,对其中的几张表进行增/删/改/查。我们只需要确保在操作前,校验这个用户是管理员用户就行了。
核心业务表:
– `ai_tools`:正式上线的 AI 工具数据
– `tool_categories`:工具分类
– `tool_submissions`:用户提交待审核的数据
现实问题:
– 管理员如何手动新增工具?
– 用户提交的工具如何审核?
– 审核通过后,怎么把提交数据同步到正式工具表?
– 非管理员如何禁止进入后台?
– 多个管理员之间如何管理权限?
项目开发规则
所有的文案都使用中文的,这是一个中文网站
所有的数据库请求逻辑,都需要新建api实现,不能直接通过supabase-sdk操作
api的所有请求,都使用utils/supabase/admin.ts进行操作,避免RLS策略
所有的api请求逻辑,都需要通过中间件校验用户是否是管理员。通过用户是否在 admin_users这张表中。如果该用户不是管理员,则接口报错。
1.核心目标:
1. 只有管理员可以进入后台
2. 管理员可以查看平台概览数据
3. 管理员可以新增、编辑、查看、删除 AI 工具
4. 管理员可以审核用户提交的数据
5. 审核通过后,自动写入 `ai_tools`
6. 管理员可以管理其他管理员权限
7. 管理员可以管理工具分类
换句话说,这套系统解决的是一个 AI 内容站点从“能展示”到“能运营”的问题。
2.技术栈:
这个项目主要使用了下面这些技术:
– `Next.js 15`
– `React 19`
– `TypeScript`
– `Supabase`
– `@supabase/supabase-js`
– `Tailwind CSS`
技术选型的思路也很直接:
– `Next.js` 负责后台页面、服务端渲染和 API Route
– `Supabase` 负责认证、数据库、Storage
– `TypeScript` 负责把后台的数据结构和接口约束住
– `Tailwind CSS` 负责快速搭页面和后台样式
3.权限认证:
权限系统是怎么做的
这一块是整个项目里我最重视的部分之一。
因为后台权限不能只靠前端隐藏按钮,必须在服务端真正拦住。
我采用的是三层校验:
1. 登录后校验是否为管理员
用户即使账号密码正确,如果不在 `admin_users` 表里,也不能进入后台。
2. 中间件保护后台路由
对 `/protected` 和 `/admin` 路由做拦截。
未登录或非管理员,直接跳回登录页。
3. 所有后台 API 再做一次管理员校验
也就是说,即使前端被绕过,后端接口依然会拒绝非管理员请求。
这个设计的意义很简单:
– 前端负责体验
– 服务端负责安全
4.为什么我没有在页面里直接查 Supabase?
这个项目里我专门约束了一件事:
> 页面不直接操作 Supabase,所有数据库读写都走 API。
这样做有几个好处:
– 权限逻辑集中在 API 层
– 更方便统一使用 `service_role`
– 页面更干净,职责更清晰
– 后期更容易接日志、限流、审计
同时,后台的数据库操作统一通过服务端私钥客户端来做,也就是 `service_role` 模式。
这可以绕开前台 RLS 场景里很多不必要的限制,但前提是一定要把管理员校验写严。
5.后台设计:
1. 概览页
概览页是管理员登录后的首页,负责提供全局状态和快捷入口。
目前展示了 4 个核心统计:
– AI 工具总数
– 分类总数
– 今日提交数
– 待审核数
同时在顶部导航里提供了几个独立模块入口:
– 概览
– 工具分类
– AI 工具管理
– 审核中心
– 用户管理
2. AI 工具管理
这是后台最核心的内容管理模块。
现在已经支持:
– 新增 AI 工具
– 查看工具详情
– 编辑工具
– 删除工具
在新增工具时,我还接了两个重要能力:
– Logo 上传到 Supabase Storage 的 `tool-logos`
– 封面图上传到 Supabase Storage 的 `tool-covers`
另外,`content` 字段支持 Markdown 编辑和预览,这样工具详情内容就不会只是一个普通文本框。
3. 审核中心
审核中心对接的是 `tool_submissions`。
它现在支持三个状态分类:
– 待审核
– 已通过
– 已驳回
管理员可以:
– 查看提交详情
– 点击通过
– 点击驳回
审核通过时,系统会做两件事:
1. 把当前提交的数据插入到 `ai_tools`
2. 把当前提交状态更新为 `approved`
同时还会写入:
– `approved_tool_id`
– `reviewed_at`
如果是驳回,则会把状态更新为 `rejected`,并记录审核备注。
4. 用户管理
用户管理页面用于控制“谁可以进入后台”。
这里的逻辑不是直接改 Supabase Auth,而是:
– 列出所有已注册用户
– 判断用户是否在 `admin_users`
– 支持设为管理员
– 支持取消管理员身份
我还额外加了一个保护:
– 不能删除最后一个管理员
这样可以避免后台彻底失控。
5. 工具分类管理
分类模块主要维护 `tool_categories`。
现在支持完整 CRUD:
– 新增分类
– 编辑分类
– 查看分类列表
– 删除分类
删除时我还加了安全校验:
– 如果分类已经被 `ai_tools` 或 `tool_submissions` 引用,就不允许删除
这样可以避免线上数据挂掉。
三.遇到的问题:
– `NEXT_PUBLIC_SUPABASE_URL` 没配置导致运行时报错
– 邮箱验证链接没回跳成功
– Next.js dev 模式下 `.next` chunk 缓存错乱
– 静态资源 404
– 图片 URL 渲染与图标展示兼容问题
– 页面需要从模拟数据切换到真实数据库数据






