mcpField
F
frontic-implementation

frontic-implementation

github.com/frontic开发053 次安装35 周前更新
代码仓库

关于 frontic-implementation

frontic-implementation 是用于创建和管理 Frontic 区块、列表与页面的技能。它强调先检查数据结构并复用兼容资源,同时指导客户端生成、查询、路由和字段配置。

主要功能

  1. 01使用前检查资源数据结构
  2. 02判断复用、扩展或新建
  3. 03指导区块与列表配置
  4. 04说明页面和查询的客户端用法
  5. 05涵盖筛选、排序和字段验证
  6. 06变更后要求重新生成客户端

适用场景

  1. 01构建 Frontic 商品列表
  2. 02将动态路由连接到页面数据
  3. 03添加筛选、排序或分页
  4. 04排查字段错误或生成代码过期

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/frontic/skills --skill frontic-implementation

安装后在 Claude Code 中输入/frontic-implementation确认已加载。

详细介绍

Frontic 实现与配置

根据用户请求自主创建或管理区块、列表和页面时,请使用此技能。始终优先使用 Frontic 数据源,而非模拟数据。

开始之前

使用 fetch_api_call 工具检查任何区块、列表或页面的数据结构,然后再使用它。这样可以避免向用户展示不存在的内容或难以辨认的 ID。


1. 资源决策

创建新区块或列表之前,请分析当前的 Frontic 配置:

  • 现有区块:可复用或扩展的区块
  • 现有列表:符合用户需求的列表——请验证参数兼容性和数据结构
  • 可用存储:包含相关数据的存储
复用、扩展还是创建
场景操作
完全匹配(相同的用户流程和参数)复用
接近但不完全匹配扩展(如适用)或创建新的
参数或意图不同创建新的
规则(必须遵守)
  • 绝不强行套用:不要将区块或列表用于其设计目标之外的场景,即使是作为权宜之计也不行。
  • 参数兼容性是绝对要求:如果某个列表需要参数(例如 categoryId),而用户的使用场景未提供该参数(例如全局搜索),请创建新列表——绝不能使用虚构或占位参数值。
  • 用户意图优先:准确匹配用户表达的意图和用户流程。
  • 说明你的判断依据:简要说明复用、扩展或创建资源的原因。

⚠️ **警告:**如果你发现自己正使用虚构或默认参数,让现有资源适用于不同的使用场景,请停止。改为创建新资源。


2. 创建区块和列表

创建区块
  • 分析数据结构:确定该区块代表的单条记录或实体
  • 定义完整架构:纳入所有相关的电商字段
  • 规划变体:考虑产品类型、类别等

常见区块: ProductDetail、CategoryDetail、UserProfile、OrderDetail、ReviewDetail、BrandDetail

创建列表
  • 确定集合类型:产品、类别、博客文章等
  • 确定嵌入的区块:列表必须引用项目中已创建的区块
  • 配置筛选条件:价格、类别、品牌、评分、可用性
  • 规划排序方式:价格、人气、最新、评分
  • 启用搜索:在相关情况下(描述、标题)
  • 将参数设为可选,以支持全局使用:如果列表既用于全局搜索,也用于限定范围的场景,请将参数设为可选,并配置默认值:
{
  "name": "categoryId",
  "dataType": "string",
  "required": false,
  "defaultValue": "root-id"
}

这样,全局搜索可以使用 listing("GlobalSearch", {}),限定范围的查询则可以使用 listing("GlobalSearch", { categoryId: "xyz" })。

常见列表: ProductListing、CategoryListing、OrderListing、ReviewListing、SearchResults

重新生成客户端

创建或更新区块或列表后,务必重新生成 Frontic Client:

npx @frontic/cli@latest generate

3. Frontic Client 用法

导入客户端(根据应用根目录解析 .frontic/ 路径):

import client from '../../.frontic/generated-client'
区块(按键获取单项)

单项始终通过键来标识。不要编造 'root-category' 之类的占位键,务必使用与该区块关联的存储中的实际键。

const data = await client.block(
  'CategoryDetail',
  'a3f4b5c6-d7e8-49ab-9c2d-3e4f5e6d7c8b'
)
const data = await client.block(
  'ProductDetail',
  '123e4567-e89b-12d3-a456-426614174000'
)
列表(支持筛选、排序和分页的集合)

筛选条件和排序选项请参阅 .frontic/query-types.ts 和 .frontic/fetch-api.d.ts。

