### Install and Run OpenResume with npm Source: https://github.com/xitanggg/open-resume/blob/main/README.md Use npm to install dependencies and start a development server. Ensure Node.js is installed. ```bash git clone https://github.com/xitanggg/open-resume.git cd open-resume npm install npm run dev ``` -------------------------------- ### Install and Run OpenResume with Docker Source: https://github.com/xitanggg/open-resume/blob/main/README.md Use Docker to build and run OpenResume as a container. Docker must be installed and running. ```bash git clone https://github.com/xitanggg/open-resume.git cd open-resume docker build -t open-resume . docker run -p 3000:3000 open-resume ``` -------------------------------- ### Manage Resume Slice Actions Source: https://context7.com/xitanggg/open-resume/llms.txt Provides examples for updating profile fields, modifying work experience sections, and loading parsed resume data into the state. ```typescript // lib/redux/resumeSlice.ts import { useAppDispatch, useAppSelector } from "lib/redux/hooks"; import { changeProfile, changeWorkExperiences, changeEducations, changeProjects, changeSkills, addSectionInForm, deleteSectionInFormByIdx, moveSectionInForm, setResume, selectResume, selectProfile, } from "lib/redux/resumeSlice"; // Update profile fields const ProfileEditor = () => { const dispatch = useAppDispatch(); const profile = useAppSelector(selectProfile); const handleNameChange = (value: string) => { dispatch(changeProfile({ field: "name", value })); }; const handleEmailChange = (value: string) => { dispatch(changeProfile({ field: "email", value })); }; return ( handleNameChange(e.target.value)} /> ); }; // Update work experience const WorkExperienceEditor = () => { const dispatch = useAppDispatch(); const updateCompany = (idx: number, company: string) => { dispatch(changeWorkExperiences({ idx, field: "company", value: company })); }; const updateDescriptions = (idx: number, descriptions: string[]) => { dispatch(changeWorkExperiences({ idx, field: "descriptions", value: descriptions })); }; const addNewExperience = () => { dispatch(addSectionInForm({ form: "workExperiences" })); }; const removeExperience = (idx: number) => { dispatch(deleteSectionInFormByIdx({ form: "workExperiences", idx })); }; const moveUp = (idx: number) => { dispatch(moveSectionInForm({ form: "workExperiences", idx, direction: "up" })); }; }; // Load parsed resume data const loadParsedResume = (parsedResume: Resume) => { dispatch(setResume(parsedResume)); }; ``` -------------------------------- ### Resume Data Structures Source: https://context7.com/xitanggg/open-resume/llms.txt Defines the core TypeScript interfaces for structuring resume data, including profile, work experience, education, projects, and skills. An example `sampleResume` object is provided. ```typescript // lib/redux/types.ts - Core resume data structures interface ResumeProfile { name: string; email: string; phone: string; url: string; summary: string; location: string; } interface ResumeWorkExperience { company: string; jobTitle: string; date: string; descriptions: string[]; } interface ResumeEducation { school: string; degree: string; date: string; gpa: string; descriptions: string[]; } interface ResumeProject { project: string; date: string; descriptions: string[]; } interface FeaturedSkill { skill: string; rating: number; } interface ResumeSkills { featuredSkills: FeaturedSkill[]; descriptions: string[]; } interface Resume { profile: ResumeProfile; workExperiences: ResumeWorkExperience[]; educations: ResumeEducation[]; projects: ResumeProject[]; skills: ResumeSkills; custom: { descriptions: string[] }; } // Example resume data const sampleResume: Resume = { profile: { name: "John Doe", email: "john@example.com", phone: "(123)456-7890", url: "linkedin.com/in/johndoe", summary: "Full-stack developer with 5 years of experience", location: "San Francisco, CA" }, workExperiences: [{ company: "Tech Corp", jobTitle: "Senior Developer", date: "Jan 2020 - Present", descriptions: [ "Led development of microservices architecture", "Mentored team of 5 junior developers" ] }], educations: [{ school: "Stanford University", degree: "B.S. Computer Science", date: "2015 - 2019", gpa: "3.8", descriptions: ["Dean's List", "CS Club President"] }], projects: [{ project: "OpenSource CMS", date: "2021", descriptions: ["Built a headless CMS with 1000+ GitHub stars"] }], skills: { featuredSkills: [ { skill: "React", rating: 4 }, { skill: "TypeScript", rating: 4 } ], descriptions: ["React", "TypeScript", "Node.js", "PostgreSQL"] }, custom: { descriptions: [] } }; ``` -------------------------------- ### Configure Redux Store and Provider Source: https://context7.com/xitanggg/open-resume/llms.txt Sets up the Redux store with resume and settings reducers and demonstrates wrapping the application with the Redux Provider. ```typescript // lib/redux/store.ts import { configureStore } from "@reduxjs/toolkit"; import resumeReducer from "lib/redux/resumeSlice"; import settingsReducer from "lib/redux/settingsSlice"; export const store = configureStore({ reducer: { resume: resumeReducer, settings: settingsReducer, }, }); export type RootState = ReturnType; export type AppDispatch = typeof store.dispatch; // Usage in components with Provider import { Provider } from "react-redux"; function App() { return ( ); } ``` -------------------------------- ### Manage Settings Slice Actions Source: https://context7.com/xitanggg/open-resume/llms.txt Defines the settings interface and demonstrates how to update theme colors, fonts, and section visibility via Redux actions. ```typescript // lib/redux/settingsSlice.ts import { changeSettings, changeShowForm, changeFormHeading, changeFormOrder, changeShowBulletPoints, selectSettings, selectThemeColor, DEFAULT_THEME_COLOR, DEFAULT_FONT_FAMILY, } from "lib/redux/settingsSlice"; // Settings interface interface Settings { themeColor: string; // e.g., "#38bdf8" fontFamily: string; // e.g., "Roboto" fontSize: string; // e.g., "11" documentSize: string; // "Letter" or "A4" formToShow: { workExperiences: boolean; educations: boolean; projects: boolean; skills: boolean; custom: boolean; }; formToHeading: { workExperiences: string; // e.g., "WORK EXPERIENCE" educations: string; projects: string; skills: string; custom: string; }; formsOrder: ShowForm[]; showBulletPoints: { educations: boolean; projects: boolean; skills: boolean; custom: boolean; }; } // Available theme colors const THEME_COLORS = [ "#f87171", // Red-400 "#fb923c", // Orange-400 "#22c55e", // Green-500 "#38bdf8", // Sky-400 (default) "#818cf8", // Indigo-400 ]; // Theme customization component const ThemeCustomizer = () => { const dispatch = useAppDispatch(); const setThemeColor = (color: string) => { dispatch(changeSettings({ field: "themeColor", value: color })); }; const setFontFamily = (font: string) => { dispatch(changeSettings({ field: "fontFamily", value: font })); }; const toggleSection = (section: ShowForm) => { const current = settings.formToShow[section]; dispatch(changeShowForm({ field: section, value: !current })); }; const reorderSection = (section: ShowForm, direction: "up" | "down") => { dispatch(changeFormOrder({ form: section, type: direction })); }; }; ``` -------------------------------- ### Handle Resume File Upload Source: https://context7.com/xitanggg/open-resume/llms.txt Manages drag-and-drop file selection and triggers PDF parsing, followed by state initialization and navigation. ```typescript // components/ResumeDropzone.tsx import { ResumeDropzone } from "components/ResumeDropzone"; import { parseResumeFromPdf } from "lib/parse-resume-from-pdf"; // File upload with drag-and-drop support const ImportResumePage = () => { const [fileUrl, setFileUrl] = useState(""); const router = useRouter(); const handleImport = async () => { // Parse the uploaded PDF const resume = await parseResumeFromPdf(fileUrl); // Initialize settings based on parsed content const settings = { ...initialSettings }; settings.formToShow = { workExperiences: resume.workExperiences.length > 0, educations: resume.educations.length > 0, projects: resume.projects.length > 0, skills: resume.skills.descriptions.length > 0, custom: false, }; // Save to localStorage and navigate to builder saveStateToLocalStorage({ resume, settings }); router.push("/resume-builder"); }; return ( {fileUrl && ( Import and Continue )} ); }; // Dropzone props interface interface ResumeDropzoneProps { onFileUrlChange: (fileUrl: string) => void; className?: string; playgroundView?: boolean; // Compact mode for parser playground } ``` -------------------------------- ### Render Resume PDF Document Source: https://context7.com/xitanggg/open-resume/llms.txt Uses react-pdf to define a document structure with customizable theme colors, fonts, and section visibility. ```typescript // components/Resume/ResumePDF/index.tsx import { Document, Page, View } from "@react-pdf/renderer"; import { ResumePDF } from "components/Resume/ResumePDF"; // PDF Document component const ResumePDFDocument = ({ resume, settings, isPDF = false }) => { const { profile, workExperiences, educations, projects, skills, custom } = resume; const { fontFamily, fontSize, documentSize, formToHeading, formToShow, formsOrder, themeColor } = settings; return ( {/* Theme color header bar */} {themeColor && ( )} {/* Resume content sections */} {formToShow.workExperiences && ( )} {formToShow.educations && ( )} {/* Additional sections... */} ); }; // Usage with live preview const ResumePreview = () => { const resume = useAppSelector(selectResume); const settings = useAppSelector(selectSettings); return ( ); }; ``` -------------------------------- ### Resume Builder Page Component Source: https://context7.com/xitanggg/open-resume/llms.txt Main page component for the resume builder, integrating the form editor and live PDF preview. It uses React Redux for state management and displays ResumeForm and Resume components. ```typescript "use client"; import { Provider } from "react-redux"; import { store } from "lib/redux/store"; import { ResumeForm } from "components/ResumeForm"; import { Resume } from "components/Resume"; export default function ResumeBuilderPage() { return ( {/* Left: Form editor */} {/* Right: Live PDF preview */} ); } // Resume component with zoom controls and download const Resume = () => { const [scale, setScale] = useState(0.8); const resume = useAppSelector(selectResume); const settings = useAppSelector(selectSettings); const document = useMemo( () => , [resume, settings] ); return ( ); }; ``` -------------------------------- ### Resume Parser Page Component Source: https://context7.com/xitanggg/open-resume/llms.txt Page component for the resume parser playground, demonstrating the resume parsing algorithm with visual feedback. It processes a PDF through a pipeline of parsing functions and displays the results. ```typescript "use client"; import { readPdf } from "lib/parse-resume-from-pdf/read-pdf"; import { groupTextItemsIntoLines } from "lib/parse-resume-from-pdf/group-text-items-into-lines"; import { groupLinesIntoSections } from "lib/parse-resume-from-pdf/group-lines-into-sections"; import { extractResumeFromSections } from "lib/parse-resume-from-pdf/extract-resume-from-sections"; export default function ResumeParserPage() { const [fileUrl, setFileUrl] = useState("resume-example/laverne-resume.pdf"); const [textItems, setTextItems] = useState([]); // Process PDF through parser pipeline const lines = groupTextItemsIntoLines(textItems || []); const sections = groupLinesIntoSections(lines); const resume = extractResumeFromSections(sections); useEffect(() => { async function loadPdf() { const items = await readPdf(fileUrl); setTextItems(items); } loadPdf(); }, [fileUrl]); return ( {/* PDF preview */} {/* Upload custom PDF */} setFileUrl(url || defaultUrl)} playgroundView={true} /> {/* Parsed results table */} {/* Algorithm visualization */} ); } ``` -------------------------------- ### Group Lines into Resume Sections Source: https://context7.com/xitanggg/open-resume/llms.txt Organizes lines of text into distinct resume sections by identifying section titles, typically bold and uppercase text. Subsequent lines are grouped under the detected section. Uses a predefined list of keywords to help identify section titles. ```typescript // lib/parse-resume-from-pdf/group-lines-into-sections.ts import { groupLinesIntoSections } from "lib/parse-resume-from-pdf/group-lines-into-sections"; // Section detection keywords const SECTION_TITLE_KEYWORDS = [ "experience", "education", "project", "skill", "job", "course", "extracurricular", "objective", "summary", "award", "honor" ]; const processSections = (lines: Lines) => { const sections = groupLinesIntoSections(lines); // Example output - sections mapped by detected title: // { // "profile": [[name items], [contact items]], // "WORK EXPERIENCE": [[company1 items], [descriptions...]], // "EDUCATION": [[school items], [degree items]], // "SKILLS": [[skill items]] // } console.log("Detected sections:", Object.keys(sections)); // Output: ["profile", "WORK EXPERIENCE", "EDUCATION", "SKILLS"] return sections; }; ``` -------------------------------- ### Parse Resume from PDF Source: https://context7.com/xitanggg/open-resume/llms.txt Handles file uploads and uses the `parseResumeFromPdf` function to extract structured resume data from a PDF. Ensure to revoke the object URL after use to prevent memory leaks. ```typescript // lib/parse-resume-from-pdf/index.ts import { parseResumeFromPdf } from "lib/parse-resume-from-pdf"; // Parse a resume from a PDF file const handleFileUpload = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; // Create object URL for the uploaded file const fileUrl = URL.createObjectURL(file); try { // Parse the resume - returns structured Resume object const resume = await parseResumeFromPdf(fileUrl); console.log("Parsed Resume:", { name: resume.profile.name, email: resume.profile.email, phone: resume.profile.phone, location: resume.profile.location, workExperiences: resume.workExperiences.length, educations: resume.educations.length, projects: resume.projects.length, skills: resume.skills.descriptions }); // Output example: // { // name: "John Doe", // email: "john@example.com", // phone: "(123)456-7890", // location: "San Francisco, CA", // workExperiences: 2, // educations: 1, // projects: 3, // skills: ["JavaScript", "React", "Node.js"] // } } finally { // Clean up object URL URL.revokeObjectURL(fileUrl); } }; ``` -------------------------------- ### Implement LocalStorage State Persistence Source: https://context7.com/xitanggg/open-resume/llms.txt Provides utility functions to serialize and deserialize Redux state to localStorage, along with custom hooks for automatic synchronization. ```typescript // lib/redux/local-storage.ts import { loadStateFromLocalStorage, saveStateToLocalStorage, getHasUsedAppBefore } from "lib/redux/local-storage"; const LOCAL_STORAGE_KEY = "open-resume-state"; // Save state to localStorage const saveState = (state: RootState) => { try { const stringifiedState = JSON.stringify(state); localStorage.setItem(LOCAL_STORAGE_KEY, stringifiedState); } catch (e) { // Handle storage quota exceeded } }; // Load state from localStorage const loadState = (): RootState | undefined => { try { const stringifiedState = localStorage.getItem(LOCAL_STORAGE_KEY); if (!stringifiedState) return undefined; return JSON.parse(stringifiedState); } catch (e) { return undefined; } }; // Custom hooks for automatic persistence import { useSaveStateToLocalStorageOnChange, useSetInitialStore } from "lib/redux/hooks"; const ResumeForm = () => { // Load initial state from localStorage on mount useSetInitialStore(); // Auto-save state changes to localStorage useSaveStateToLocalStorageOnChange(); return ...; }; ``` -------------------------------- ### Extract Resume Attributes from Sections Source: https://context7.com/xitanggg/open-resume/llms.txt The main extraction engine that utilizes a feature-scoring system to identify and extract specific resume attributes from the organized sections. This function populates a complete Resume object with fields like profile, work experiences, education, etc. ```typescript // lib/parse-resume-from-pdf/extract-resume-from-sections/index.ts import { extractResumeFromSections } from "lib/parse-resume-from-pdf/extract-resume-from-sections"; // Feature scoring example for profile extraction // Each feature set: [matchFunction, score, returnMatchOnly?] const NAME_FEATURE_SETS = [ [matchOnlyLetterSpaceOrPeriod, 3, true], // +3 for letter-only names [isBold, 2], // +2 for bold text [hasLetterAndIsAllUpperCase, 2], // +2 for uppercase [hasAt, -4], // -4 if contains @ (likely email) [hasNumber, -4], // -4 if contains numbers ]; const extractFromSections = (sections: ResumeSectionToLines) => { const resume = extractResumeFromSections(sections); // Returns complete Resume object with all fields populated: // { // profile: { name, email, phone, location, url, summary }, // workExperiences: [{ company, jobTitle, date, descriptions }], // educations: [{ school, degree, date, gpa, descriptions }], // projects: [{ project, date, descriptions }], // skills: { featuredSkills, descriptions }, // custom: { descriptions: [] } // } return resume; }; ``` -------------------------------- ### Read PDF and Extract Text Items Source: https://context7.com/xitanggg/open-resume/llms.txt Reads a PDF file and extracts text items, including their text content, position, font, and styling information. Requires the 'pdfjs-dist' library. The output is an array of TextItem objects. ```typescript // lib/parse-resume-from-pdf/read-pdf.ts import { readPdf } from "lib/parse-resume-from-pdf/read-pdf"; // TextItem interface returned by readPdf interface TextItem { text: string; x: number; // X position (origin: bottom-left) y: number; // Y position (origin: bottom-left) width: number; height: number; fontName: string; // e.g., "GVDLYI+Arial-BoldMT" hasEOL: boolean; // End of line marker } // Read PDF and get text items const processResumePdf = async (fileUrl: string) => { const textItems = await readPdf(fileUrl); // Example output for first few items: // [ // { text: "John Doe", x: 72, y: 750, width: 85, height: 18, // fontName: "Arial-BoldMT", hasEOL: true }, // { text: "john@example.com", x: 72, y: 730, width: 120, height: 12, // fontName: "Arial", hasEOL: false }, // { text: " | ", x: 192, y: 730, width: 10, height: 12, // fontName: "Arial", hasEOL: false }, // { text: "(123)456-7890", x: 202, y: 730, width: 90, height: 12, // fontName: "Arial", hasEOL: true } // ] return textItems; }; ``` -------------------------------- ### Group Text Items into Lines Source: https://context7.com/xitanggg/open-resume/llms.txt Groups extracted text items into logical lines, merging adjacent items that might have been split due to PDF encoding. Uses EOL markers to identify line breaks. Input is an array of TextItem, output is an array of lines, where each line is an array of TextItem. ```typescript // lib/parse-resume-from-pdf/group-text-items-into-lines.ts import { groupTextItemsIntoLines } from "lib/parse-resume-from-pdf/group-text-items-into-lines"; // Lines are arrays of TextItem arrays type Line = TextItem[]; type Lines = Line[]; const processLines = (textItems: TextItems) => { const lines = groupTextItemsIntoLines(textItems); // Example output - each line is an array of text items: // [ // [{ text: "John Doe", ... }], // Line 1: Name // [{ text: "john@example.com | (123)456-7890", ... }], // Line 2: Contact // [{ text: "WORK EXPERIENCE", ... }], // Line 3: Section // [{ text: "Tech Corp", ... }, { text: "2020-Present", ... }] // Line 4 // ] console.log(`Grouped ${textItems.length} items into ${lines.length} lines`); return lines; }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.