用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/samhwang/me.samh.page --skill add-resume-section命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | add-resume-section |
| description | Add a new section to the resume page with component, tests, metadata, and integration |
Create a complete resume section following the established patterns: metadata types, data hooks, component, tests, and page integration.
When user asks to:
Ask the user for:
Add the new type to metadata/metadata.ts:
export type SectionName = {
field1: string;
field2: string;
field3?: string; // optional fields use ?
};
Add the field to PersonalInformation in the same file:
export type PersonalInformation = {
// ... existing fields
sectionName: SectionName[];
};
Add the actual data to the personalInformation object in metadata/metadata.ts.
Add to metadata/use-metadata.ts:
import type { SectionName } from './metadata';
export type SectionNameData = SectionName[];
export function useSectionNameData(): SectionNameData {
const { sectionName } = metadata.personalInformation;
return sectionName;
}
Add to src/test-utils/mock-metadata.ts:
import type { SectionNameData } from '../../metadata/use-metadata';
export const sectionNameData: SectionNameData = [
{
field1: 'Test Item 1',
field2: 'Test Value',
},
];
Create src/resume/section-name.tsx (kebab-case filename):
import { useSectionNameData } from '../../metadata/use-metadata';
import { css } from '../../styled-system/css';
import { fullWidth, heading } from '../../styled-system/recipes';
interface ItemProps {
field1: string;
field2: string;
field3?: string;
}
function Item({ field1, field2, field3 }: ItemProps) {
return (
<li className={css({ marginBottom: '0.5rem' })}>
<strong>{field1}</strong> — {field2}
{field3 && ` (${field3})`}
</li>
);
}
export default function SectionNameSection() {
const items = useSectionNameData();
if (items.length === 0) return null;
return (
<div className={fullWidth()}>
<h2 =>Section Name
{items.map((item) => (
))}
);
}
Patterns to follow:
useXxxData())fullWidth, heading) from styled-system/recipescss() from styled-system/css for component-specific stylesCreate src/resume/section-name.test.tsx:
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { sectionNameData as mockData } from '../test-utils/mock-metadata';
import SectionNameSection from './section-name';
describe('SectionNameSection', () => {
it('should match snapshot', () => {
const { container } = render(<SectionNameSection />);
expect(container).toMatchSnapshot();
});
it('displays the section heading', () => {
render(<SectionNameSection />);
const heading = screen.getByRole('heading', { name: 'Section Name', level: 2 });
expect(heading).toBeInTheDocument();
});
it('displays item information', () => {
render(<SectionNameSection />);
const item = mockData[];
(screen.(item.)).();
});
});
Test patterns:
render and screen from @testing-library/react directly../test-utils/mock-metadataAdd to src/routes/index.tsx:
import SectionNameSection from './section-name';
// Add to sections array in desired position
const sections = [
{ id: 'about', content: <About /> },
// ... other sections
{ id: 'section-name', content: <SectionNameSection /> },
// ...
];
pnpm typecheck
pnpm lint
pnpm test
pnpm dev
metadata/metadata.tsPersonalInformation typepersonalInformation objectmetadata/use-metadata.tssrc/test-utils/mock-metadata.tssrc/resume/section-name.tsxsrc/resume/section-name.test.tsxsrc/routes/index.tsx sections arraypnpm typecheck passespnpm lint passespnpm test passesuseXxxData() patternsrc/routes/index.tsx should be kebab-casefullWidth() recipe for wrapper, heading() recipe for the h2section-name.recipe.ts file registered in panda.config.ts