用Astro Content Collections管理产品/应用/博客内容,frontmatter字段直接对应注册表的pkw/skw/nkw。Pillar页用静态路由,Cluster页用动态路由[slug].astro。每个页面模板中,h1使用pkw,meta title/description从frontmatter生成,结构化数据通过SEOHead组件注入。
Pillar 与产品页开发:基于注册表意图的页面结构实现
前两篇解决了“用什么工具建”和“怎么和 AI 协作”的问题。这篇解决“如何把注册表数据转化为真实页面”——让代码结构和 SEO 策略完全对齐。
内容数据架构:Content Collections
Astro 的 Content Collections 是管理结构化内容的最佳方式。它允许在 Markdown/MDX frontmatter 里定义字段,Astro 会自动进行类型检查。
配置 src/content.config.ts
import { defineCollection, z } from 'astro:content';
// 产品(Pillar + SKU Cluster)
const products = defineCollection({
type: 'content',
schema: z.object({
title: z.string(), // 页面显示标题
pkw: z.string(), // 注册表主词(用于 H1 和 Title)
skw: z.array(z.string()), // 次级词列表
nkw: z.array(z.string()), // 负面词(用于 AI 写作检查)
pageType: z.enum(['pillar', 'cluster-sku']),
description: z.string(), // Meta description
category: z.string(), // 对应哪个 Pillar(SKU 用)
specs: z.record(z.string()).optional(), // 参数规格
certifications: z.array(z.string()).optional(),
priority: z.number().min(1).max(5),
targetLocale: z.array(z.string()),
publishedAt: z.coerce.date(),
}),
});
// 应用场景(Application Cluster)
const applications = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pkw: z.string(),
skw: z.array(z.string()),
description: z.string(),
relatedProducts: z.array(z.string()), // 关联的 SKU slug 列表
industry: z.string(),
publishedAt: z.coerce.date(),
}),
});
// 博客(Resource Cluster)
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pkw: z.string(),
description: z.string(),
relatedApplications: z.array(z.string()).optional(),
publishedAt: z.coerce.date(),
}),
});
export const collections = { products, applications, blog };
Pillar 页实现
文件位置
src/pages/products/[category].astro
代码结构
---
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import SEOHead from '../../components/seo/SEOHead.astro';
import ProductCard from '../../components/ui/ProductCard.astro';
// 静态路径生成(每个品类一个页面)
export async function getStaticPaths() {
const categories = ['centrifugal-pumps', 'submersible-pumps', 'gear-pumps'];
return categories.map(cat => ({ params: { category: cat } }));
}
const { category } = Astro.params;
// 获取该品类的 Pillar 页数据
const pillarEntries = await getCollection('products',
entry => entry.data.pageType === 'pillar'
&& entry.data.category === category
);
const pillar = pillarEntries[0];
// 获取该品类的所有 SKU
const skuEntries = await getCollection('products',
entry => entry.data.pageType === 'cluster-sku'
&& entry.data.category === category
);
// Schema JSON-LD
const orgSchema = {
"@context": "https://schema.org",
"@type": "Organization",
"name": "AquaFlow Industrial",
"description": pillar.data.pkw + " manufacturer",
"url": Astro.site?.toString(),
};
---
<BaseLayout>
<SEOHead
slot="head"
title={`${pillar.data.pkw} | AquaFlow Industrial`}
description={pillar.data.description}
canonicalUrl={Astro.url.href}
schema={orgSchema}
/>
<!-- Hero 区:H1 必须包含 PKW -->
<section class="bg-navy-900 text-white py-20">
<div class="container mx-auto px-6">
<!-- ⚠️ H1 使用 PKW,不要随意修改 -->
<h1 class="text-4xl font-bold mb-4">{pillar.data.pkw}</h1>
<p class="text-xl text-gray-300 mb-8">{pillar.data.description}</p>
<a href="#quote" class="btn-primary">Request a Free Quote</a>
<a href="/catalog.pdf" class="btn-secondary ml-4">Download Catalog</a>
</div>
</section>
<!-- SKU 卡片矩阵(内链到各 SKU 页) -->
<section class="py-16">
<div class="container mx-auto px-6">
<h2 class="text-2xl font-semibold mb-8">Our Product Range</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
{skuEntries.map(sku => (
<!-- 锚文本使用型号名,不用"view details" -->
<a href={`/products/${category}/${sku.slug}`}>
<ProductCard product={sku.data} />
</a>
))}
</div>
</div>
</section>
<!-- 底部询盘 CTA -->
<section id="quote" class="bg-gray-50 py-16">
<InquiryForm category={category} />
</section>
</BaseLayout>
SKU Cluster 页实现
关键:参数表用语义化 HTML
<!-- 参数规格表:必须用原生 <table>,不用 Markdown 表格 -->
{entry.data.specs && (
<table class="w-full border-collapse">
<caption class="text-left font-semibold mb-2">
{entry.data.pkw} Technical Specifications
</caption>
<thead>
<tr class="bg-gray-100">
<th scope="col" class="p-3 text-left">Parameter</th>
<th scope="col" class="p-3 text-left">Value</th>
</tr>
</thead>
<tbody>
{Object.entries(entry.data.specs).map(([key, value]) => (
<tr class="border-b">
<td class="p-3 font-medium">{key}</td>
<td class="p-3">{value}</td>
</tr>
))}
</tbody>
</table>
)}
面包屑(自动内链到 Pillar)
<!-- 面包屑:自动生成,锚文本用品类名 -->
<nav aria-label="Breadcrumb">
<ol class="flex gap-2 text-sm text-gray-500">
<li><a href="/">Home</a></li>
<li>›</li>
<!-- 这条内链的锚文本用品类名(Pillar 的 PKW 含义) -->
<li><a href={`/products/${entry.data.category}`}
class="text-blue-600 hover:underline">
{categoryName}
</a></li>
<li>›</li>
<li aria-current="page">{entry.data.title}</li>
</ol>
</nav>
注册表字段到 HTML 的完整映射
| 注册表字段 | HTML 位置 | 规范 |
|---|---|---|
pkw |
<h1> + <title> + og:title |
H1 必须包含,不可省略 |
skw[0] |
第一个 <h2> |
尽量自然包含 |
skw[1–n] |
其他 <h2> 或正文 |
自然出现,不堆砌 |
description |
<meta name="description"> + og:description |
精确复制,不要重写 |
page_slug |
URL path | 已确定,不可修改 |
targetLocale |
<html lang=""> + hreflang |
多语言配置 |
动态内容驱动的 pSEO 预配置
Application Cluster 页用动态路由,配合 YAML 数据文件可以轻松扩展到几十个场景:
// src/pages/applications/[slug].astro
export async function getStaticPaths() {
const apps = await getCollection('applications');
return apps.map(entry => ({
params: { slug: entry.slug },
props: { entry },
}));
}
只要在 src/content/applications/ 下新增一个 Markdown 文件,Astro 就会自动生成对应页面——这就是 pSEO 批量生成的基础架构。
→ AI 写外贸英文内容:产品描述 / About Us / 首页文案
RELATED / 相关推荐
接着读这些
按同一分类、系列与标签为你挑选。
从供应商资料到网站产品页:这条链上的顺序为什么不能换
从供应商发来一份 PDF 到产品页上线,中间有五个环节,顺序不能换。跳过关键词登记这一步,新页面会和自己站上已有页面抢同一个词;把核对挪到最后,审核必然退化成走过场。这篇逐段讲清每个"为什么必须是这个顺序"。
数据库设计:品类 × 场景的组合矩阵构建
pSEO 的核心是数据,数据结构决定了能批量生成什么样的页面。这篇讲如何设计品类和场景两个维度的 YAML 数据文件——包含哪些字段、如何处理"有些组合无意义"的问题,以及如何用 AI 辅助填写场景数据里的技术细节。
双骨架:把词的地图和问的地图叠在同一张 slug 上
两张表用 page_slug 一叠,每个页面就得到一张意图卡——它排哪些词、主答哪些问、复述哪些问、明确不答哪些问。叠加还会立刻暴露两类问题页:有排名但不回答任何具体问题的页,和零搜索量却被 AI 反复引用的页。这篇给出四象限诊断、意图卡模板和存量站的迁移路径。