| name | add-resume-section |
| description | Add a new section to the resume page with component, tests, metadata, and integration |
Add Resume Section Skill
Purpose
Create a complete resume section following the established patterns: metadata types, data hooks, component, tests, and page integration.
Trigger Condition
When user asks to:
- Add a new resume section
- Add a new section to the resume page
- Create a new resume component
Workflow
Step 1: Gather Section Details
Ask the user for:
- Section name (e.g., "Certifications", "Awards", "Publications")
- Data shape (what fields each item has, e.g., name, issuer, date)
- Position in the resume (order among existing sections)
- Special rendering needs (links, icons, conditional display)
Step 2: Add Metadata Types
Add the new type to metadata/metadata.ts:
export type SectionName = {
field1: string;
field2: string;
field3?: string;
};
Add the field to PersonalInformation in the same file:
export type PersonalInformation = {
sectionName: SectionName[];
};
Add the actual data to the personalInformation object in metadata/metadata.ts.
Step 3: Create Data Hook
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;
}
Step 4: Add Mock Data
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',
},
];
Step 5: Create Component
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:
- Default export for the main component
- Hook pattern for data (
useXxxData())
- Early return for empty state
- Import shared recipes (
fullWidth, heading) from styled-system/recipes
- Use
css() from styled-system/css for component-specific styles
- Inline single-use styles, define constants for repeated styles
Step 6: Write Tests
Create 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:
- Import
render and screen from @testing-library/react directly
- Import mock data from
../test-utils/mock-metadata
- Include snapshot test
- Test heading renders with correct name and level
- Test item data displays
Step 7: Integrate into Page
Add to src/routes/index.tsx:
import SectionNameSection from './section-name';
const sections = [
{ id: 'about', content: <About /> },
{ id: 'section-name', content: <SectionNameSection /> },
];
Step 8: Verify
pnpm typecheck
pnpm lint
pnpm test
pnpm dev
Checklist
Notes
- Section name should be PascalCase in code, kebab-case in filename
- Hook name follows
useXxxData() pattern
- Section ID in
src/routes/index.tsx should be kebab-case
- Use
fullWidth() recipe for wrapper, heading() recipe for the h2
- If the section has many named parts, define a slot recipe in a
section-name.recipe.ts file registered in panda.config.ts