我多年来一直在用无头CMS平台构建网站。Contentful、Sanity、Strapi——你能想到的我都集成过。但在2025年末的某个时候,我开始注意到一个模式:对于越来越多的项目,我根本不去找CMS。相反,我用Vercel上的Next.js、Supabase处理数据和身份认证,以及Claude API处理任何我需要的内容智能,来构建完整的全栈应用。没有CMS供应商。没有内容建模UI。没有月度席位许可费。

这不是关于标新立异。绝对有一些项目是选择无头CMS的正确决定——我们在Social Animal就构建了不少这样的项目(看看我们的无头CMS开发工作)。但有一类特定的应用,这个无供应商栈不仅可行,而且更优。让我带你详细了解它的工作原理、何时使用它,以及如何从零开始设置。

目录

为什么开发者放弃了CMS

坦率地说,CMS能给你什么:一个供非技术人员编辑内容的UI、一个结构化的数据层、也许还有一些媒体管理功能,以及一个API来获取所有这些。当你有一个营销团队每天发布博文时,这是真正有价值的。

但这是我在2026年一直看到的:

  • SaaS产品,其中"内容"是用户生成的数据,而不是编辑文案
  • 内部工具,其中团队足够技术化,可以直接编辑数据库或使用轻量级管理面板
  • AI原生应用,其中内容是实时生成、汇总或转换的
  • 创业公司,无法为CMS辩护$300-500/月的开支,当他们只有三个用户时

对于这些项目,CMS是开销。你为不会使用的内容建模功能付费,为基本上是一个花哨的数据库包装器的服务管理API密钥,并处理webhook复杂性以保持同步。

替代方案?完全拥有你的数据层。Supabase给你Postgres(一个真实的数据库,不是专有的内容存储)、身份认证、文件存储和实时订阅。Claude处理智能层。Next.js和Vercel处理其他一切。

栈速览

技术 角色 2026定价(起始)
前端和API Next.js 15 (App Router) UI、服务器组件、路由处理器 免费(开源)
托管和边缘 Vercel 部署、CDN、无服务器函数 免费层 / $20/月Pro
数据库和身份认证 Supabase Postgres、行级安全、身份认证、存储 免费层 / $25/月Pro
AI层 Claude API (Anthropic) 内容生成、汇总、分类 按令牌付费(约$3/$15/每100万令牌用于Sonnet 4)
管理UI 自定义(React + Supabase) 为你的团队进行内容管理 $0(你构建它)

中等流量的生产应用的总成本:$45-100/月。相比之下,典型的无头CMS设置中,仅CMS就可能花费$99-500/月,还没考虑托管成本。

在Vercel上设置你的Next.js项目

我假设你有Node.js 20+和一个Vercel账户。如果你对Next.js是新手,我们的团队在Next.js开发能力页面上有大量文章。

npx create-next-app@latest my-app --typescript --tailwind --app --src-dir
cd my-app

具有App Router的Next.js 15是这里的基础。我们默认使用服务器组件,这意味着我们的大部分数据获取都在服务器上进行——没有暴露的API密钥,没有初始内容的客户端加载旋转器。

这是我为这个栈提供的典型项目结构:

src/
├── app/
│   ├── (public)/           # 营销页面、博客
│   ├── (dashboard)/        # 经过身份认证的管理区域
│   │   ├── layout.tsx      # 身份认证检查包装器
│   │   ├── posts/
│   │   ├── media/
│   │   └── settings/
│   ├── api/
│   │   ├── ai/             # Claude API路由
│   │   └── webhooks/       # Supabase实时挂钩
│   └── layout.tsx
├── lib/
│   ├── supabase/
│   │   ├── client.ts       # 浏览器客户端
│   │   ├── server.ts       # 服务器客户端
│   │   └── admin.ts        # 服务角色客户端
│   ├── claude.ts           # Anthropic SDK包装器
│   └── utils.ts
├── components/
└── types/

环境变量

你需要在你的.env.local中有这些:

NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-key
ANTHROPIC_API_KEY=sk-ant-...

部署到Vercel

推送到GitHub。在Vercel中连接仓库。添加你的环境变量。完成。我不打算再赘述这个——Vercel为Next.js部署提供的开发体验是业界最好的,你可能已经知道它是如何工作的。

值得注意的一点:如果你需要在不重新部署的情况下更新的功能标志或配置,请使用Vercel的Edge Config。这是一个小细节,但它替代了另一个SaaS工具。

Supabase作为你的后端:身份认证、数据库和存储

