用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/aksel26/hmkim-blog-keystatic --skill structured-data命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | structured-data |
| description | Schema.org 구조화된 데이터(JSON-LD) 구현 스킬. Article, FAQPage, BreadcrumbList, HowTo 등 다양한 스키마를 블로그에 적용합니다. |
| triggers | ["JSON-LD 추가해줘","구조화 데이터 추가","스키마 마크업","리치 결과 최적화"] |
Schema.org 기반 JSON-LD 구조화된 데이터를 구현하여 Google 리치 결과(Rich Results)에 노출되도록 최적화합니다.
// components/schema/BlogPostingSchema.tsx
interface BlogPostingSchemaProps {
title: string;
description: string;
slug: string;
category: string;
createdAt: string;
updatedAt?: string;
author: string;
thumbnailImage?: string;
keywords?: string[];
wordCount?: number;
}
export function BlogPostingSchema(props: BlogPostingSchemaProps) {
const schema = {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: props.title,
description: props.description,
image: props.thumbnailImage,
datePublished: props.createdAt,
dateModified: props.updatedAt || props.createdAt,
author: {
'@type': 'Person',
name: props.author,
url: 'https://yourdomain.com/me',
},
publisher: {
'@type': 'Organization',
name: 'HM Blog',
logo: {
'@type': 'ImageObject',
url: 'https://yourdomain.com/logo.png',
},
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': `https://yourdomain.com/${props.category}/${props.slug}`,
},
keywords: props.keywords?.join(', '),
wordCount: props.wordCount,
articleSection: props.category,
inLanguage: 'ko-KR',
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// components/schema/BreadcrumbSchema.tsx
interface Breadcrumb {
name: string;
url: string;
}
export function BreadcrumbSchema({ items }: { items: Breadcrumb[] }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
name: item.name,
item: item.url,
})),
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// 사용 예시
<BreadcrumbSchema
items={[
{ name: 'Home', url: 'https://yourdomain.com' },
{ name: 'Tech', url: 'https://yourdomain.com/tech' },
{ name: 'Next.js 가이드', url: },
]}
/>
// components/schema/FAQSchema.tsx
interface FAQ {
question: string;
answer: string;
}
export function FAQSchema({ faqs }: { faqs: FAQ[] }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faqs.map((faq) => ({
'@type': 'Question',
name: faq.question,
acceptedAnswer: {
'@type': 'Answer',
text: faq.answer,
},
})),
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// components/schema/HowToSchema.tsx
interface HowToStep {
name: string;
text: string;
image?: string;
}
interface HowToSchemaProps {
name: string;
description: string;
steps: HowToStep[];
totalTime?: string; // ISO 8601 duration (예: "PT30M")
}
export function HowToSchema(props: HowToSchemaProps) {
const schema = {
'@context': 'https://schema.org',
'@type': 'HowTo',
name: props.name,
description: props.description,
totalTime: props.totalTime,
step: props.steps.map((step, index) => ({
'@type': 'HowToStep',
position: index + 1,
name: step.name,
text: step.text,
image: step.image,
})),
};
(
);
}
// components/schema/WebSiteSchema.tsx
export function WebSiteSchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'HM Blog',
url: 'https://yourdomain.com',
description: 'Tech & Life 이야기를 전합니다.',
inLanguage: 'ko-KR',
potentialAction: {
'@type': 'SearchAction',
target: {
'@type': 'EntryPoint',
urlTemplate: 'https://yourdomain.com/search?q={search_term_string}',
},
'query-input': 'required name=search_term_string',
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// components/schema/PersonSchema.tsx
export function PersonSchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'Person',
name: '홍길동',
jobTitle: '시니어 프론트엔드 개발자',
url: 'https://yourdomain.com/me',
image: 'https://yourdomain.com/profile.jpg',
description: 'Tech & Life 블로그를 운영하는 개발자입니다.',
sameAs: [
'https://github.com/username',
'https://linkedin.com/in/username',
'https://twitter.com/username',
],
knowsAbout: ['React', 'Next.js', 'TypeScript', 'Web Development'],
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// components/schema/OrganizationSchema.tsx
export function OrganizationSchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'HM Blog',
url: 'https://yourdomain.com',
logo: 'https://yourdomain.com/logo.png',
sameAs: [
'https://github.com/username',
],
contactPoint: {
'@type': 'ContactPoint',
email: 'contact@yourdomain.com',
contactType: 'customer service',
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
// components/schema/index.tsx
import { BlogPostingSchema } from './BlogPostingSchema';
import { BreadcrumbSchema } from './BreadcrumbSchema';
import { FAQSchema } from './FAQSchema';
interface PostSchemaProps {
post: Post;
faqs?: FAQ[];
}
export function PostStructuredData({ post, faqs }: PostSchemaProps) {
const breadcrumbs = [
{ name: 'Home', url: 'https://yourdomain.com' },
{ name: post.category === 'tech' ? 'Tech' : 'Life', url: `https://yourdomain.com/${post.category}` },
{ name: post.title, url: `https://yourdomain.com/${post.category}/${post.slug}` },
];
return (
<>
<BlogPostingSchema
title={post.title}
description={post.summary}
=
=
=
=
=
=
=
/>
{faqs && faqs.length > 0 && }
);
}
// app/page.tsx
<WebSiteSchema />
<OrganizationSchema />
// app/[category]/[slug]/page.tsx
<PostStructuredData post={post} />
// app/me/page.tsx
<PersonSchema />
https://search.google.com/test/rich-results
https://validator.schema.org/