@@ -285,17 +282,17 @@ export function MinimalTemplate({ data }: TemplateProps) {
-
+
{ref.name}
-
+
{ref.title} at {ref.company}
-
+
{ref.relationship}
-
+
@@ -304,16 +301,31 @@ export function MinimalTemplate({ data }: TemplateProps) {
))}
- );
-
- default:
- return null;
- }
- };
+ )}
- return (
-
- {visibleSections.map(renderSection)}
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+ {pub.title}
+
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
+
+
+ )}
+
);
}
\ No newline at end of file
diff --git a/src/components/resume-builder/templates/MinimalistATS.tsx b/src/components/resume-builder/templates/MinimalistATS.tsx
new file mode 100644
index 0000000..b4fc4ff
--- /dev/null
+++ b/src/components/resume-builder/templates/MinimalistATS.tsx
@@ -0,0 +1,158 @@
+import { TemplateProps } from './types';
+
+export function MinimalistATS({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short' });
+ };
+
+ return (
+
+ {/* Header */}
+
+
{personalInfo?.fullName}
+ {personalInfo?.title &&
{personalInfo.title}
}
+
+ {personalInfo?.email && {personalInfo.email}}
+ {personalInfo?.phone && {personalInfo.phone}}
+ {personalInfo?.location && {personalInfo.location}}
+ {personalInfo?.linkedin && linkedin.com/in/username}
+
+
+
+ {/* Summary */}
+ {summary && (
+
+ )}
+
+ {/* Experience */}
+ {experience.length > 0 && (
+
+
EXPERIENCE
+
+ {experience.map((exp) => (
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education.length > 0 && (
+
+
EDUCATION
+
+ {education.map((edu) => (
+
+
+
{edu.degree}
+
+ {formatDate(edu.graduationDate)}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+ {edu.gpa && ` β’ GPA: ${edu.gpa}`}
+
+
+ ))}
+
+
+ )}
+
+ {/* Skills */}
+ {skills.length > 0 && (
+
+
SKILLS
+
+ {skills.map((skill) => (
+
+ {skill.name}
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
CERTIFICATIONS
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
+ {cert.issuer} β’ {formatDate(cert.date)}
+
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
PROJECTS
+
+ {projects.map((project) => (
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ Technologies: {project.technologies.join(', ')}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
PUBLICATIONS
+
+ {publications.map((pub) => (
+
+
{pub.title}
+
+ {pub.journal} β’ {formatDate(pub.publicationDate)}
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/MinimalistProfessionalTemplate.tsx b/src/components/resume-builder/templates/MinimalistProfessionalTemplate.tsx
new file mode 100644
index 0000000..4c1c5cf
--- /dev/null
+++ b/src/components/resume-builder/templates/MinimalistProfessionalTemplate.tsx
@@ -0,0 +1,310 @@
+import { TemplateProps } from './types';
+
+export function MinimalistProfessionalTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ const formatUrl = (url: string) => {
+ if (!url) return '';
+ return url.replace(/^https?:\/\/(www\.)?/, '').replace(/\/$/, '');
+ };
+
+ return (
+
+ {/* Personal Info */}
+
+
+
+ {personalInfo?.fullName || 'Your Name'}
+
+
+
+ {personalInfo?.title || 'Professional Title'}
+
+
+
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+
+ Profile
+
+
+ {summary}
+
+
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+ Experience
+
+
+ {experience.map((exp) => (
+
+
+
+ {exp.jobTitle}
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+ {edu.degree}
+
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+ {edu.gpa && ` β’ GPA: ${edu.gpa}`}
+
+ {edu.relevantCourses && edu.relevantCourses.length > 0 && (
+
+
+ Relevant Coursework:
+
+
+ {edu.relevantCourses.map((course, i) => (
+
+ {course}
+
+ ))}
+
+
+ )}
+
+ ))}
+
+
+
+ )}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ Skills
+
+
+ {skills.map((skill) => (
+
+ {skill.name}
+
+ ))}
+
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
+ {project.name}
+ {project.url && (
+
+ (View Project)
+
+ )}
+
+ {project.startDate && (
+
+ {formatDate(project.startDate)}
+ {project.endDate ? ` - ${formatDate(project.endDate)}` : ' - Present'}
+
+ )}
+
+
+ {project.description}
+
+ {project.technologies && project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, i) => (
+
+ {tech}
+
+ ))}
+
+ )}
+
+ ))}
+
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
+ {cert.name}
+
+
+ {cert.issuer}
+ {cert.date && ` β’ ${formatDate(cert.date)}`}
+ {cert.expirationDate && ` - ${formatDate(cert.expirationDate)}`}
+
+
+ ))}
+
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+ {pub.title}
+
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/MinimalistSidebarTemplate.tsx b/src/components/resume-builder/templates/MinimalistSidebarTemplate.tsx
new file mode 100644
index 0000000..2fa2f38
--- /dev/null
+++ b/src/components/resume-builder/templates/MinimalistSidebarTemplate.tsx
@@ -0,0 +1,222 @@
+import { Mail, Phone, MapPin, Globe, Briefcase, GraduationCap, User, Award, BookOpen, Star } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function MinimalistSidebarTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ const renderSidebar = () => (
+
+ {personalInfo?.profileImage && (
+
+

+
+ )}
+
+
+
+
CONTACT
+
+ {personalInfo?.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+
+
+
{personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.website && (
+
+
+ {personalInfo.website.replace(/^https?:\/\//, '')}
+
+ )}
+
+
+
+ {skills && skills.length > 0 && (
+
+
SKILLS
+
+ {skills.map((skill) => (
+
+
+ {skill.name}
+
+ {skill.level === 'Expert' ? 'β
β
β
β
β
' :
+ skill.level === 'Advanced' ? 'β
β
β
β
β' :
+ skill.level === 'Intermediate' ? 'β
β
β
ββ' : 'β
β
βββ'}
+
+
+
+ ))}
+
+
+ )}
+
+
+ );
+
+ const renderMainContent = () => (
+
+
+ {personalInfo?.fullName || 'Your Name'}
+
+
+ {personalInfo?.title || 'Professional Title'}
+
+
+ {summary && (
+
+
+
+ PROFILE
+
+
{summary}
+
+ )}
+
+ {experience.length > 0 && (
+
+
+
+ EXPERIENCE
+
+
+ {experience.map((exp) => (
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ - {desc}
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {education && education.length > 0 && (
+
+
+
+ EDUCATION
+
+
+ {education.map((edu) => (
+
+
+
{edu.degree}
+
+ {formatDate(edu.graduationDate)}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+ {edu.gpa && ` β’ GPA: ${edu.gpa}`}
+
+
+ ))}
+
+
+ )}
+
+ {certifications && certifications.length > 0 && (
+
+
+
+ CERTIFICATIONS
+
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
+ {cert.issuer} β’ {formatDate(cert.date)}
+
+
+ ))}
+
+
+ )}
+
+ {projects && projects.length > 0 && (
+
+
+
+ PROJECTS
+
+
+ {projects.map((project) => (
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ Technologies: {project.technologies.join(', ')}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {publications && publications.length > 0 && (
+
+
+
+ PUBLICATIONS
+
+
+ {publications.map((pub) => (
+
+
{pub.title}
+
+ {pub.journal} β’ {formatDate(pub.publicationDate)}
+
+
+ ))}
+
+
+ )}
+
+ );
+
+ return (
+
+ {renderSidebar()}
+ {renderMainContent()}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/MinimalistTemplate.tsx b/src/components/resume-builder/templates/MinimalistTemplate.tsx
new file mode 100644
index 0000000..3ebfd1e
--- /dev/null
+++ b/src/components/resume-builder/templates/MinimalistTemplate.tsx
@@ -0,0 +1,261 @@
+import { Mail, Phone, MapPin, Globe, Linkedin, Github } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function MinimalistTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ const formatUrl = (url: string) => {
+ if (!url) return '';
+ return url.replace(/^https?:\/\/(www\.)?/, '').replace(/\/$/, '');
+ };
+
+ return (
+
+ {/* Personal Info */}
+
+
+ {personalInfo?.fullName || 'Your Name'}
+
+ {personalInfo?.title && (
+
+ {personalInfo.title}
+
+ )}
+
+
+ {personalInfo?.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.website && (
+
+
+ {formatUrl(personalInfo.website)}
+
+ )}
+ {personalInfo?.linkedin && (
+
+
+ {formatUrl(personalInfo.linkedin)}
+
+ )}
+ {personalInfo?.github && (
+
+
+ {formatUrl(personalInfo.github)}
+
+ )}
+
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+ About
+
+
+ {summary}
+
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+ Experience
+
+
+ {experience.map((exp) => (
+
+
+
+ {exp.jobTitle}
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}{exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+ {edu.degree}
+
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
+
+
+
+ {edu.school}{edu.location && ` β’ ${edu.location}`}
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+ Skills
+
+
+ {skills.map((skill) => (
+
+ {skill.name}
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
+ {cert.name}
+
+
+ {cert.issuer}
+ {cert.date && ` β’ ${formatDate(cert.date)}`}
+
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+ {project.technologies && project.technologies.length > 0 && (
+
+ {project.technologies.join(' β’ ')}
+
+ )}
+
+ {project.description}
+
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+ {pub.title}
+
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ModernDarkSidebarTemplate.tsx b/src/components/resume-builder/templates/ModernDarkSidebarTemplate.tsx
new file mode 100644
index 0000000..4aa7e46
--- /dev/null
+++ b/src/components/resume-builder/templates/ModernDarkSidebarTemplate.tsx
@@ -0,0 +1,229 @@
+import { Mail, Phone, MapPin, Globe, Briefcase, GraduationCap, User, BookOpen, Star } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ModernDarkSidebarTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ const renderSidebar = () => (
+
+ {personalInfo?.profileImage && (
+
+

+
+ )}
+
+
+
+
CONTACT
+
+ {personalInfo?.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+
+
+
{personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.website && (
+
+ )}
+
+
+
+ {skills && skills.length > 0 && (
+
+
SKILLS
+
+ {skills.map((skill) => (
+
+
+ {skill.name}
+
+ {skill.level === 'Expert' ? 'β
β
β
β
β
' :
+ skill.level === 'Advanced' ? 'β
β
β
β
β' :
+ skill.level === 'Intermediate' ? 'β
β
β
ββ' : 'β
β
βββ'}
+
+
+
+ ))}
+
+
+ )}
+
+ {certifications && certifications.length > 0 && (
+
+
CERTIFICATIONS
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
{cert.issuer}
+ {cert.date && (
+
+ {new Date(cert.date).toLocaleDateString('en-US', { year: 'numeric', month: 'short' })}
+
+ )}
+
+ ))}
+
+
+ )}
+
+
+ );
+
+ const renderMainContent = () => (
+
+
+
+ {personalInfo?.fullName || 'Your Name'}
+
+
+ {personalInfo?.title || 'Professional Title'}
+
+
+
+ {summary && (
+
+
+
+ ABOUT ME
+
+
{summary}
+
+ )}
+
+ {experience.length > 0 && (
+
+
+
+ WORK EXPERIENCE
+
+
+ {experience.map((exp) => (
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {education && education.length > 0 && (
+
+
+
+ EDUCATION
+
+
+ {education.map((edu) => (
+
+
+
{edu.degree}
+
+ {formatDate(edu.graduationDate)}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+ {edu.gpa && ` β’ GPA: ${edu.gpa}`}
+
+
+ ))}
+
+
+ )}
+
+ {projects && projects.length > 0 && (
+
+
+
+ PROJECTS
+
+
+ {projects.map((project) => (
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ Technologies: {project.technologies.join(', ')}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {publications && publications.length > 0 && (
+
+
+
+ PUBLICATIONS
+
+
+ {publications.map((pub) => (
+
+
{pub.title}
+
+ {pub.journal} β’ {formatDate(pub.publicationDate)}
+
+
+ ))}
+
+
+ )}
+
+ );
+
+ return (
+
+ {renderSidebar()}
+ {renderMainContent()}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ModernExecutiveTemplate.tsx b/src/components/resume-builder/templates/ModernExecutiveTemplate.tsx
new file mode 100644
index 0000000..01abbb1
--- /dev/null
+++ b/src/components/resume-builder/templates/ModernExecutiveTemplate.tsx
@@ -0,0 +1,262 @@
+import { Mail, Phone, MapPin, Linkedin, Globe, Briefcase, GraduationCap, Star, BookOpen } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ModernExecutiveTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+ const accentColor = customization?.accentColor || '#2563eb';
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Sidebar */}
+
+ {/* Profile Image */}
+ {personalInfo?.profileImage && (
+
+

+
+ )}
+
+ {/* Contact */}
+
+
+ Contact
+
+
+ {personalInfo?.email && (
+ -
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+ -
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+ -
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.linkedin && (
+ -
+
+ LinkedIn
+
+ )}
+ {personalInfo?.website && (
+ -
+
+ {personalInfo.website.replace(/^https?:\/\//, '')}
+
+ )}
+
+
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+ Skills
+
+
+ {skills.map((skill) => (
+
+
+ {skill.name}
+ {skill.level}
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications.length > 0 && (
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
{cert.issuer}
+
+ {formatDate(cert.date)}
+ {cert.expirationDate && ` β’ Expires: ${formatDate(cert.expirationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+
+ {/* Main Content */}
+
+ {/* Header */}
+
+
+ {personalInfo?.fullName}
+
+ {personalInfo?.title && (
+
+ {personalInfo.title}
+
+ )}
+
+
+ {/* Summary */}
+ {summary && (
+
+
+ Professional Summary
+
+
+ {summary}
+
+
+ )}
+
+ {/* Experience */}
+ {experience.length > 0 && (
+
+
+
+ Work Experience
+
+
+ {experience.map((exp) => (
+
+
+
+
{exp.jobTitle}
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
{edu.degree}
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+
+ {edu.fieldOfStudy}
+ {formatDate(edu.graduationDate)}
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ Technologies: {project.technologies.join(', ')}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+
{pub.title}
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ModernProfessionalTemplate.tsx b/src/components/resume-builder/templates/ModernProfessionalTemplate.tsx
new file mode 100644
index 0000000..0fe9154
--- /dev/null
+++ b/src/components/resume-builder/templates/ModernProfessionalTemplate.tsx
@@ -0,0 +1,367 @@
+import { Mail, Phone, MapPin, Globe, Linkedin, Github, Briefcase, GraduationCap, Code, Award, User, BookOpen } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ModernProfessionalTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Personal Info */}
+
+
+
+ {personalInfo?.fullName || 'Your Name'}
+
+
+ {personalInfo?.title || 'Professional Title'}
+
+
+
+
+
+ {personalInfo?.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.website && (
+
+
+ Website
+
+ )}
+ {personalInfo?.linkedin && (
+
+
+ LinkedIn
+
+ )}
+ {personalInfo?.github && (
+
+
+ GitHub
+
+ )}
+
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+
+ Professional Profile
+
+
+ {summary}
+
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+ Professional Experience
+
+
+ {experience.map((exp) => (
+
+
+
+
+ {exp.jobTitle}
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+
+ {edu.degree}
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
+
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+ {edu.relevantCourses && edu.relevantCourses.length > 0 && (
+
+
+ Relevant Coursework:
+
+
+ {edu.relevantCourses.map((course, i) => (
+
+ {course}
+
+ ))}
+
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ Skills & Expertise
+
+
+ {skills.map((skill) => (
+
+
+
+ {skill.name}
+
+
+ {skill.level}
+
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
+ {project.name}
+ {project.url && (
+
+ (View Project)
+
+ )}
+
+ {project.startDate && (
+
+ {formatDate(project.startDate)}
+ {project.endDate ? ` - ${formatDate(project.endDate)}` : ' - Present'}
+
+ )}
+
+
+ {project.description}
+
+ {project.technologies && project.technologies.length > 0 && (
+
+
+ {project.technologies.map((tech, i) => (
+
+ {tech}
+
+ ))}
+
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
+ {cert.name}
+
+
+ {cert.issuer}
+
+
+ {formatDate(cert.date)}
+ {cert.expirationDate && ` - ${formatDate(cert.expirationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+ {pub.title}
+
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ModernSidebarTemplate.tsx b/src/components/resume-builder/templates/ModernSidebarTemplate.tsx
new file mode 100644
index 0000000..0ca1ec2
--- /dev/null
+++ b/src/components/resume-builder/templates/ModernSidebarTemplate.tsx
@@ -0,0 +1,283 @@
+import { Mail, Phone, MapPin, Globe, Linkedin, Github, Briefcase, GraduationCap, User, BookOpen } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ModernSidebarTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ const renderSidebar = () => (
+
+ {personalInfo?.profileImage && (
+
+

+
+ )}
+
+
+
+
CONTACT
+
+ {personalInfo?.email && (
+
+ )}
+ {personalInfo?.phone && (
+
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.website && (
+
+ )}
+ {personalInfo?.linkedin && (
+
+ )}
+ {personalInfo?.github && (
+
+ )}
+
+
+
+ {skills && skills.length > 0 && (
+
+
SKILLS
+
+ {skills.map((skill) => (
+
+
+ {skill.name}
+
+ {skill.level === 'Expert' ? 'β
β
β
β
β
' :
+ skill.level === 'Advanced' ? 'β
β
β
β
β' :
+ skill.level === 'Intermediate' ? 'β
β
β
ββ' : 'β
β
βββ'}
+
+
+
+ ))}
+
+
+ )}
+
+ {certifications && certifications.length > 0 && (
+
+
CERTIFICATIONS
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
{cert.issuer}
+
+ {formatDate(cert.date)}
+ {cert.expirationDate && ` β’ Expires: ${formatDate(cert.expirationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+
+ );
+
+ const renderMainContent = () => (
+
+
+
+ {personalInfo?.fullName}
+
+ {personalInfo?.title && (
+
+ {personalInfo.title}
+
+ )}
+
+
+ {summary && (
+
+
+
+ PROFILE
+
+
{summary}
+
+ )}
+
+ {experience && experience.length > 0 && (
+
+
+
+ EXPERIENCE
+
+
+ {experience.map((exp) => (
+
+
+
+
+ {exp.jobTitle}
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {education && education.length > 0 && (
+
+
+
+ EDUCATION
+
+
+ {education.map((edu) => (
+
+
+
+
+ {edu.degree}
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+
+
+ {formatDate(edu.graduationDate)}
+
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {projects && projects.length > 0 && (
+
+
+
+ PROJECTS
+
+
+ {projects.map((project) => (
+
+
+
+ {project.name}
+
+
+ {formatDate(project.startDate)}
+ {project.endDate && ` - ${formatDate(project.endDate)}`}
+
+
+
+ {project.description}
+
+ {project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, idx) => (
+
+ {tech}
+
+ ))}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {publications && publications.length > 0 && (
+
+
+
+ PUBLICATIONS
+
+
+ {publications.map((pub) => (
+
+
+ {pub.title}
+
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+ );
+
+ return (
+
+ {renderSidebar()}
+ {renderMainContent()}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ModernTemplate.tsx b/src/components/resume-builder/templates/ModernTemplate.tsx
index b338344..3faf50a 100644
--- a/src/components/resume-builder/templates/ModernTemplate.tsx
+++ b/src/components/resume-builder/templates/ModernTemplate.tsx
@@ -1,16 +1,9 @@
-import React from 'react';
-import { ResumeData } from '@/types/resume';
import { Mail, Phone, MapPin, Globe, Linkedin, Github } from 'lucide-react';
-
-interface TemplateProps {
- data: ResumeData;
-}
+import { TemplateProps } from './types';
export function ModernTemplate({ data }: TemplateProps) {
- const { personalInfo, summary, experience, education, skills, certifications, projects, references, sections, customization } = data;
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, references, customization } = data || {};
- const visibleSections = sections.filter(section => section.isVisible).sort((a, b) => a.order - b.order);
-
const formatDate = (dateStr: string) => {
if (!dateStr) return '';
const date = new Date(dateStr + '-01');
@@ -23,317 +16,324 @@ export function ModernTemplate({ data }: TemplateProps) {
return url.replace(/^https?:\/\/(www\.)?/, '');
};
- const renderSection = (section: typeof sections[0]) => {
- switch (section.type) {
- case 'personalInfo':
- return (
-
-
- {customization.showProfileImage && personalInfo.profileImage && (
-

+ return (
+
+ {/* Personal Info */}
+
+
+ {customization?.showProfileImage && personalInfo?.profileImage && (
+

+ )}
+
+
+ {personalInfo?.fullName || 'Your Name'}
+
+
+
+ {personalInfo?.email && (
+
+
+ {personalInfo.email}
+
)}
-
-
- {personalInfo.fullName || 'Your Name'}
-
-
-
- {personalInfo.email && (
-
-
- {personalInfo.email}
-
- )}
- {personalInfo.phone && (
-
-
- {personalInfo.phone}
-
- )}
- {personalInfo.location && (
-
-
- {personalInfo.location}
-
- )}
- {personalInfo.website && (
-
-
- {formatUrl(personalInfo.website)}
-
- )}
- {personalInfo.linkedin && (
-
-
- {formatUrl(personalInfo.linkedin)}
-
- )}
- {personalInfo.github && (
-
-
- {formatUrl(personalInfo.github)}
-
- )}
+ {personalInfo?.phone && (
+
-
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.website && (
+
+
+ {formatUrl(personalInfo.website)}
+
+ )}
+ {personalInfo?.linkedin && (
+
+
+ {formatUrl(personalInfo.linkedin)}
+
+ )}
+ {personalInfo?.github && (
+
+
+ {formatUrl(personalInfo.github)}
+
+ )}
- );
+
+
- case 'summary':
- if (!summary) return null;
- return (
-
-
-
-
- Professional Summary
-
-
-
- {summary}
-
+ {/* Summary */}
+ {summary && (
+
+
+
+
+ Professional Summary
+
- );
+
+ {summary}
+
+
+ )}
- case 'experience':
- if (experience.length === 0) return null;
- return (
-
-
-
-
- Work Experience
-
-
-
- {experience.map((exp) => (
-
-
-
-
-
- {exp.jobTitle}
-
-
- {exp.company}{exp.location && `, ${exp.location}`}
-
-
-
- {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
-
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+
+ Work Experience
+
+
+
+ {experience.map((exp) => (
+
+
+
+
+
+ {exp.jobTitle}
+
+
+ {exp.company}{exp.location && `, ${exp.location}`}
+
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
-
- {exp.description.filter(desc => desc.trim()).map((desc, index) => (
- - {desc}
- ))}
-
- ))}
-
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ - {desc}
+ ))}
+
+
+ ))}
- );
+
+ )}
- case 'education':
- if (education.length === 0) return null;
- return (
-
-
-
- {education.map((edu) => (
-
-
-
-
-
- {edu.degree}
-
-
- {edu.school}{edu.location && `, ${edu.location}`}
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ {education.map((edu) => (
+
+
+
+
+
+ {edu.degree}
+
+
+ {edu.school}{edu.location && `, ${edu.location}`}
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
- {edu.gpa && (
-
- GPA: {edu.gpa}
-
- )}
-
-
- {formatDate(edu.graduationDate)}
-
+ )}
+
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
- ))}
-
+
+ ))}
- );
+
+ )}
- case 'skills':
- if (skills.length === 0) return null;
- return (
-
-
-
- {skills.map((skill) => (
-
-
{skill.name}
-
- {skill.level}
-
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ {skills.map((skill) => (
+
+ {skill.name}
+
+ {skill.level}
+
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+
+ {certifications.map((cert) => (
+
+
+
+ {cert.name}
+
+
+ {cert.issuer}
+
- ))}
-
+
+ {formatDate(cert.date)}
+ {cert.expirationDate && ` - ${formatDate(cert.expirationDate)}`}
+
+
+ ))}
- );
+
+ )}
- case 'certifications':
- if (certifications.length === 0) return null;
- return (
-
-
-
- {certifications.map((cert) => (
-
-
-
- {cert.name}
-
-
- {cert.issuer}
-
-
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ {projects.map((project) => (
+
+
+
+ {project.name}
+
- {formatDate(cert.date)}
- {cert.expirationDate && ` - ${formatDate(cert.expirationDate)}`}
+ style={{ backgroundColor: customization?.accentColor, fontFamily: customization?.fontFamily }}>
+ {formatDate(project.startDate)}
+ {project.endDate && ` - ${formatDate(project.endDate)}`}
- ))}
-
+
+ {project.description}
+
+ {project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, index) => (
+
+ {tech}
+
+ ))}
+
+ )}
+ {project.url && (
+
+ {formatUrl(project.url)}
+
+ )}
+
+ ))}
- );
+
+ )}
- case 'projects':
- if (projects.length === 0) return null;
- return (
-
-
-
- {projects.map((project) => (
-
-
-
- {project.name}
+ {/* References */}
+ {references && references.length > 0 && (
+
+
+
+
+ Professional References
+
+
+
+ {references.map((ref) => (
+
+
+
+
+ {ref.name}
-
- {formatDate(project.startDate)}
- {project.endDate && ` - ${formatDate(project.endDate)}`}
-
-
-
- {project.description}
-
- {project.technologies.length > 0 && (
-
- {project.technologies.map((tech, index) => (
-
- {tech}
-
- ))}
-
- )}
- {project.url && (
-
- {formatUrl(project.url)}
+
+ {ref.title} at {ref.company}
- )}
+
+ {ref.relationship}
+
+
+
+
{ref.email}
+
{ref.phone}
+
- ))}
-
+
+ ))}
- );
+
+ )}
- case 'references':
- if (references.length === 0) return null;
- return (
-
-
-
-
- Professional References
-
-
-
- {references.map((ref) => (
-
-
-
-
- {ref.name}
-
-
- {ref.title} at {ref.company}
-
-
- {ref.relationship}
-
-
-
-
{ref.email}
-
{ref.phone}
-
-
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+
+ {publications.map((pub) => (
+
+
+ {pub.title}
+
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ ))}
- ))}
-
- );
-
- default:
- return null;
- }
- };
-
- return (
-
- {visibleSections.map(renderSection)}
+ )}
);
}
\ No newline at end of file
diff --git a/src/components/resume-builder/templates/ModernTimelineTemplate.tsx b/src/components/resume-builder/templates/ModernTimelineTemplate.tsx
new file mode 100644
index 0000000..b95a117
--- /dev/null
+++ b/src/components/resume-builder/templates/ModernTimelineTemplate.tsx
@@ -0,0 +1,269 @@
+import { Mail, Phone, MapPin, Briefcase, GraduationCap, Award, Star, BookOpen } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ModernTimelineTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+ const accentColor = customization?.accentColor || '#3b82f6';
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Header */}
+
+
+ {personalInfo?.fullName}
+
+ {personalInfo?.title && (
+
+ {personalInfo.title}
+
+ )}
+
+ {personalInfo?.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+
+
+ {personalInfo.location}
+
+ )}
+
+
+
+ {/* Summary */}
+ {summary && (
+
+ )}
+
+ {/* Timeline Section */}
+
+ {/* Timeline Line */}
+
+
+
+ {/* Experience */}
+ {experience.length > 0 && (
+
+
+
+ Work Experience
+
+
+ {experience.map((exp) => (
+
+
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+
+
{edu.degree}
+
+ {formatDate(edu.graduationDate)}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+ {edu.fieldOfStudy && (
+
+ {edu.fieldOfStudy}
+
+ )}
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+
+ ))}
+
+
+ )}
+
+
+
+ {/* Skills & Certifications */}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ Key Skills
+
+
+ {skills.map((skill) => (
+
+ {skill.name}
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
+ {cert.issuer} β’ {formatDate(cert.date)}
+
+
+ ))}
+
+
+ )}
+
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, i) => (
+ {tech}
+ ))}
+
+ )}
+
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+
+
{pub.title}
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ModernTwoColumn.tsx b/src/components/resume-builder/templates/ModernTwoColumn.tsx
new file mode 100644
index 0000000..d316fe9
--- /dev/null
+++ b/src/components/resume-builder/templates/ModernTwoColumn.tsx
@@ -0,0 +1,248 @@
+import { Mail, Phone, MapPin, Linkedin } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ModernTwoColumn({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+ const accentColor = customization?.accentColor || '#3b82f6';
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short' });
+ };
+
+ return (
+
+ {/* Left Column */}
+
+ {/* Profile */}
+
+
+ {personalInfo?.profileImage ? (
+

+ ) : (
+
+
+ {personalInfo?.fullName.split(' ').map(n => n[0]).join('')}
+
+
+ )}
+
+
{personalInfo?.fullName}
+ {personalInfo?.title && (
+
{personalInfo.title}
+ )}
+
+
+ {/* Contact */}
+
+
Contact
+
+ {personalInfo?.email && (
+ -
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo?.phone && (
+ -
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo?.location && (
+ -
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo?.linkedin && (
+ -
+
+ LinkedIn
+
+ )}
+
+
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
Skills
+
+ {skills.map((skill) => (
+
+
+ {skill.name}
+ {skill.level}
+
+
+
+ ))}
+
+
+ )}
+
+
+ {/* Right Column */}
+
+ {/* Summary */}
+ {summary && (
+
+
+ About Me
+
+
{summary}
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+ Work Experience
+
+
+ {experience.map((exp) => (
+
+
+
+
{exp.jobTitle}
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+
{edu.degree}
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+
+
+ {formatDate(edu.graduationDate)}
+
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, i) => (
+ {tech}
+ ))}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
{pub.title}
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ View Publication
+
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
+ {cert.issuer} β’ {formatDate(cert.date)}
+
+
+ ))}
+
+
+ )}
+
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ProfessionalBlueTemplate.tsx b/src/components/resume-builder/templates/ProfessionalBlueTemplate.tsx
new file mode 100644
index 0000000..475d5d3
--- /dev/null
+++ b/src/components/resume-builder/templates/ProfessionalBlueTemplate.tsx
@@ -0,0 +1,130 @@
+import { Briefcase, GraduationCap, Code, User } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ProfessionalBlueTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Personal Info */}
+
+
+ {personalInfo.profileImage && (
+
+

+
+ )}
+
+
{personalInfo.fullName || 'Your Name'}
+
{personalInfo.title || 'Professional Title'}
+
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+
+ PROFILE
+
+
{summary}
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+ WORK EXPERIENCE
+
+
+ {experience.map((exp) => (
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ EDUCATION
+
+
+ {education.map((edu) => (
+
+
+
{edu.degree}
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+ {edu.gpa && ` β’ GPA: ${edu.gpa}`}
+
+
+ ))}
+
+
+ )}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ SKILLS
+
+
+ {skills.map((skill) => (
+
+
+
+ {skill.name}
+
+
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ProfessionalSidebarTemplate.tsx b/src/components/resume-builder/templates/ProfessionalSidebarTemplate.tsx
new file mode 100644
index 0000000..1b579fb
--- /dev/null
+++ b/src/components/resume-builder/templates/ProfessionalSidebarTemplate.tsx
@@ -0,0 +1,175 @@
+import { Mail, Phone, MapPin, Linkedin, Briefcase, GraduationCap } from 'lucide-react';
+import { ResumeData } from '@/types/resume';
+
+type TemplateProps = {
+ data: ResumeData;
+};
+
+export function ProfessionalSidebarTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills } = data;
+ const accentColor = data.customization.accentColor || '#2563eb';
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Sidebar */}
+
+ {/* Profile */}
+
+ {personalInfo.profileImage ? (
+
+

+
+ ) : (
+
+
+ {personalInfo.fullName.split(' ').map(n => n[0]).join('')}
+
+
+ )}
+
{personalInfo.fullName}
+ {personalInfo.title &&
{personalInfo.title}
}
+
+
+ {/* Contact */}
+
+
Contact
+
+ {personalInfo.email && (
+ -
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo.phone && (
+ -
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo.location && (
+ -
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo.linkedin && (
+ -
+
+ LinkedIn
+
+ )}
+
+
+
+ {/* Skills */}
+ {skills.length > 0 && (
+
+
Skills
+
+ {skills.map((skill) => (
+
+
+ {skill.name}
+ {skill.level}
+
+
+
+ ))}
+
+
+ )}
+
+
+ {/* Main Content */}
+
+ {/* Summary */}
+ {summary && (
+
+
+ Professional Summary
+
+
{summary}
+
+ )}
+
+ {/* Experience */}
+ {experience.length > 0 && (
+
+
+
+ Work Experience
+
+
+ {experience.map((exp) => (
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
{edu.degree}
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+
+ {edu.relevantCourses ? edu.relevantCourses.join(', ') : ''}
+ {formatDate(edu.graduationDate)}
+
+ {edu.gpa && (
+
GPA: {edu.gpa}
+ )}
+
+ ))}
+
+
+ )}
+
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ProfessionalSummaryTemplate.tsx b/src/components/resume-builder/templates/ProfessionalSummaryTemplate.tsx
new file mode 100644
index 0000000..58f1bc7
--- /dev/null
+++ b/src/components/resume-builder/templates/ProfessionalSummaryTemplate.tsx
@@ -0,0 +1,189 @@
+import { ResumeData } from '@/types/resume';
+import { Briefcase, GraduationCap, User, Code, Mail, Phone, MapPin, Globe } from 'lucide-react';
+
+interface TemplateProps {
+ data: ResumeData;
+}
+
+export function ProfessionalSummaryTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications } = data;
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Header */}
+
+
{personalInfo.fullName || 'Your Name'}
+
{personalInfo.title || 'Professional Title'}
+
+
+ {personalInfo.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo.phone && (
+
+
+
{personalInfo.phone}
+
+ )}
+ {personalInfo.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo.website && (
+
+ )}
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+
+ PROFESSIONAL SUMMARY
+
+
{summary}
+
+ )}
+
+
+ {/* Left Column */}
+
+ {/* Experience */}
+ {experience.length > 0 && (
+
+
+
+ WORK EXPERIENCE
+
+
+ {experience.map((exp) => (
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education.length > 0 && (
+
+
+
+ EDUCATION
+
+
+ {education.map((edu) => (
+
+
+
{edu.degree}
+
+ {formatDate(edu.graduationDate)}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+ {edu.gpa && ` β’ GPA: ${edu.gpa}`}
+
+
+ ))}
+
+
+ )}
+
+
+ {/* Right Column */}
+
+ {/* Skills */}
+ {skills.length > 0 && (
+
+
+
+ SKILLS
+
+
+ {skills.map((skill) => (
+
+
+
+ {skill.name}
+
+
+ {skill.level}
+
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
CERTIFICATIONS
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
{cert.issuer}
+ {cert.date && (
+
+ {new Date(cert.date).toLocaleDateString('en-US', { year: 'numeric', month: 'short' })}
+
+ )}
+
+ ))}
+
+
+ )}
+
+
+
+ );
+}
diff --git a/src/components/resume-builder/templates/ProfessionalTemplate.tsx b/src/components/resume-builder/templates/ProfessionalTemplate.tsx
new file mode 100644
index 0000000..4d0c6fe
--- /dev/null
+++ b/src/components/resume-builder/templates/ProfessionalTemplate.tsx
@@ -0,0 +1,174 @@
+import { Mail, Phone, MapPin, Globe, Linkedin, Github, Briefcase, GraduationCap, Code } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function ProfessionalTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ const formatUrl = (url: string) => {
+ if (!url) return '';
+ return url.replace(/^https?:\/\/(www\.)?/, '').replace(/\/$/, '');
+ };
+
+ return (
+
+ {/* Personal Info */}
+
+
+
+ {personalInfo.fullName || 'Your Name'}
+
+ {personalInfo.title && (
+
+ {personalInfo.title}
+
+ )}
+
+
+
+ {personalInfo.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo.phone && (
+
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo.website && (
+
+
+ {formatUrl(personalInfo.website)}
+
+ )}
+ {personalInfo.linkedin && (
+
+
+ {formatUrl(personalInfo.linkedin)}
+
+ )}
+ {personalInfo.github && (
+
+
+ {formatUrl(personalInfo.github)}
+
+ )}
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+
+
+ Professional Summary
+
+
+
+ {summary}
+
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+
+ Professional Experience
+
+
+
+ {experience.map((exp) => (
+
+
+
+ {exp.jobTitle}
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+
+ {exp.company}{exp.location && ` β’ ${exp.location}`}
+
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ - {desc}
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+
+ Education
+
+
+
+ {education.map((edu) => (
+
+
+
+ {edu.degree}
+
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
+
+
+
+
+ {edu.school}{edu.location && ` β’ ${edu.location}`}
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+
+ Skills
+
+
+
+ {skills.map(skill => (
+ {skill.name}
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/TechTemplate.tsx b/src/components/resume-builder/templates/TechTemplate.tsx
new file mode 100644
index 0000000..f0ced95
--- /dev/null
+++ b/src/components/resume-builder/templates/TechTemplate.tsx
@@ -0,0 +1,293 @@
+import { Mail, Phone, MapPin, Globe, Linkedin, Github, Code, Cpu, Award, Briefcase, GraduationCap } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function TechTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, customization } = data || {};
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
+ };
+
+ return (
+
+ {/* Personal Info */}
+
+
+
+
+ {personalInfo.fullName || 'Your Name'}
+
+
+ {personalInfo.title || 'Software Engineer'}
+
+
+
+ {personalInfo.email && (
+
+
+ {personalInfo.email}
+
+ )}
+ {personalInfo.phone && (
+
+
+ {personalInfo.phone}
+
+ )}
+ {personalInfo.location && (
+
+
+ {personalInfo.location}
+
+ )}
+ {personalInfo.linkedin && (
+
+
+ LinkedIn
+
+ )}
+ {personalInfo.github && (
+
+
+ GitHub
+
+ )}
+ {personalInfo.website && (
+
+
+ Website
+
+ )}
+
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
+
+ Technical Profile
+
+
+ {summary}
+
+
+ )}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ Technical Skills
+
+
+ {skills.map((skill) => (
+
+
+
+ {skill.name}
+
+
+ {skill.level}
+
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+ Professional Experience
+
+
+ {experience.map((exp) => (
+
+
+
+
+ {exp.jobTitle}
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.description.filter(desc => desc.trim()).map((desc, index) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
+ {project.name}
+ {project.url && (
+
+ (View Project)
+
+ )}
+
+ {project.startDate && (
+
+ {formatDate(project.startDate)}
+ {project.endDate ? ` - ${formatDate(project.endDate)}` : ' - Present'}
+
+ )}
+
+
+ {project.description}
+
+ {project.technologies && project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, i) => (
+
+ {tech}
+
+ ))}
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+
+ {edu.degree}
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+
+ {edu.graduationDate ? formatDate(edu.graduationDate) : ''}
+
+
+ {edu.relevantCourses && edu.relevantCourses.length > 0 && (
+
+
+ Relevant Coursework:
+
+
+ {edu.relevantCourses.map((course, i) => (
+
+ {course}
+
+ ))}
+
+
+ )}
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
+ {cert.name}
+
+
+ {cert.issuer}
+
+
+ {formatDate(cert.date)}
+ {cert.expirationDate && ` - ${formatDate(cert.expirationDate)}`}
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/resume-builder/templates/TimelineTemplate.tsx b/src/components/resume-builder/templates/TimelineTemplate.tsx
new file mode 100644
index 0000000..cdf26da
--- /dev/null
+++ b/src/components/resume-builder/templates/TimelineTemplate.tsx
@@ -0,0 +1,248 @@
+import { Briefcase, GraduationCap, Code, Award, BookOpen, Star } from 'lucide-react';
+import { TemplateProps } from './types';
+
+export function TimelineTemplate({ data }: TemplateProps) {
+ const { personalInfo, summary, experience, education, skills, certifications, projects, publications, customization } = data || {};
+ const accentColor = customization?.accentColor || '#3b82f6';
+
+ const formatDate = (dateStr: string) => {
+ if (!dateStr) return '';
+ const date = new Date(dateStr + '-01');
+ return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short' });
+ };
+
+ return (
+
+ {/* Header */}
+
+
{personalInfo?.fullName}
+ {personalInfo?.title && (
+
{personalInfo.title}
+ )}
+
+ {personalInfo?.email && {personalInfo.email}}
+ {personalInfo?.phone && {personalInfo.phone}}
+ {personalInfo?.location && {personalInfo.location}}
+
+
+
+ {/* Summary */}
+ {summary && (
+
+
Professional Summary
+
{summary}
+
+ )}
+
+ {/* Timeline Section */}
+
+ {/* Timeline Line */}
+
+
+
+ {/* Experience */}
+ {experience && experience.length > 0 && (
+
+
+
+ Work Experience
+
+
+ {experience.map((exp) => (
+
+
+
+
+
{exp.jobTitle}
+
+ {formatDate(exp.startDate)} - {exp.isCurrentJob ? 'Present' : formatDate(exp.endDate)}
+
+
+
+ {exp.company}
+ {exp.location && ` β’ ${exp.location}`}
+
+
+ {exp.description.map((desc, idx) => (
+ -
+ β’
+ {desc}
+
+ ))}
+
+
+
+ ))}
+
+
+ )}
+
+ {/* Education */}
+ {education && education.length > 0 && (
+
+
+
+ Education
+
+
+ {education.map((edu) => (
+
+
+
+
+
{edu.degree}
+
+ {formatDate(edu.graduationDate)}
+
+
+
+ {edu.school}
+ {edu.location && `, ${edu.location}`}
+
+ {edu.gpa && (
+
+ GPA: {edu.gpa}
+
+ )}
+
+
+ ))}
+
+
+ )}
+
+ {/* Projects */}
+ {projects && projects.length > 0 && (
+
+
+
+ Projects
+
+
+ {projects.map((project) => (
+
+
+
+
{project.name}
+
{project.description}
+ {project.technologies && project.technologies.length > 0 && (
+
+ {project.technologies.map((tech, i) => (
+ {tech}
+ ))}
+
+ )}
+
+
+ ))}
+
+
+ )}
+
+ {/* Publications */}
+ {publications && publications.length > 0 && (
+
+
+
+ Publications
+
+
+ {publications.map((pub) => (
+
+
+
+
{pub.title}
+
+ {pub.journal}
+ {pub.publicationDate && ` β’ ${formatDate(pub.publicationDate)}`}
+
+
+ View Publication
+
+
+
+ ))}
+
+
+ )}
+
+
+
+ {/* Skills & Certifications */}
+
+ {/* Skills */}
+ {skills && skills.length > 0 && (
+
+
+
+ Skills
+
+
+ {skills.map((skill) => (
+
+ {skill.name}
+
+ ))}
+
+
+ )}
+
+ {/* Certifications */}
+ {certifications && certifications.length > 0 && (
+
+
+
+ Certifications
+
+
+ {certifications.map((cert) => (
+
+
{cert.name}
+
+ {cert.issuer} β’ {formatDate(cert.date)}
+
+
+ ))}
+
+
+ )}
+
+
+ );
+}
diff --git a/src/components/resume-builder/templates/types.ts b/src/components/resume-builder/templates/types.ts
new file mode 100644
index 0000000..6f36d51
--- /dev/null
+++ b/src/components/resume-builder/templates/types.ts
@@ -0,0 +1,58 @@
+import { ResumeData } from '@/types/resume';
+
+export interface TemplateProps {
+ data: ResumeData;
+}
+
+export interface TemplateSectionProps {
+ title: string;
+ className?: string;
+ children: React.ReactNode;
+}
+
+export interface ExperienceItemProps {
+ jobTitle: string;
+ company: string;
+ location?: string;
+ startDate: string;
+ endDate: string;
+ isCurrentJob: boolean;
+ description: string[];
+ className?: string;
+}
+
+export interface EducationItemProps {
+ degree: string;
+ school: string;
+ location?: string;
+ graduationDate: string;
+ fieldOfStudy?: string;
+ gpa?: string;
+ className?: string;
+}
+
+export interface SkillItemProps {
+ name: string;
+ level: 'Beginner' | 'Intermediate' | 'Advanced' | 'Expert';
+ className?: string;
+}
+
+export interface CertificationItemProps {
+ name: string;
+ issuer: string;
+ date: string;
+ expirationDate?: string;
+ className?: string;
+}
+
+export interface TemplateStyles {
+ fontFamily?: string;
+ primaryColor?: string;
+ secondaryColor?: string;
+ textColor?: string;
+ backgroundColor?: string;
+ spacing?: {
+ section?: string;
+ item?: string;
+ };
+}
diff --git a/src/components/resume-builder/types.ts b/src/components/resume-builder/types.ts
new file mode 100644
index 0000000..1506996
--- /dev/null
+++ b/src/components/resume-builder/types.ts
@@ -0,0 +1,21 @@
+import { TemplateProps as TemplateComponentProps } from './templates/types';
+
+export interface TemplateMeta {
+ id: string;
+ name: string;
+ description: string;
+ category: TemplateCategory;
+ previewImage?: string;
+ component: React.LazyExoticComponent<(props: TemplateComponentProps) => JSX.Element>;
+ tags?: string[];
+ atsFriendly: boolean;
+ lastUpdated: string;
+}
+
+export enum TemplateCategory {
+ PROFESSIONAL = 'Professional',
+ MODERN = 'Modern',
+ MINIMALIST = 'Minimalist',
+ CREATIVE = 'Creative',
+ SPECIALIZED = 'Specialized',
+}
diff --git a/src/components/tutorial/TutorialModal.tsx b/src/components/tutorial/TutorialModal.tsx
index c06403b..b08885c 100644
--- a/src/components/tutorial/TutorialModal.tsx
+++ b/src/components/tutorial/TutorialModal.tsx
@@ -1,7 +1,6 @@
-import React, { useState, useEffect } from 'react';
-import { Dialog, DialogContent } from '@/components/ui/dialog';
+import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
-import { X, ChevronLeft, ChevronRight, User, FileText, Briefcase, Palette, Save, Download } from 'lucide-react';
+import { X, ChevronLeft, ChevronRight, User, Palette, Save, Download } from 'lucide-react';
interface TutorialStep {
id: number;
diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx
index 1b7bc45..1c59433 100644
--- a/src/components/ui/calendar.tsx
+++ b/src/components/ui/calendar.tsx
@@ -58,8 +58,8 @@ function Calendar({
...classNames,
}}
components={{
- IconLeft: ({ ...props }) =>
,
- IconRight: ({ ...props }) =>
,
+ IconLeft: () =>
,
+ IconRight: () =>
,
}}
{...props}
/>
diff --git a/src/components/ui/chart.tsx b/src/components/ui/chart.tsx
index 13c1bd3..63d0845 100644
--- a/src/components/ui/chart.tsx
+++ b/src/components/ui/chart.tsx
@@ -1,10 +1,5 @@
import * as React from 'react';
import * as RechartsPrimitive from 'recharts';
-import {
- NameType,
- Payload,
- ValueType,
-} from 'recharts/types/component/DefaultTooltipContent';
import { cn } from '@/lib/utils';
diff --git a/src/contexts/ResumeContext.tsx b/src/contexts/ResumeContext.tsx
index 62e7bac..d037a5f 100644
--- a/src/contexts/ResumeContext.tsx
+++ b/src/contexts/ResumeContext.tsx
@@ -1,5 +1,5 @@
import React, { createContext, useContext, useReducer, useEffect, ReactNode } from 'react';
-import { ResumeData, ResumeSection, WorkExperience, Education, Skill, Certification, Project, Reference } from '@/types/resume';
+import { ResumeData, WorkExperience, Education, Skill, Certification, Project, Publication, Reference } from '@/types/resume';
interface ResumeState {
resumeData: ResumeData;
@@ -28,10 +28,12 @@ type ResumeAction =
| { type: 'ADD_PROJECT'; payload: Project }
| { type: 'UPDATE_PROJECT'; payload: { id: string; data: Partial
} }
| { type: 'DELETE_PROJECT'; payload: string }
+ | { type: 'ADD_PUBLICATION'; payload: Publication }
+ | { type: 'UPDATE_PUBLICATION'; payload: { id: string; data: Partial } }
+ | { type: 'DELETE_PUBLICATION'; payload: string }
| { type: 'ADD_REFERENCE'; payload: Reference }
| { type: 'UPDATE_REFERENCE'; payload: { id: string; data: Partial } }
| { type: 'DELETE_REFERENCE'; payload: string }
- | { type: 'REORDER_SECTIONS'; payload: ResumeSection[] }
| { type: 'UPDATE_TEMPLATE'; payload: ResumeData['template'] }
| { type: 'UPDATE_CUSTOMIZATION'; payload: Partial }
| { type: 'SET_LOADING'; payload: boolean }
@@ -201,6 +203,17 @@ const initialResumeData: ResumeData = {
endDate: "2022-01",
},
],
+ publications: [
+ {
+ id: "1",
+ title: "The Impact of Machine Learning on Software Development Lifecycles",
+ authors: ["Sarah Johnson", "John Doe"],
+ journal: "Journal of Computer Science",
+ publicationDate: "2022-10",
+ doi: "10.1234/jcs.2022.5678",
+ url: "https://example.com/publication1"
+ }
+ ],
references: [
{
id: "1",
@@ -230,53 +243,7 @@ const initialResumeData: ResumeData = {
relationship: "Academic Reference",
},
],
- sections: [
- {
- id: "1",
- type: "personalInfo",
- title: "Personal Information",
- isVisible: true,
- order: 1,
- },
- {
- id: "2",
- type: "summary",
- title: "Professional Summary",
- isVisible: true,
- order: 2,
- },
- {
- id: "3",
- type: "experience",
- title: "Work Experience",
- isVisible: true,
- order: 3,
- },
- {
- id: "4",
- type: "education",
- title: "Education",
- isVisible: true,
- order: 4,
- },
- { id: "5", type: "skills", title: "Skills", isVisible: true, order: 5 },
- {
- id: "6",
- type: "certifications",
- title: "Certifications",
- isVisible: true,
- order: 6,
- },
- { id: "7", type: "projects", title: "Projects", isVisible: true, order: 7 },
- {
- id: "8",
- type: "references",
- title: "References",
- isVisible: true,
- order: 8,
- },
- ],
- template: "minimal",
+ template: "minimalist",
customization: {
fontFamily: "Inter",
accentColor: "#3B82F6",
@@ -503,6 +470,38 @@ function resumeReducer(state: ResumeState, action: ResumeAction): ResumeState {
hasUnsavedChanges: true
};
+ case 'ADD_PUBLICATION':
+ return {
+ ...state,
+ resumeData: {
+ ...state.resumeData,
+ publications: [...state.resumeData.publications, action.payload]
+ },
+ hasUnsavedChanges: true
+ };
+
+ case 'UPDATE_PUBLICATION':
+ return {
+ ...state,
+ resumeData: {
+ ...state.resumeData,
+ publications: state.resumeData.publications.map(pub =>
+ pub.id === action.payload.id ? { ...pub, ...action.payload.data } : pub
+ )
+ },
+ hasUnsavedChanges: true
+ };
+
+ case 'DELETE_PUBLICATION':
+ return {
+ ...state,
+ resumeData: {
+ ...state.resumeData,
+ publications: state.resumeData.publications.filter(pub => pub.id !== action.payload)
+ },
+ hasUnsavedChanges: true
+ };
+
case 'ADD_REFERENCE':
return {
...state,
@@ -535,19 +534,19 @@ function resumeReducer(state: ResumeState, action: ResumeAction): ResumeState {
hasUnsavedChanges: true
};
- case 'REORDER_SECTIONS':
+ case 'UPDATE_TEMPLATE': {
+ // Ensure the template ID exists in the registry, otherwise fall back to 'clean-minimalist'
+ const templateId = typeof action.payload === 'string' ? action.payload : 'clean-minimalist';
+ console.log('Updating template to:', templateId);
return {
...state,
- resumeData: { ...state.resumeData, sections: action.payload },
- hasUnsavedChanges: true
- };
-
- case 'UPDATE_TEMPLATE':
- return {
- ...state,
- resumeData: { ...state.resumeData, template: action.payload },
+ resumeData: {
+ ...state.resumeData,
+ template: templateId
+ },
hasUnsavedChanges: true
};
+ }
case 'UPDATE_CUSTOMIZATION':
return {
diff --git a/src/contexts/ResumeData.tsx b/src/contexts/ResumeData.tsx
index fc0bf1f..733dea5 100644
--- a/src/contexts/ResumeData.tsx
+++ b/src/contexts/ResumeData.tsx
@@ -1,6 +1,6 @@
import { ResumeData } from '@/types/resume'
-const initialResumeData: ResumeData = {
+const initialData: ResumeData = {
personalInfo: {
fullName: "Sarah Johnson",
email: "sarah.johnson@email.com",
@@ -163,6 +163,7 @@ const initialResumeData: ResumeData = {
endDate: "2022-01",
},
],
+ publications: [],
references: [
{
id: "1",
@@ -192,53 +193,7 @@ const initialResumeData: ResumeData = {
relationship: "Academic Reference",
},
],
- sections: [
- {
- id: "1",
- type: "personalInfo",
- title: "Personal Information",
- isVisible: true,
- order: 1,
- },
- {
- id: "2",
- type: "summary",
- title: "Professional Summary",
- isVisible: true,
- order: 2,
- },
- {
- id: "3",
- type: "experience",
- title: "Work Experience",
- isVisible: true,
- order: 3,
- },
- {
- id: "4",
- type: "education",
- title: "Education",
- isVisible: true,
- order: 4,
- },
- { id: "5", type: "skills", title: "Skills", isVisible: true, order: 5 },
- {
- id: "6",
- type: "certifications",
- title: "Certifications",
- isVisible: true,
- order: 6,
- },
- { id: "7", type: "projects", title: "Projects", isVisible: true, order: 7 },
- {
- id: "8",
- type: "references",
- title: "References",
- isVisible: true,
- order: 8,
- },
- ],
- template: "minimal",
+ template: "clean-minimalist",
customization: {
fontFamily: "Inter",
accentColor: "#3B82F6",
@@ -246,4 +201,4 @@ const initialResumeData: ResumeData = {
},
};
-export default initialResumeData;
\ No newline at end of file
+export default initialData;
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
index 9e89c2d..322e97e 100644
--- a/src/index.css
+++ b/src/index.css
@@ -25,17 +25,17 @@
*::-webkit-scrollbar {
height: 5px;
width: 5px;
- background-color:#5f5f5f5b;
+ background-color:#788ca96c;
scale: 1;
}
*::-webkit-scrollbar-thumb {
- background-color:#6f6f6fc8;
- border-radius: 10px;
+ background-color:#67979552;
+ border-radius: 10px;
}
-
+s
*::-webkit-scrollbar-tracks {
- background-color:#545454;
+ background-color:#88abb967;
}
a {
@@ -172,6 +172,44 @@ button:focus-visible {
color: #fff;
}
+.resume-preview-header {
+ width: 100%;
+ display: block;
+ position: fixed;
+ z-index: 99;
+ padding-bottom: 25px;
+ margin-bottom: 25px;
+}
+
+/* Resume print styles */
+.resume-preview {
+ page-break-inside: avoid;
+ break-inside:
+ avoid;
+}
+
+#resume-preview h1,
+#resume-preview h2,
+#resume-preview h3,
+#resume-preview h4,
+#resume-preview h5,
+#resume-preview h6 {
+ page-break-after: avoid;
+ break-after: avoid;
+}
+
+#resume-preview p,
+#resume-preview li,
+#resume-preview div {
+ page-break-inside: avoid;
+ break-inside: avoid;
+}
+
+#resume-preview .break-inside-avoid {
+ page-break-inside: avoid;
+ break-inside: avoid;
+}
+
@media print {
.resume-preview {
margin: 20px;
@@ -179,4 +217,8 @@ button:focus-visible {
background: white !important;
page-break-inside: avoid;
}
+
+ #resume-preview {
+ box-shadow: none !important;
+ }
}
\ No newline at end of file
diff --git a/src/types/resume.ts b/src/types/resume.ts
index 3690c46..02f8138 100644
--- a/src/types/resume.ts
+++ b/src/types/resume.ts
@@ -1,5 +1,6 @@
export interface PersonalInfo {
fullName: string;
+ title?: string;
email: string;
phone: string;
location: string;
@@ -21,13 +22,15 @@ export interface WorkExperience {
}
export interface Education {
- id: string;
+ id:string;
degree: string;
school: string;
location: string;
graduationDate: string;
gpa?: string;
+ fieldOfStudy?: string;
relevantCourses?: string[];
+ achievements?: string[];
}
export interface Skill {
@@ -54,6 +57,16 @@ export interface Project {
endDate?: string;
}
+export interface Publication {
+ id: string;
+ title: string;
+ authors: string[];
+ journal: string;
+ publicationDate: string;
+ doi?: string;
+ url?: string;
+}
+
export interface Reference {
id: string;
name: string;
@@ -72,15 +85,8 @@ export type ResumeSectionType =
| 'skills'
| 'certifications'
| 'projects'
- | 'references';
-
-export interface ResumeSection {
- id: string;
- type: ResumeSectionType;
- title: string;
- isVisible: boolean;
- order: number;
-}
+ | 'references'
+ | 'publications';
export interface ResumeData {
id?: string;
@@ -91,9 +97,9 @@ export interface ResumeData {
skills: Skill[];
certifications: Certification[];
projects: Project[];
+ publications: Publication[];
references: Reference[];
- sections: ResumeSection[];
- template: 'minimal' | 'modern' | 'creative';
+ template: string; // Template IDs are now validated at runtime
customization: {
fontFamily: string;
accentColor: string;
diff --git a/src/utils/pdfGenerator.ts b/src/utils/pdfGenerator.ts
index 7eb7b23..ad65b75 100644
--- a/src/utils/pdfGenerator.ts
+++ b/src/utils/pdfGenerator.ts
@@ -16,15 +16,25 @@ export const generatePDF = async (
filename = 'resume.pdf',
quality = 2,
format = 'a4 || letter',
- margin = 14,
} = options;
try {
- // Find the resume element
- const element = document.getElementById(elementId);
- if (!element) {
+ // Find all page elements
+ const allPages = [];
+ const firstPage = document.getElementById(elementId);
+ if (!firstPage) {
throw new Error('Resume element not found');
}
+ allPages.push(firstPage);
+
+ // Find additional pages
+ let pageIndex = 2;
+ while (true) {
+ const nextPage = document.getElementById(`resume-preview-page-${pageIndex}`);
+ if (!nextPage) break;
+ allPages.push(nextPage);
+ pageIndex++;
+ }
// Show loading state
const loadingToast = document.createElement('div');
@@ -32,112 +42,50 @@ export const generatePDF = async (
loadingToast.className = 'fixed top-4 right-4 bg-blue-600 text-white px-4 py-2 rounded-lg shadow-lg z-50';
document.body.appendChild(loadingToast);
- // Configure canvas options for better quality
- const canvas = await html2canvas(element, {
- scale: quality * 2, // Higher scale for better quality
- useCORS: true,
- allowTaint: true,
- backgroundColor: '#ffffff',
- removeContainer: true,
- imageTimeout: 0,
- height: element.scrollHeight-50,
- width: element.scrollWidth,
- scrollX: 0,
- scrollY: 50
- });
-
// PDF dimensions in mm
- const pageWidth = format === 'a4' ? 200 : 206; // A4: 210mm, Letter: 216mm (8.5")
- const pageHeight = format === 'a4' ? 279 : 259; // A4: 297mm, Letter: 279mm (11")
-
- // Available space after margins
- const availableWidth = pageWidth - (margin * 2);
- const availableHeight = pageHeight - (margin * 2);
-
- // Convert canvas dimensions to mm (96 DPI to mm conversion)
- const canvasWidthMM = (canvas.width * 25.4) / (96 * quality * 2);
- const canvasHeightMM = (canvas.height * 25.4) / (96 * quality * 2);
-
- // Calculate scale to fit width
- const scale = availableWidth / canvasWidthMM;
- const scaledWidth = availableWidth;
- const scaledHeight = canvasHeightMM * scale;
+ const pageWidth = format === 'a4' ? 216 : 210;
+ const pageHeight = format === 'a4' ? 279 : 297;
// Create PDF
- const pdf = new jsPDF(options);
-
- // Convert canvas to image data
- const imgData = canvas.toDataURL('image/png', 2.0);
+ const pdf = new jsPDF({
+ orientation: 'portrait',
+ unit: 'mm',
+ format: format === 'a4' ? 'a4' : [pageWidth, pageHeight]
+ });
- // If content fits on one page
- if (scaledHeight <= availableHeight) {
+ // Process each page element
+ for (let i = 0; i < allPages.length; i++) {
+ const pageElement = allPages[i];
+
+ // Create canvas for this page
+ const pageCanvas = await html2canvas(pageElement, {
+ scale: quality,
+ useCORS: true,
+ allowTaint: true,
+ backgroundColor: '#ffffff',
+ removeContainer: true,
+ imageTimeout: 0,
+ width: pageElement.scrollWidth,
+ height: pageElement.scrollHeight
+ });
+
+ // Convert to image
+ const pageImgData = pageCanvas.toDataURL('image/png', 1.0);
+
+ // Add new page if not the first
+ if (i > 0) {
+ pdf.addPage();
+ }
+
+ // Add image to PDF (full page)
pdf.addImage(
- imgData,
- 'PNG',
- margin,
- margin,
- scaledWidth,
- scaledHeight,
- undefined,
- 'FAST'
+ pageImgData,
+ 'PNG',
+ 0,
+ 0,
+ pageWidth,
+ pageHeight
);
- } else {
- // Multi-page handling
- let remainingHeight = scaledHeight;
- let currentY = 0;
- let pageNumber = 0;
-
- while (remainingHeight > 0) {
- // Calculate the height for this page
- const pageContentHeight = Math.min(remainingHeight, availableHeight);
-
- // Calculate the source rectangle for this page
- const sourceY = (currentY / scaledHeight) * canvas.height;
- const sourceHeight = (pageContentHeight / scaledHeight) * canvas.height;
-
- // Create a canvas for this page section
- const pageCanvas = document.createElement('canvas');
- const pageCtx = pageCanvas.getContext('2d');
-
- pageCanvas.width = canvas.width;
- pageCanvas.height = sourceHeight;
-
- if (pageCtx) {
- // Fill with white background
- pageCtx.fillStyle = '#ffffff';
- pageCtx.fillRect(0, 0, pageCanvas.width, pageCanvas.height);
-
- // Draw the section of the original canvas
- pageCtx.drawImage(
- canvas,
- 0, sourceY, canvas.width, sourceHeight,
- 0, 0, pageCanvas.width, pageCanvas.height
- );
-
- // Add new page if not the first page
- if (pageNumber > 0) {
- pdf.addPage();
- }
-
- // Add the page image to PDF
- const pageImgData = pageCanvas.toDataURL('image/png', 2.0);
- pdf.addImage(
- pageImgData,
- 'PNG',
- margin,
- margin,
- scaledWidth,
- pageContentHeight,
- undefined,
- 'FAST'
- );
- }
-
- // Update for next page
- currentY += pageContentHeight;
- remainingHeight -= pageContentHeight;
- pageNumber++;
- }
}
// Save the PDF
@@ -183,6 +131,73 @@ export const generatePDF = async (
}
};
+export const generatePDFBlob = async (
+ elementId: string,
+ options: PDFOptions = {}
+): Promise => {
+ const {
+ quality = 2,
+ format = 'letter'
+ } = options;
+
+ // Find all page elements
+ const allPages = [];
+ const firstPage = document.getElementById(elementId);
+ if (!firstPage) {
+ throw new Error('Resume element not found');
+ }
+ allPages.push(firstPage);
+
+ let pageIndex = 2;
+ while (true) {
+ const nextPage = document.getElementById(`resume-preview-page-${pageIndex}`);
+ if (!nextPage) break;
+ allPages.push(nextPage);
+ pageIndex++;
+ }
+
+ const pageWidth = format === 'letter' ? 216 : 210;
+ const pageHeight = format === 'letter' ? 279 : 297;
+
+ const pdf = new jsPDF({
+ orientation: 'portrait',
+ unit: 'mm',
+ format: format === 'a4' ? 'a4' : [pageWidth, pageHeight]
+ });
+
+ for (let i = 0; i < allPages.length; i++) {
+ const pageElement = allPages[i];
+
+ const pageCanvas = await html2canvas(pageElement, {
+ scale: quality,
+ useCORS: true,
+ allowTaint: true,
+ backgroundColor: '#ffffff',
+ removeContainer: true,
+ imageTimeout: 0,
+ width: pageElement.scrollWidth,
+ height: pageElement.scrollHeight
+ });
+
+ const pageImgData = pageCanvas.toDataURL('image/png', 1.0);
+
+ if (i > 0) {
+ pdf.addPage();
+ }
+
+ pdf.addImage(
+ pageImgData,
+ 'PNG',
+ 0,
+ 0,
+ pageWidth,
+ pageHeight
+ );
+ }
+
+ return pdf.output('blob');
+};
+
export const generateResumeFilename = (fullName: string): string => {
const cleanName = fullName
.replace(/[^a-zA-Z0-9\s]/g, ' ') // Remove special characters
diff --git a/tsconfig.app.tsbuildinfo b/tsconfig.app.tsbuildinfo
new file mode 100644
index 0000000..0bb8c6b
--- /dev/null
+++ b/tsconfig.app.tsbuildinfo
@@ -0,0 +1 @@
+{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/userApi.ts","./src/components/CookieBanner.tsx","./src/components/Footer.tsx","./src/components/TestApi.tsx","./src/components/resume-builder/Header.tsx","./src/components/resume-builder/ResumeBuilder.tsx","./src/components/resume-builder/ResumeForm.tsx","./src/components/resume-builder/ResumePreview.tsx","./src/components/resume-builder/TemplatePreview.tsx","./src/components/resume-builder/TemplateSelector.tsx","./src/components/resume-builder/templateRegistry.ts","./src/components/resume-builder/types.ts","./src/components/resume-builder/form-sections/CertificationsForm.tsx","./src/components/resume-builder/form-sections/CustomizationForm.tsx","./src/components/resume-builder/form-sections/EducationForm.tsx","./src/components/resume-builder/form-sections/ExperienceForm.tsx","./src/components/resume-builder/form-sections/PersonalInfoForm.tsx","./src/components/resume-builder/form-sections/ProjectsForm.tsx","./src/components/resume-builder/form-sections/ReferencesForm.tsx","./src/components/resume-builder/form-sections/SkillsForm.tsx","./src/components/resume-builder/form-sections/SummaryForm.tsx","./src/components/resume-builder/templates/AcademicTemplate.tsx","./src/components/resume-builder/templates/BoldTemplate.tsx","./src/components/resume-builder/templates/CleanMinimalistTemplate.tsx","./src/components/resume-builder/templates/CleanProfessionalTemplate.tsx","./src/components/resume-builder/templates/CorporateTemplate.tsx","./src/components/resume-builder/templates/CreativeColorBlocksTemplate.tsx","./src/components/resume-builder/templates/CreativeTemplate.tsx","./src/components/resume-builder/templates/ElegantTemplate.tsx","./src/components/resume-builder/templates/ExecutiveTemplate.tsx","./src/components/resume-builder/templates/MinimalTemplate.tsx","./src/components/resume-builder/templates/MinimalistATS.tsx","./src/components/resume-builder/templates/MinimalistProfessionalTemplate.tsx","./src/components/resume-builder/templates/MinimalistSidebarTemplate.tsx","./src/components/resume-builder/templates/MinimalistTemplate.tsx","./src/components/resume-builder/templates/ModernDarkSidebarTemplate.tsx","./src/components/resume-builder/templates/ModernExecutiveTemplate.tsx","./src/components/resume-builder/templates/ModernProfessionalTemplate.tsx","./src/components/resume-builder/templates/ModernSidebarTemplate.tsx","./src/components/resume-builder/templates/ModernTemplate.tsx","./src/components/resume-builder/templates/ModernTimelineTemplate.tsx","./src/components/resume-builder/templates/ModernTwoColumn.tsx","./src/components/resume-builder/templates/ProfessionalBlueTemplate.tsx","./src/components/resume-builder/templates/ProfessionalSidebarTemplate.tsx","./src/components/resume-builder/templates/ProfessionalSummaryTemplate.tsx","./src/components/resume-builder/templates/ProfessionalTemplate.tsx","./src/components/resume-builder/templates/TechTemplate.tsx","./src/components/resume-builder/templates/TimelineTemplate.tsx","./src/components/resume-builder/templates/types.ts","./src/components/tutorial/TutorialModal.tsx","./src/components/ui/accordion.tsx","./src/components/ui/alert-dialog.tsx","./src/components/ui/alert.tsx","./src/components/ui/aspect-ratio.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/carousel.tsx","./src/components/ui/chart.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/command.tsx","./src/components/ui/context-menu.tsx","./src/components/ui/dialog.tsx","./src/components/ui/drawer.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/form.tsx","./src/components/ui/hover-card.tsx","./src/components/ui/input-otp.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/menubar.tsx","./src/components/ui/navigation-menu.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/progress.tsx","./src/components/ui/radio-group.tsx","./src/components/ui/resizable.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/sheet.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/slider.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/toast.tsx","./src/components/ui/toaster.tsx","./src/components/ui/toggle-group.tsx","./src/components/ui/toggle.tsx","./src/components/ui/tooltip.tsx","./src/contexts/ResumeContext.tsx","./src/contexts/ResumeData.tsx","./src/hooks/use-toast.ts","./src/lib/utils.ts","./src/types/resume.ts","./src/utils/fontLoader.ts","./src/utils/pdfGenerator.ts"],"version":"5.8.3"}
\ No newline at end of file
diff --git a/tsconfig.node.tsbuildinfo b/tsconfig.node.tsbuildinfo
new file mode 100644
index 0000000..3015526
--- /dev/null
+++ b/tsconfig.node.tsbuildinfo
@@ -0,0 +1 @@
+{"root":["./vite.config.ts"],"version":"5.8.3"}
\ No newline at end of file