这是魔法发生的地方。Supabase不仅仅是"Firebase但用Postgres"——它是一个你实际拥有的完整后端平台。你的数据存储在标准PostgreSQL数据库中。如果你曾想离开,你可以pg_dump然后走开。试试用专有CMS做这个。

数据库模式

假设你正在构建一个内容驱动的应用(这是你通常会选择CMS的应用类型)。这是一个处理文章、媒体和基本分类的模式:

-- 启用UUID生成
create extension if not exists "uuid-ossp";

-- 内容表(替换你的CMS内容模型)
create table public.posts (
  id uuid default uuid_generate_v4() primary key,
  title text not null,
  slug text unique not null,
  body text, -- Markdown内容
  excerpt text,
  status text default 'draft' check (status in ('draft', 'published', 'archived')),
  author_id uuid references auth.users(id),
  featured_image text, -- Supabase存储路径
  metadata jsonb default '{}', -- 灵活的字段,无需迁移
  published_at timestamptz,
  created_at timestamptz default now(),
  updated_at timestamptz default now()
);

-- 标签/分类
create table public.tags (
  id uuid default uuid_generate_v4() primary key,
  name text unique not null,
  slug text unique not null
);

create table public.post_tags (
  post_id uuid references public.posts(id) on delete cascade,
  tag_id uuid references public.tags(id) on delete cascade,
  primary key (post_id, tag_id)
);

-- 行级安全
alter table public.posts enable row level security;

-- 任何人都可以读取已发布的文章
create policy "Public can read published posts"
  on public.posts for select
  using (status = 'published');

-- 经过身份认证的用户可以管理自己的文章
create policy "Authors can manage own posts"
  on public.posts for all
  using (auth.uid() = author_id);

那个metadata jsonb列很关键。它给你CMS的自定义字段的灵活性,而不需要在营销团队想要新字段时运行迁移。需要SEO描述?metadata->>'seo_description'。需要Open Graph图像覆盖?metadata->>'og_image'。它在你需要灵活性的地方是无模式的,在你需要完整性的地方是结构化的。

身份认证设置

Supabase身份认证处理一切。电子邮件/密码、魔法链接、与Google/GitHub的OAuth——全都内置。

// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            cookieStore.set(name, value, options)
          )
        },
      },
    }
  )
}

文件存储

Supabase存储替代了你的CMS拥有的任何媒体库。创建一个叫media的bucket,设置一个策略,你就有了一个S3兼容的文件存储,具有自动CDN URL。

// 上传文件
const { data, error } = await supabase.storage
  .from('media')
  .upload(`posts/${slug}/${file.name}`, file, {
    cacheControl: '3600',
    upsert: false,
  })

// 获取公开URL
const { data: { publicUrl } } = supabase.storage
  .from('media')
  .getPublicUrl(`posts/${slug}/${file.name}`)

集成Claude API实现内容智能

这是2026栈与传统网页开发最大的差异所在。Claude API不仅仅是一个聊天机器人——它是一个智能层,可以替代整个CMS插件和第三方服务类别。

这是我在生产中使用它的内容:

  • 从文章内容自动生成SEO元数据
  • 内容汇总用于摘录和社交卡片
  • 内容分类和自动标记
  • 智能搜索理解意图,而不仅仅是关键词
  • 草稿协助用于内容作者

设置Anthropic SDK

npm install @anthropic-ai/sdk
// lib/claude.ts
import Anthropic from '@anthropic-ai/sdk'

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY!,
})

export async function generateSEOMetadata(content: string, title: string) {
  const message = await anthropic.messages.create({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 1024,
    messages: [
      {
        role: 'user',
        content: `给定这篇文章的标题和内容,生成SEO元数据。

标题:${title}
内容:${content.slice(0, 3000)}

仅用JSON响应:
{
  "seo_title": "50-60个字符的标题,包含主要关键词",
  "seo_description": "120-160个字符的元描述",
  "excerpt": "社交分享的1-2句钩子",
  "suggested_tags": ["tag1", "tag2", "tag3"]
}`,
      },
    ],
  })

  const text = message.content[0].type === 'text' ? message.content[0].text : ''
  return JSON.parse(text)
}

export async function classifyContent(content: string, existingTags: string[]) {
  const message = await anthropic.messages.create({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 256,
    messages: [
      {
        role: 'user',
        content: `将此内容分类到现有列表中最相关的标签。如果没有匹配项,你可以建议最多2个新标签。

现有标签:${existingTags.join(', ')}

内容:${content.slice(0, 2000)}

用JSON响应:{ "tags": ["tag1", "tag2"], "new_tags": ["maybe-new"] }`,
      },
    ],
  })

  const text = message.content[0].type === 'text' ? message.content[0].text : ''
  return JSON.parse(text)
}

