用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/miles990/claude-software-skills --skill content-platforms命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | content-platforms |
| description | CMS, blogging platforms, and content management patterns |
| domain | domain-applications |
| version | 1.0.0 |
| tags | ["cms","blog","content","markdown","rich-text","media"] |
| triggers | {"keywords":{"primary":["cms","blog","content management","headless cms","rich text editor"],"secondary":["markdown","media library","versioning","publishing","seo","tiptap"]},"context_boost":["content","article","post","page","publish"],"context_penalty":["e-commerce","payment","game"],"priority":"medium"} |
Building content management systems, blogging platforms, and rich media applications.
// Content types
interface ContentType {
id: string;
name: string;
slug: string;
fields: Field[];
settings: ContentTypeSettings;
}
interface Field {
id: string;
name: string;
type: FieldType;
required: boolean;
localized: boolean;
validation?: FieldValidation;
}
type FieldType =
| 'text'
| 'richText'
| 'number'
| 'boolean'
| 'date'
| 'media'
| 'reference'
| 'array'
| 'json';
// Blog post content type
const blogPostType: ContentType = {
id: 'blogPost',
name: 'Blog Post',
slug: 'blog-posts',
fields: [
{ id: 'title', name: 'Title', type: 'text', required: true, localized: true },
{ id: 'slug', name: 'Slug', type: 'text', required: true, localized: false },
{ id: 'content', name: 'Content', type: 'richText', required: true, localized: true },
{ id: 'excerpt', name: 'Excerpt', type: 'text', required: false, localized: true },
{ id: 'featuredImage', name: 'Featured Image', type: 'media', required: false, localized: false },
{ id: 'author', name: 'Author', type: 'reference', required: true, localized: false },
{ id: 'tags', name: 'Tags', type: 'array', required: false, localized: false },
{ id: 'publishedAt', name: 'Published At', type: 'date', required: false, localized: false },
{ id: 'seo', name: 'SEO', type: 'json', required: false, localized: true },
],
settings: {
previewable: true,
versionable: true,
publishable: true,
},
};
// Prisma schema
/*
model Content {
id String @id @default(cuid())
contentTypeId String
status String @default("draft")
data Json
locale String @default("en")
version Int @default(1)
publishedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([contentTypeId, status])
@@index([contentTypeId, locale])
}
*/
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Image from '@tiptap/extension-image';
import Link from '@tiptap/extension-link';
import Placeholder from '@tiptap/extension-placeholder';
function RichTextEditor({
content,
onChange,
}: {
content: string;
onChange: (content: string) => void;
}) {
const editor = useEditor({
extensions: [
StarterKit,
Image.configure({ inline: true }),
Link.configure({ openOnClick: false }),
Placeholder.configure({ placeholder: 'Start writing...' }),
],
content,
onUpdate: ({ editor }) => {
onChange(editor.getHTML());
},
});
if (!editor) return null;
(
);
}
() {
(
);
}
import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import sharp from 'sharp';
const s3 = new S3Client({ region: process.env.AWS_REGION });
interface MediaAsset {
id: string;
filename: string;
mimeType: string;
size: number;
url: string;
thumbnailUrl?: string;
width?: number;
height?: number;
alt?: string;
}
// Upload with image processing
async function uploadMedia(file: Express.Multer.File): Promise<MediaAsset> {
const id = crypto.randomUUID();
const extension = path.extname(file.originalname);
key = ;
processedBuffer = file.;
: | ;
: | ;
(file..()) {
image = (file.);
metadata = image.();
width = metadata.;
height = metadata.;
(width && width > ) {
processedBuffer = image
.(, , { : })
.();
}
thumbnail = image
.(, , { : })
.({ : })
.();
s3.( ({
: process..,
: ,
: thumbnail,
: ,
}));
}
s3.( ({
: process..,
: key,
: processedBuffer,
: file.,
}));
prisma..({
: {
id,
: file.,
: file.,
: processedBuffer.,
: ,
: file..()
?
: ,
width,
height,
},
});
}
() {
cacheKey = ;
cached = redis.(cacheKey);
(cached) {
.(cached, );
}
original = s3.( ({
: process..,
: key,
}));
image = ( original.?.());
(options. || options.) {
image = image.(options., options., {
: ,
: ,
});
}
(options.) {
image = image.(options., { : });
}
buffer = image.();
redis.(cacheKey, , buffer.());
buffer;
}
interface ContentVersion {
id: string;
contentId: string;
version: number;
data: Record<string, any>;
createdBy: string;
createdAt: Date;
changeDescription?: string;
}
// Create new version
async function createVersion(
contentId: string,
data: Record<string, any>,
userId: string,
description?: string
) {
const current = await prisma.content.findUnique({
where: { id: contentId },
});
// Save current as version
await prisma.contentVersion.create({
data: {
contentId,
version: current.version,
data: current.data,
createdBy: userId,
changeDescription: description,
},
});
// Update content
return prisma..({
: { : contentId },
: {
data,
: { : },
},
});
}
() {
prisma..({
: { contentId },
: { : },
: {
: { : { : , : } },
},
});
}
() {
version = prisma..({
: { contentId, : versionNumber },
});
(!version) {
();
}
(contentId, version., userId, );
}
() {
diff = ();
(oldVersion., newVersion.);
}
enum ContentStatus {
DRAFT = 'draft',
IN_REVIEW = 'in_review',
APPROVED = 'approved',
PUBLISHED = 'published',
ARCHIVED = 'archived',
}
// Workflow transitions
const workflowTransitions: Record<ContentStatus, ContentStatus[]> = {
[ContentStatus.DRAFT]: [ContentStatus.IN_REVIEW],
[ContentStatus.IN_REVIEW]: [ContentStatus.DRAFT, ContentStatus.APPROVED],
[ContentStatus.APPROVED]: [ContentStatus.IN_REVIEW, ContentStatus.PUBLISHED],
[ContentStatus.PUBLISHED]: [ContentStatus.ARCHIVED],
[ContentStatus.ARCHIVED]: [ContentStatus.DRAFT],
};
async function transitionContent(
contentId: string,
newStatus: ContentStatus,
: ,
?:
) {
content = prisma..({ : { : contentId } });
allowedTransitions = workflowTransitions[content.];
(!allowedTransitions.(newStatus)) {
();
}
prisma..({
: {
contentId,
: content.,
: newStatus,
userId,
comment,
},
});
prisma..({
: { : contentId },
: {
: newStatus,
...(newStatus === . && { : () }),
},
});
}
() {
prisma..({
: { : contentId },
: {
: publishAt,
: .,
},
});
queue.(, { contentId }, {
: publishAt.() - .(),
});
}
interface SEOMetadata {
title: string;
description: string;
keywords?: string[];
ogImage?: string;
ogType?: string;
canonical?: string;
noIndex?: boolean;
}
function generateSEOTags(meta: SEOMetadata, url: string) {
return {
title: meta.title,
meta: [
{ name: 'description', content: meta.description },
meta.keywords && { name: 'keywords', content: meta.keywords.join(', ') },
meta.noIndex && { name: 'robots', content: 'noindex, nofollow' },
// Open Graph
{ property: 'og:title', content: meta.title },
{ property: 'og:description', content: meta.description },
{ property: 'og:type', : meta. || },
{ : , : url },
meta. && { : , : meta. },
{ : , : },
{ : , : meta. },
{ : , : meta. },
meta. && { : , : meta. },
].(),
: [
meta. && { : , : meta. },
].(),
};
}
Enterprise-grade repository analysis with arc42/C4 architecture documentation, technical debt quantification, security assessment, and multi-stakeholder reporting
Claude Code Plugin 開發、發布、安裝、更新與 Marketplace 管理完整指南
Flame Engine core fundamentals - components, input, collision, camera, animation, scenes
基于 SOC 职业分类