const products = await client.listing('ProductList', {
  categoryId: 'e72b0f5e-1c3d-4a7e-913a-2e4c95cd8f31'
})

const results = await client.listing(
  'ProductList',
  { categoryId: '...' },
  {
    query: {
      filter: [
        {
          type: 'and',
          filter: [
            { type: 'equals', field: 'attributes.size', value: '10' },
            { type: 'range', field: 'price.amount', from: 10 }
          ]
        },
        { type: 'range', field: 'price.amount', from: 2000, to: 10000 },
        { type: 'equals', field: 'sale', value: true }
      ],
      sort: { field: 'price.amount', order: 'asc' },
      search: 'Red',
      page: 1,
      limit: 20
    }
  }
)
页面(按路由获取)
// The route path is the full path including the domain without the protocol
const pageData = await client.page('demo-shop.com/uk/women/shoes')
类型参考

请检查 .frontic/generated-types.d.ts 和 .frontic/query-types.ts,了解区块、列表、页面、参数和返回类型。


4. 页面集成与动态更新

使用页面实现动态路由

除非用户另有要求,否则始终使用页面实现动态路由。页面是由 slug 标识的区块容器。页面 slug 包含域名、区域设置(如果已配置)和路径。区块可以包含用于路由信息的 pageRoute 字段。

对于根级动态路由,创建一个 catch-all 页面,调用 client.page() 并传入拼接后的 slug。单独处理根路径 /(例如使用硬编码区块)。

页面结构层级
Page (e.g. CategoryDetail)
 ├── Block (e.g. CategoryDetailShopware)
 └── Nested Listing (e.g. ProductListShopware)
实现模式
  1. 初始加载:使用 client.page() 或 client.block()——它们会提供完整的页面上下文和嵌入内容。
  2. 筛选/排序/分页:使用 client.listing()——client.page() 和 client.block() 不接受查询参数。
// 1. Initial page load
const pageData = await client.page('domain.com/category-name')

// 2. Dynamic updates — extract params, call embedded listing directly
const categoryId = pageData.data.key
const filteredData = await client.listing('ProductListShopware', { categoryId }, {
  query: { filter: [...], sort: {...}, page: 2 }
})

总结: 初始加载始终从 client.page() 开始。对于动态更新,找到嵌套的 listing,从页面数据中提取所需参数,然后使用查询参数调用 client.listing()。仅更新组件状态中的 listing 部分。


5. 字段配置

使用路径命名筛选字段

当筛选字段配置了 path 参数时,查询中必须使用完整的点分路径:

// Configuration:
{ "name": "price", "source": "blockField", "path": "amount" }

// In queries — use "price.amount", NOT "price":
{ "type": "range", "field": "price.amount", "from": 2000, "to": 10000 }

规则: 如果筛选字段有 path: "X",查询中始终将其引用为 fieldName.X。

排序字段配置

Frontic 不支持名称相同但方向不同的重复排序字段。每个排序字段只添加一次——API 会自动同时支持 asc 和 desc。在查询时指定方向:

// One sort field configured, direction chosen per query:
sort: { field: 'price.amount', order: 'asc' }  // or 'desc'
字段来源选择

配置搜索、筛选和排序字段时,始终优先选择 blockField,而非 storageField:

  • 区块字段已公开且已配置
  • 存储字段可能无法访问或类型不正确
  • 区块字段可保持与嵌套区块结构的一致性
// Prefer:
{ type: "filter", name: "price", source: "blockField" }

// Avoid:
{ type: "filter", name: "price", source: "storageField" }
验证字段路径

使用筛选或排序字段之前,请验证准确的名称:

  1. 使用 list_resources 查看已配置的字段
  2. 使用 fetch_api_call 测试 listing 并检查响应结构
// Test listing response reveals field structure:
// items: [{ price: { amount: 49595 } }]
// → filter field is "price.amount"

6. 价格格式

Frontic 价格采用带精度的整数格式:

{ "amount": 49595, "currency": "EUR", "precision": 2, "ref": 0 }

显示计算:

const displayPrice = price.amount / Math.pow(10, price.precision)
// 49595 / 100 = 495.95

7. 故障排除

浏览器与构建缓存

重新生成客户端后,缓存可能导致旧代码继续生效。

  • 清除框架构建缓存(例如 .next/、.nuxt/、dist/)
  • 强制刷新浏览器: Cmd+Shift+R(Mac)/Ctrl+Shift+F5(Windows/Linux)
  • 在 DevTools 中停用缓存: Network 选项卡 → “Disable cache”

评论

支持 Markdown