SuperAPI AI 工具集

enable-shopify-cms

前端与建站

查看项目

更新于 10-16 06:10

技能介绍

用途

enable-shopify-cms 用于给 shop 模板添加基于 Shopify metaobject 的 CMS 支持。它把原本硬编码的首页内容替换为 Shopify 托管的内容,使用 cms_homepage 和 cms_page 两种 metaobject 定义来驱动首页与营销页。

前提条件

  • Shopify 店铺中已定义 cms_homepage 和 cms_page 的 metaobject 定义
  • 已配置 Storefront API 访问令牌

内容模型

cms_homepage 字段

  • title(single_line_text):页面标题
  • meta_title(single_line_text):SEO 标题覆盖
  • meta_description(single_line_text):SEO 描述覆盖
  • hero_headline(single_line_text):Hero 横幅主标题
  • hero_subheadline(single_line_text):Hero 横幅副标题
  • hero_image(file):Hero 背景图
  • hero_cta_text(single_line_text):Hero 行动号召标签
  • hero_cta_link(single_line_text):Hero 行动号召 URL
  • sections(json):内容区块定义数组

cms_page 字段

  • slug(single_line_text):URL slug
  • title(single_line_text):页面标题
  • locale(single_line_text):语言代码(如 en-US)
  • meta_title(single_line_text):SEO 标题覆盖
  • meta_description(single_line_text):SEO 描述覆盖
  • hero_headline(single_line_text):Hero 横幅主标题
  • hero_subheadline(single_line_text):Hero 横幅副标题
  • hero_image(file):Hero 背景图
  • hero_cta_text(single_line_text):Hero 行动号召标签
  • hero_cta_link(single_line_text):Hero 行动号召 URL
  • sections(json):内容区块定义数组

实现步骤

1. 创建 lib/shopify/operations/cms.ts

实现三个返回 lib/types.ts 领域类型的操作:

import { defaultLocale } from "@/lib/i18n";
import { assertStorefrontOk } from "@/lib/shopify/errors";
import { storefront } from "@/lib/shopify/storefront";
import type { Homepage, MarketingPage } from "@/lib/types";

export async function getHomepage({
  locale = defaultLocale,
}: {
  locale?: string;
} = {}): Promise<Homepage | null> {
  "use cache";
  cacheLife("max");
  cacheTag("cms:all", "cms:homepage");
  // Query cms_homepage metaobject, transform to Homepage type
}

export async function getMarketingPage({
  slug,
  locale = defaultLocale,
}: {
  slug: string;
  locale?: string;
}): Promise<MarketingPage | null> {
  "use cache";
  cacheLife("max");
  cacheTag("cms:all", "cms:pages", `cms:page:${slug}`);
  // Query cms_page metaobject by slug, transform to MarketingPage type
}

export async function getAllMarketingPageSlugs(): Promise<
  Array<{ slug: string; updatedAt: string }>
> {
  "use cache: remote";
  cacheLife("max");
  cacheTag("cms:all", "cms:pages");
  // Query all cms_page metaobjects, return slugs
}

2. 编写 GraphQL 查询

先使用 Shopify AI Toolkit 的 custom-data 技能,再用其 Storefront 技能校验最终的 Storefront GraphQL 文档。使用 metaobjects(type: "cms_homepage") 和 metaobjects(type: "cms_page") 查询,并配合 @inContext locale 指令。

3. 转换 metaobject 响应

创建 lib/shopify/transforms/cms.ts,把原始 metaobject 字段转换为领域类型:

  • 将 sections JSON 字段解析为 ContentSection[]
  • 使用 getProductsByIds 把 sections 中的商品引用解析为 ProductCard[]
  • 将 hero 字段映射为 HeroSection
  • 将图片引用映射为 MarketingImage

4. 接入路由

更新 app/page.tsx 使用 CMS 操作:

import { getHomepage } from "@/lib/shopify/operations/cms";
import { MarketingPageRenderer } from "@/components/cms/page-renderer";

export default async function HomePage() {
  const locale = await getLocale();
  const page = await getHomepage(locale);
  if (!page) return <FallbackHomepage />;
  return (
    <Container>
      <MarketingPageRenderer page={page} />
    </Container>
  );
}

更新 app/pages/[slug]/page.tsx 使用 getMarketingPage 和 getAllMarketingPageSlugs。若要在站点地图中索引 CMS 页面,需在 app/sitemap/[shard]/route.ts 中添加 cms-pages-{n} 分片类型,并在 app/sitemap.xml/route.ts 中包含它。

首页和营销页读取使用普通 "use cache",以便其稳定内容能一致地包含在预渲染外壳中。slug 枚举使用 "use cache: remote",因为站点地图和发现类读取可在请求时运行并共享结果。

5. 使用现有的缓存失效 webhook

将 metaobject 失效逻辑保留在 app/api/webhooks/shopify/route.ts 中,该文件已校验 Shopify 签名,并把 metaobjects/* 主题映射到 cms:all、cms:homepage、cms:pages 以及页面级标签。如果内容模型新增了其他 CMS metaobject 类型,请扩展该映射;不要创建第二个未校验的 CMS webhook 端点。

约束

  • 返回 lib/types.ts 中确切的领域类型:Homepage、MarketingPage、ContentSection。
  • 将商品引用解析为 ProductCard[],组件期望可直接渲染的商品数据。
  • 优雅处理语言回退:当请求的语言不可用时返回默认语言内容,绝不抛出异常。
  • 支持 MarketingPage 上的 alternates 字段,它用于驱动语言感知的 URL 切换。
  • 保持 CMS 缓存标签与 app/api/webhooks/shopify/route.ts 一致。