@resume-mapper/widget
v1.2.0
Published
AI-powered CV parsing widget for recruitment portals
Downloads
239
Maintainers
Readme
@resume-mapper/widget
AI-powered CV parsing widget for recruitment portals. Drop-in React component that handles file uploads, sends CVs to the Resume Mapper API, and returns structured candidate data — in seconds.
Features
- Zero-config drop-in — one component, one API key, works instantly
- AI-powered parsing — GPT-4o-mini extracts structured data from PDF, DOCX, and TXT
- Typed results — full TypeScript types for
ParseResult,ParsedExperience,ParsedSkill, and more - i18n ready — built-in support for
en,pl,de,es,fr - Theming — light / dark / auto (follows system preference) + CSS custom properties
- White-label — hide branding on Pro plan (
showBranding={false}) - React 18+ — CJS and ESM builds, SSR-safe
Installation
npm install @resume-mapper/widget
# or
pnpm add @resume-mapper/widget
# or
yarn add @resume-mapper/widgetPeer dependencies:
react >= 18.0.0andreact-dom >= 18.0.0
Get an API Key
Sign up for free at resume-mapper.dev — the Trial plan includes 25 free parses with no credit card required.
Your API key will start with rm_.
Quick Start
import { ResumeMapper } from '@resume-mapper/widget'
function App() {
return (
<ResumeMapper
apiKey='rm_your_api_key_here'
onParsed={result => {
console.log('Parsed CV:', result.rawData)
// Update your candidate profile with the extracted data
}}
onError={error => {
console.error('Parse error:', error.message)
}}
/>
)
}Props
| Prop | Type | Default | Description |
| -------------- | -------------------------------------- | --------------------------------------- | --------------------------------------- |
| apiKey | string | required | Your Resume Mapper API key |
| apiUrl | string | 'https://resume-mapper.dev/api/parse' | Custom API endpoint (for self-hosted) |
| onParsed | (result: ParseResult) => void | - | Callback when CV is successfully parsed |
| onError | (error: Error) => void | - | Callback when parsing fails |
| onUpload | (file: File) => void | - | Callback when file is selected |
| accept | string[] | ['application/pdf', ...] | Accepted MIME types |
| maxSize | number | 10485760 (10MB) | Maximum file size in bytes |
| disabled | boolean | false | Disable the widget |
| className | string | '' | Additional CSS classes |
| theme | 'light' \| 'dark' \| 'auto' | 'auto' | Color theme |
| showBranding | boolean | true | Show "Powered by Resume Mapper" |
| locale | 'en' \| 'pl' \| 'de' \| 'es' \| 'fr' | 'en' | UI language |
ParseResult Type
interface ParseResult {
success: boolean
data: Record<string, unknown> // Your mapped fields
rawData: {
personalInfo: {
firstName?: string
lastName?: string
email?: string
phone?: string
location?: string
linkedIn?: string
github?: string
summary?: string
}
experience: Array<{
company: string
position: string
startDate?: string
endDate?: string
current?: boolean
description?: string
}>
education: Array<{
institution: string
degree?: string
field?: string
startDate?: string
endDate?: string
}>
skills: Array<{
name: string
level?: 'beginner' | 'intermediate' | 'advanced' | 'expert'
}>
languages: Array<{
name: string
level?: string
}>
certifications: Array<{
name: string
issuer?: string
date?: string
}>
projects: Array<{
name: string
description?: string
technologies?: string[]
}>
}
metadata: {
fileName: string
parsedAt: string
usage: {
cvParsedThisMonth: number
cvLimit: number | 'unlimited'
}
}
}Customization
Custom Text
<ResumeMapper
apiKey='rm_...'
dropzoneText='Upload your resume'
parseButtonText='Extract Data'
parsingText='Processing...'
/>Theme
// Force dark mode
<ResumeMapper apiKey="rm_..." theme="dark" />
// Force light mode
<ResumeMapper apiKey="rm_..." theme="light" />
// Auto (follows system preference) - default
<ResumeMapper apiKey="rm_..." theme="auto" />Localization
// Polish
<ResumeMapper apiKey="rm_..." locale="pl" />
// German
<ResumeMapper apiKey="rm_..." locale="de" />
// Spanish
<ResumeMapper apiKey="rm_..." locale="es" />
// French
<ResumeMapper apiKey="rm_..." locale="fr" />Remove Branding (Pro only)
<ResumeMapper apiKey='rm_...' showBranding={false} />Custom Styling
The widget uses CSS custom properties that you can override:
.rm-widget {
--rm-bg: #ffffff;
--rm-text: #1a1a1a;
--rm-text-muted: #6b7280;
--rm-border: #e5e7eb;
--rm-primary: #3b82f6;
--rm-primary-hover: #2563eb;
--rm-success: #10b981;
--rm-error: #ef4444;
--rm-radius: 0.75rem;
}TypeScript Usage
All types are exported from the package — no separate @types install needed.
import type {
ParseResult,
ParsedPersonalInfo,
ParsedExperience,
ParsedEducation,
ParsedSkill,
ParsedLanguage,
ParsedCertification,
ParsedProject,
ResumeMapperProps,
} from '@resume-mapper/widget'
import { ResumeMapper } from '@resume-mapper/widget'
function CandidateForm() {
const handleParsed = (result: ParseResult) => {
const { personalInfo, experience, skills } = result.rawData
// personalInfo.email, personalInfo.firstName, etc.
// experience[0].company, experience[0].position, etc.
}
return <ResumeMapper apiKey='rm_...' onParsed={handleParsed} />
}Error Handling
import { ResumeMapper } from '@resume-mapper/widget'
function App() {
return (
<ResumeMapper
apiKey='rm_...'
onParsed={result => {
if (!result.success) {
// result.success is false when the API returned an error
console.warn('Parsing returned no data')
return
}
saveCandidate(result.rawData)
}}
onError={error => {
// Network errors, invalid API key, quota exceeded, etc.
if (error.message.includes('quota')) {
showAlert('Monthly parse limit reached. Please upgrade your plan.')
} else {
showAlert('Could not parse CV. Please try again.')
}
}}
/>
)
}Framework Integration
Next.js (App Router)
Mark the parent as a Client Component — the widget uses browser APIs:
'use client'
import { ResumeMapper } from '@resume-mapper/widget'
export default function UploadPage() {
return <ResumeMapper apiKey={process.env.NEXT_PUBLIC_RM_API_KEY!} onParsed={console.log} />
}Next.js (Pages Router)
import dynamic from 'next/dynamic'
const ResumeMapper = dynamic(() => import('@resume-mapper/widget').then(m => m.ResumeMapper), {
ssr: false,
})
export default function UploadPage() {
return <ResumeMapper apiKey={process.env.NEXT_PUBLIC_RM_API_KEY!} onParsed={console.log} />
}Vite / CRA / plain React
import { ResumeMapper } from '@resume-mapper/widget'
export function UploadPage() {
return <ResumeMapper apiKey='rm_...' onParsed={console.log} />
}Supported React Versions
| React | Supported | | ----- | --------- | | 18.x | ✅ | | 19.x | ✅ | | 17.x | ❌ |
Plans & Limits
| Plan | Monthly parses | White-label | Custom field mapping | | ------- | -------------- | ----------- | -------------------- | | Trial | 25 (one-time) | ❌ | ❌ | | Starter | 200 | ❌ | ❌ | | Pro | Unlimited | ✅ | ✅ |
See full pricing at resume-mapper.dev/#pricing.
Contributing
Issues and PRs are welcome. When reporting a bug, please attach a sample CV file (anonymised) to help reproduce it.
- Repository: github.com/resume-mapper/widget
- Email: [email protected]
License
Proprietary — Commercial Use License. Use of this package requires an active Resume Mapper subscription. See LICENSE for details.