AI功能的API路由

// app/api/ai/seo/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { createClient } from '@/lib/supabase/server'
import { generateSEOMetadata } from '@/lib/claude'

export async function POST(request: NextRequest) {
  const supabase = await createClient()
  const { data: { user } } = await supabase.auth.getUser()

  if (!user) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }

  const { content, title } = await request.json()
  
  try {
    const metadata = await generateSEOMetadata(content, title)
    return NextResponse.json(metadata)
  } catch (error) {
    return NextResponse.json(
      { error: 'AI generation failed' },
      { status: 500 }
    )
  }
}

这里的成本可以忽略不计。典型的SEO元数据生成调用使用大约4000个输入令牌和200个输出令牌。使用Claude Sonnet 4的定价,约为$3/100万输入令牌和$15/100万输出令牌,这是每次调用约$0.015。你可以为1000篇文章生成元数据,花费$15。

构建自定义管理界面

这是让人们感到紧张的部分。"如果我没有CMS,非技术人员怎样编辑内容?"

你构建一个简单的管理UI。在2026年,"简单"实际上就是简单。这是一个基本的文章编辑器组件:

// app/(dashboard)/posts/[id]/editor.tsx
'use client'

import { useState } from 'react'
import { createBrowserClient } from '@supabase/ssr'

export function PostEditor({ post }: { post: Post }) {
  const [title, setTitle] = useState(post.title)
  const [body, setBody] = useState(post.body || '')
  const [saving, setSaving] = useState(false)
  
  const supabase = createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )

  async function save() {
    setSaving(true)
    const { error } = await supabase
      .from('posts')
      .update({
        title,
        body,
        updated_at: new Date().toISOString(),
      })
      .eq('id', post.id)

    setSaving(false)
    if (error) alert('Save failed: ' + error.message)
  }

  async function generateSEO() {
    const res = await fetch('/api/ai/seo', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ title, content: body }),
    })
    const metadata = await res.json()
    // 将生成的元数据应用于文章
    await supabase
      .from('posts')
      .update({ metadata, excerpt: metadata.excerpt })
      .eq('id', post.id)
  }

  return (
    <div className="max-w-4xl mx-auto p-6">
      <input
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        className="text-3xl font-bold w-full mb-4 border-b pb-2"
      />
      <textarea
        value={body}
        onChange={(e) => setBody(e.target.value)}
        className="w-full h-96 font-mono text-sm p-4 border rounded"
      />
      <div className="flex gap-4 mt-4">
        <button onClick={save} disabled={saving}
          className="px-4 py-2 bg-blue-600 text-white rounded">
          {saving ? 'Saving...' : 'Save Draft'}
        </button>
        <button onClick={generateSEO}
          className="px-4 py-2 bg-purple-600 text-white rounded">
          ✨ Generate SEO Metadata
        </button>
      </div>
    </div>
  )
}

是的,这是一个简单的textarea。在一个真实的项目中,你会交换进入Tiptap、MDXEditor或BlockNote之类的东西进行丰富的编辑。重点是:管理界面是你的代码。你控制每个像素、每个工作流、每个权限。没有与CMS UI限制的冲突。

对于更复杂的项目,考虑Refine或AdminJS作为直接插入Supabase的管理面板框架。它们将为你节省数周的时间。

真实成本:这个栈实际花费多少

对于一个每月有100K页面浏览量的内容丰富的网站,让我们用具体的数字:

服务 月度成本 你得到什么
Vercel Pro $20 1TB带宽、1000 GB-小时无服务器
Supabase Pro $25 8GB数据库、250GB带宽、100K认证用户
Claude API 按使用付费 ~$10-30 ~500万令牌/月(SEO生成、汇总、搜索)
域名 年度 ~$1 .com域名
总计 $56-76/月

现在将此与典型的无头CMS栈进行比较:

服务 月度成本
Contentful 团队 $300
Vercel Pro $20
Algolia(搜索) 构建 $50
Auth0(身份认证) 必需品 $35
总计 $405/月

这是5-6倍的成本差异。而Supabase栈给你更多的灵活性,而不是更少。

何时你应该仍然使用CMS

