@jsonresume/core
v0.1.0
Published
Framework-agnostic resume component core - design tokens, primitives, and validators
Readme
@jsonresume/core
React component library for building ATS-friendly, print-optimized resume themes
A comprehensive collection of 200+ React components, design tokens, and utilities that enable rapid development of professional resume themes. Built with styled-components for maximum flexibility and SSR support.
Features
- 200+ React Components - Comprehensive primitives across 20 categories
- Design Tokens System - Typography, colors, spacing, layout, radius, shadows
- Security Utilities - URL validation, HTML sanitization, external link detection
- Calculation Helpers - 20+ functions for resume metrics and statistics
- SSR Support - Full server-side rendering with styled-components
- Print Optimization - Perfect PDF exports with @media print styles
- ATS-Friendly - Semantic HTML, proper heading hierarchy, accessibility features
- Theme Support - ThemeProvider with customizable design tokens
Installation
npm install @jsonresume/core
# or
yarn add @jsonresume/core
# or
pnpm add @jsonresume/corePeer Dependencies:
This package requires React 18 or 19 and styled-components:
npm install react react-dom styled-componentsQuick Start
import React from 'react';
import {
ThemeProvider,
Section,
SectionTitle,
ListItem,
DateRange,
Badge,
BadgeList,
} from '@jsonresume/core';
function Resume({ resume }) {
return (
<ThemeProvider>
<Section id="work">
<SectionTitle>Work Experience</SectionTitle>
{resume.work.map((job) => (
<ListItem
key={job.name}
title={job.position}
subtitle={job.name}
dateRange={<DateRange start={job.startDate} end={job.endDate} />}
location={job.location}
highlights={job.highlights}
/>
))}
</Section>
<Section id="skills">
<SectionTitle>Skills</SectionTitle>
{resume.skills.map((skill) => (
<div key={skill.name}>
<h3>{skill.name}</h3>
<BadgeList items={skill.keywords} />
</div>
))}
</Section>
</ThemeProvider>
);
}
export default Resume;Component Categories
Core Primitives (7 components)
Basic building blocks for resume sections:
Section- Semantic section wrapper with print optimizationSectionTitle- Styled section headingsListItem- Experience/education entries with metadataDateRange- Smart date formatting with "Present" supportBadge- Skill tags and keywordsBadgeList- Multiple badges with consistent stylingContactInfo- Contact details with iconsLink- Safe external links with security validation
Layout Components (6 components)
Structure and organization:
GridLayout- Multi-column responsive gridsSidebarLayout- Two-column layout with sidebarStackLayout- Vertical stacking with spacingCardLayout- Card-based content containersFlexLayout- Flexible box layoutsTwoColumnMicroGrid- Compact two-column grids
Skills Components (6 components)
Visual skill representations:
SkillBar- Progress bar visualizationSkillPill- Pill-shaped skill badgesSkillRating- Star or dot rating displaySkillGroup- Grouped skill categoriesSkillCloud- Tag cloud visualizationSkillCategory- Categorized skill lists
Profile Components (4 components)
Header and contact sections:
Avatar- Profile image with fallbackProfileCard- Complete profile headerContactGrid- Grid of contact methodsSocialLinks- Social media icon links
Typography Components (6 components)
Text styling and formatting:
Heading- Semantic headings (h1-h6)Text- Body text with variantsLabel- Small labels and captionsSectionIntroParagraph- Section introductionsQuoteStripe- Pull quotesHyphenationSafeParagraph- Print-safe paragraphs
Data Display Components (10 components)
Metrics and statistics:
ProgressCircle- Circular progress indicatorsStatCard- Statistic cardsMetricBar- Horizontal metric barsMetricInline- Inline metric displayMetricBullet- Bullet-style metricsMetricBulletList- List of bullet metricsKPIChipLine- Key performance indicator chipsKPIChip- Single KPI chipKeyValueInline- Inline key-value pairsKeyValue- Block key-value pairs
Experience Components (4 components)
Work history layouts:
ExperienceCard- Card-based job entriesExperienceTimeline- Timeline visualizationExperienceGrid- Grid layout for multiple jobsExperienceCompact- Condensed job listings
Header/Footer Components (11 components)
Page headers and footers:
HeaderCentered- Centered header layoutHeaderSplit- Two-column headerHeaderMinimal- Minimal header designCornerInitials- Initials in cornerFooter- Page footerPageBreak- Explicit page breaksHeroNameBlock- Large name displayContactRowLine- Single-line contact rowSectionRuleTitle- Title with horizontal ruleSectionFlagTitle- Title with accent flagNameStackElegant- Elegant name stack
Timeline Components (4 components)
Chronological displays:
TimelineSection- Full timeline sectionTimelineItem- Individual timeline entryTimelineRuleMinimal- Minimal timeline ruleTimelineInline- Inline timeline display
Quote/Testimonial Components (3 components)
Highlighted quotes:
PullQuote- Sidebar pull quotesTestimonial- Testimonial cardsBlockQuote- Block quote styling
Certification/Award Components (4 components)
Credentials and honors:
CertificationBadge- Certification badgesCertificationRow- Row-based cert displayAwardCard- Award cardsHonorsList- List of honors
Language Components (4 components)
Language proficiency:
LanguageBar- Progress bar for proficiencyLanguageLevelBarLite- Compact proficiency barLanguageGrid- Grid of languagesProficiencyScale- Visual proficiency scale
Publication/Portfolio Components (4 components)
Academic and creative work:
PublicationItem- Publication entriesPublicationEntryPlain- Plain publication formatPortfolioGrid- Portfolio item gridProjectCard- Project showcase cards
Table Components (3 components)
Structured data:
SkillMatrix- Skills matrix tableComparisonTable- Comparison tablesDataTable- Generic data tables
List Components (11 components)
Various list styles:
CheckList- Checkmark listsIconList- Lists with iconsNumberedList- Numbered listsBulletList- Bullet point listsCompactList- Condensed listsAchievementListTight- Tight achievement listsAchievementListSpacious- Spacious achievementsHangingBulletList- Hanging indent bulletsListDashCompact- Dash-separated listsMiniDotLeaderList- Dot leader listsDefinitionKeyline- Definition lists
Callout Components (3 components)
Highlighted content:
Callout- Callout boxesInfoBox- Information boxesHighlightCard- Highlighted cards
Visual Components (4 components)
Decorative elements:
BackgroundPattern- Background patternsColorBlock- Colored blocksDividerVariants- Various divider stylesBorderAccent- Border accents
Date Components (2 components)
Date formatting:
DateBadge- Date badgesRelativeDate- Relative date formatting
Print Utilities (8 components)
Print optimization:
KeepTogether- Prevent page breaksColumnBreak- Force column breaksPrintOnly- Show only in printScreenOnly- Show only on screenPageHeaderLine- Print headersPageFooterLine- Print footersLetterheadBar- Letterhead stylingSoftShadowEmulation- Print-safe shadows
Metadata Components (5 components)
Supplementary information:
InlineKicker- Inline kickersMetaRow- Metadata rowsSubsectionLabel- Subsection labelsGreyLabelCaps- Small caps labelsSmallCapsHeading- Small caps headings
Container Components (4 components)
Content containers:
MutedPanel- Muted background panelsAccentCalloutPanel- Accent panelsSoftCardOutline- Soft card outlinesRoleBlockFramed- Framed role blocks
Tag/Badge Components (2 components)
Tags and badges:
ToolTagRibbon- Tool tag ribbonsBadgeRowOutline- Outlined badge rows
Design Tokens
Access design tokens for consistent theming:
import { typography, colors, spacing, layout, radius, shadows } from '@jsonresume/core';
console.log(colors.primary); // 'var(--resume-color-primary)'
console.log(typography.fonts.sans); // 'var(--resume-font-sans)'Available token categories:
typography- Font families, sizes, weights, line heightscolors- Primary, secondary, accent, muted, background colorsspacing- Margins, padding, gapslayout- Max widths, container sizesradius- Border radius valuesshadows- Box shadow definitions
Raw tokens (for SSR/PDF generation):
import { rawTokens } from '@jsonresume/core';
console.log(rawTokens.typography.fonts.sans);
// '"Helvetica Neue", Helvetica, Arial, sans-serif'Security Utilities
Protect against XSS and malicious URLs:
import { safeUrl, sanitizeHtml, isExternalUrl, getLinkRel } from '@jsonresume/core';
// Validate URLs before rendering
const url = safeUrl(userProvidedUrl); // Returns safe URL or '#'
// Sanitize HTML content
const clean = sanitizeHtml(userHTML); // Strips dangerous tags/attributes
// Check if URL is external
if (isExternalUrl(url)) {
// Add external link indicators
}
// Get appropriate rel attribute
const rel = getLinkRel(url); // Returns 'noopener noreferrer' for externalBest practices:
- Always use
safeUrl()for user-provided URLs - Use
sanitizeHtml()for any user HTML content - Apply
getLinkRel()to external links
Calculation Helpers
Calculate resume metrics and statistics:
import {
calculateTotalExperience,
countCompanies,
getHighestDegree,
isCurrentlyEmployed,
} from '@jsonresume/core';
const resume = { work: [...], education: [...] };
const experience = calculateTotalExperience(resume.work); // Years of experience
const companies = countCompanies(resume.work); // Number of companies
const degree = getHighestDegree(resume.education); // Highest degree
const employed = isCurrentlyEmployed(resume.work); // BooleanAvailable calculations:
calculateTotalExperience(work)- Total years of experiencecalculateCurrentRoleExperience(work)- Current role durationcountCompanies(work)- Number of companies worked atcountProjects(projects)- Number of projectscountPublications(publications)- Number of publicationscountAwards(awards)- Number of awardscountTotalSkills(skills)- Total skill countcountSkillCategories(skills)- Number of skill categoriescountLanguages(languages)- Number of languagescalculateVolunteerYears(volunteer)- Years of volunteer workcalculateEducationYears(education)- Years of educationgetHighestDegree(education)- Highest degree earnedcountCareerPositions(work)- Total positions heldgetCareerProgressionRate(work)- Career progression ratecountTotalHighlights(work)- Total highlights across jobsgetUniqueIndustries(work)- Unique industries worked ingetCurrentEmployer(work)- Current employer nameisCurrentlyEmployed(work)- Employment statuscalculateKeyMetrics(resume)- All metrics in one object
Server-Side Rendering (SSR)
Full SSR support with styled-components:
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';
import Resume from './Resume';
export function render(resume) {
const sheet = new ServerStyleSheet();
try {
const html = renderToString(sheet.collectStyles(<Resume resume={resume} />));
const styleTags = sheet.getStyleTags();
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${resume.basics.name} - Resume</title>
${styleTags}
</head>
<body>
${html}
</body>
</html>
`;
} finally {
sheet.seal();
}
}IMPORTANT: Without ServerStyleSheet, styled-components won't inject CSS and your theme will have no styles!
Theme Building Tutorial
Step 1: Create Theme Package
mkdir packages/jsonresume-theme-myname
cd packages/jsonresume-theme-myname
pnpm initStep 2: Configure package.json
{
"name": "jsonresume-theme-myname",
"version": "1.0.0",
"main": "./src/index.js",
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
},
"dependencies": {
"@jsonresume/core": "workspace:*",
"styled-components": "workspace:*"
}
}Step 3: Create Resume Component
// src/Resume.jsx
import React from 'react';
import {
ThemeProvider,
Section,
SectionTitle,
ProfileCard,
ExperienceTimeline,
BadgeList,
} from '@jsonresume/core';
export default function Resume({ resume }) {
const { basics, work, education, skills } = resume;
return (
<ThemeProvider>
<ProfileCard
name={basics.name}
label={basics.label}
email={basics.email}
phone={basics.phone}
url={basics.url}
summary={basics.summary}
/>
<Section id="work">
<SectionTitle>Experience</SectionTitle>
<ExperienceTimeline items={work} />
</Section>
<Section id="education">
<SectionTitle>Education</SectionTitle>
{education.map((edu) => (
<div key={edu.institution}>
<h3>{edu.institution}</h3>
<p>
{edu.studyType} in {edu.area}
</p>
</div>
))}
</Section>
<Section id="skills">
<SectionTitle>Skills</SectionTitle>
{skills.map((skill) => (
<div key={skill.name}>
<h4>{skill.name}</h4>
<BadgeList items={skill.keywords} />
</div>
))}
</Section>
</ThemeProvider>
);
}Step 4: Create Render Function
// src/index.js
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';
import Resume from './Resume.jsx';
export function render(resume) {
const sheet = new ServerStyleSheet();
try {
const html = renderToString(sheet.collectStyles(<Resume resume={resume} />));
const styles = sheet.getStyleTags();
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${resume.basics.name} - Resume</title>
${styles}
</head>
<body>
${html}
</body>
</html>
`;
} finally {
sheet.seal();
}
}Step 5: Register Theme
Add to apps/registry/lib/formatters/template/themeConfig.js:
import * as myTheme from 'jsonresume-theme-myname';
export const THEMES = {
// ...
myname: {
name: 'My Theme',
theme: myTheme,
description: 'A beautiful custom theme',
},
};Examples
Complete Resume
import Resume from 'jsonresume-theme-myname';
const resumeData = {
basics: {
name: 'John Doe',
label: 'Software Engineer',
email: '[email protected]',
// ...
},
work: [
{
name: 'TechCorp',
position: 'Senior Engineer',
startDate: '2020-01',
endDate: null,
highlights: ['Led team of 6', 'Reduced costs by $200k'],
},
],
// ...
};
const html = Resume.render(resumeData);Custom Styling
import styled from 'styled-components';
import { Section as BaseSection } from '@jsonresume/core';
const CustomSection = styled(BaseSection)`
background: linear-gradient(to right, #f0f0f0, #ffffff);
padding: 2rem;
border-radius: 8px;
`;TypeScript Support
TypeScript definitions are included:
import { Section, SectionTitle, ListItem } from '@jsonresume/core';
import type { Resume } from '@jsonresume/core';
function MyResume({ resume }: { resume: Resume }) {
// Full type safety
}Browser Support
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Requirements:
- CSS Custom Properties support
- ES6+ JavaScript
Performance
- Bundle Size: ~15KB minified + gzipped (core components only)
- Tree-Shakeable: Import only what you need
- SSR Optimized: Fast server-side rendering
- Print Optimized: Perfect PDF generation
Contributing
Contributions welcome! Please follow these guidelines:
- Add Tests: All new components must have tests
- Follow Conventions: Use existing naming patterns
- Document: Add JSDoc comments and examples
- Keep Components Small: Under 200 lines per file
- Use Styled Components: Consistent with existing code
Related Packages
- jsonresume-theme-standard - Classic theme
- jsonresume-theme-professional - Professional theme
- jsonresume-theme-spartacus - Spartacus theme
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: jsonresume.org
License
MIT
Part of the JSON Resume ecosystem - Open source resume standard used by thousands of developers worldwide.