我想对此有清醒的认识。不要为每个项目抛弃你的CMS。无头CMS在以下情况下仍然是更好的选择:

  • 大型编辑团队需要结构化的工作流(批准链、计划、超越基本RBAC的角色)
  • 内容是产品——发布商、媒体公司、有数百个贡献者的文档网站
  • 你需要可视化编辑——一些CMS平台提供实时预览和可视化构建器,复制需要几个月
  • 多渠道交付——如果同一内容涉及网站、移动应用、数字标牌和电子邮件,CMS的结构化内容模型会有所回报
  • 大规模本地化——CMS平台如Contentful和Sanity有成熟的i18n工作流

我们在Social Animal仍然构建了大量的无头CMS项目。如果这是你的项目需要的,联系我们。但对于越来越多的应用,其中它不是你需要的,停止为它付费。

生产部署检查清单

在你将这个栈发送到生产之前,请检查这个列表:

  • 行级安全策略为每个表测试(Supabase的策略模拟器有帮助)
  • 速率限制在Claude API路由上(使用Vercel的@vercel/edge速率限制器或upstash/ratelimit)
  • 输入验证在所有API路由上(Zod是你的朋友)
  • 错误边界在你的React树中应对AI失败(Claude有时会超时)
  • 缓存策略——在Next.js中对于数据库支持的页面使用unstable_cacherevalidateTag
  • 监控——Vercel分析用于性能、Supabase仪表板用于数据库指标、Anthropic控制台用于API使用
  • 备份策略——Supabase Pro包括每日备份,但还要设置逻辑复制或pg_dumpcron以防万一
  • 内容安全策略标头在next.config.js中配置
  • 图像优化——使用Next.js<Image>组件和Supabase存储URL

常见问题

Supabase真的能替代无头CMS吗? 对于许多用例,是的。Supabase给你一个PostgreSQL数据库,从你的模式自动生成REST和GraphQL API、文件存储、身份认证和实时订阅。它没有给你的是开箱即用的精美内容编辑UI——你需要自己构建或使用像Refine这样的工具。如果你的团队是技术性的或很小,这个权衡绝对值得。

Claude API对于典型网站的成本是多少? 对于一个使用Claude进行SEO元数据生成、内容汇总和基本分类的内容网站,预计花费$10-30/月,使用量适中(几百个AI操作)。2026年的Claude Sonnet 4定价约为$3/100万输入令牌和$15/100万输出令牌。单个SEO元数据生成调用的成本约为$0.01-0.02。

这个栈适合企业应用吗? 这取决于你对企业的定义。Vercel和Supabase都提供企业层,具有SLA、SOC 2合规性和专业支持。栈处理高流量很好——Vercel上的Next.js自动扩展,Supabase Pro支持连接池和读副本。对于合规性繁重的行业,你会想要Supabase的自托管选项,将数据保留在你自己的基础设施中。

关于内容预览和草稿工作流怎样? 你构建它们。Next.js Draft Mode结合posts表中的status列为你提供了草稿/已发布工作流。对于预览,创建一个经过身份认证的路由,不管状态如何获取文章。这大约是50行代码,相比在CMS仪表板中配置预览URL。

没有CMS,你如何处理富文本编辑? 使用现代富文本编辑器库。Tiptap(建立在ProseMirror上)是2026年最受欢迎的选择——它支持协作编辑、自定义块、斜杠命令和Markdown快捷方式。BlockNote是另一个具有Notion风格UI的坚实选择。将输出存储为HTML、Markdown或JSON在你的Supabasebody列中。

我能从无头CMS迁移到这个栈吗? 绝对可以。大多数无头CMS平台有导出API。编写一个迁移脚本,从你的CMS API提取内容并将其插入Supabase表中。我们已经为几个客户进行了这个迁移,从Contentful和Sanity迁移到Supabase支持的设置。最难的部分通常是将CMS的专有富文本格式映射到标准HTML或Markdown。

如果Supabase宕机怎样? Supabase在2025-2026年有稳固的正常运行时间,但没有服务是完美的。因为你的数据存储在标准PostgreSQL中,你有选项:设置读副本、在S3中保留自动备份,甚至运行一个待命实例。如果你使用Supabase的自托管层,你完全控制基础设施。这实际上比依赖CMS供应商更具有弹性——如果Contentful宕机,你不能只"切换到另一个Contentful"。

我应该为博客或营销网站使用这个栈吗? 对于开发者的个人博客或初创公司的营销网站,这个栈是完美的。你获得完全控制、最小的成本和AI驱动的功能,在CMS中需要昂贵的插件。对于有大型营销团队每周发布20多篇文章的复杂批准工作流,你可能想要一个适当的CMS。这是关于将工具与团队相匹配。如果你不确定哪种方法适合你的项目,看看我们的定价页面联系我们进行快速咨询。