Overview
Resume Builder provides two export formats:
PDF export via browser print functionality
JSON export for data backup and portability
Both features ensure your resume data is portable and can be shared or transferred between devices.
PDF Export
Export your resume as a PDF using the browser’s native print functionality.
How It Works
The PDF export button (~/workspace/source/src/routes/index.tsx:33) triggers the browser’s print dialog:
const handlePrint = () => {
window . print ();
};
return (
< Button onClick = { handlePrint } icon = {<Printer size = { 16 } /> } >
Export PDF
</ Button >
);
Source: ~/workspace/source/src/routes/index.tsx:33
Print Optimization
The app uses CSS classes to control what appears in the PDF:
Hide Editor UI:
< header className = "no-print" style = {{ marginBottom : 'var(--spacing-xl)' }} >
{ /* Editor controls - hidden in print */ }
</ header >
Show Full-Size Preview:
< div className = "print-only" style = {{ display : 'none' }} >
< Preview />
</ div >
Source: ~/workspace/source/src/routes/index.tsx:111
Click Export PDF
Click the “Export PDF” button in the header
Print Dialog Opens
Your browser’s print dialog will open
Configure Settings
Choose “Save as PDF” as the destination Recommended settings:
Paper size: A4
Margins: None
Background graphics: On
Save
Click Save to download your resume as a PDF
The PDF export uses your browser’s print functionality, which means the output quality depends on your browser. Chrome and Edge typically produce the best results.
JSON Export
Export your resume data as JSON for backup and portability.
Export Implementation
The ExportButton component (~/workspace/source/src/components/ExportButton.tsx:5) handles JSON export:
export const ExportButton = () => {
const { resumeData } = useResume ();
const handleExport = () => {
const dataStr = JSON . stringify ( resumeData , null , 2 );
const dataBlob = new Blob ([ dataStr ], { type: 'application/json' });
const url = URL . createObjectURL ( dataBlob );
const link = document . createElement ( 'a' );
link . href = url ;
link . download = `resume- ${ new Date (). toISOString (). split ( 'T' )[ 0 ] } .json` ;
document . body . appendChild ( link );
link . click ();
document . body . removeChild ( link );
URL . revokeObjectURL ( url );
};
return (
< Button
onClick = { handleExport }
variant = "outline"
size = "sm"
icon = {<Download size = { 14 } /> }
>
Export Data
</ Button >
);
};
Source: ~/workspace/source/src/components/ExportButton.tsx:5
Export Process
Serialize Data
Convert resume data to JSON string with formatting const dataStr = JSON . stringify ( resumeData , null , 2 );
Create Blob
Create a Blob with JSON content type const dataBlob = new Blob ([ dataStr ], { type: 'application/json' });
Generate Download
Create temporary download link with filename including current date link . download = `resume- ${ new Date (). toISOString (). split ( 'T' )[ 0 ] } .json` ;
Trigger Download
Programmatically click the link and clean up
Exported JSON Structure
The exported JSON file contains your complete resume data:
{
"personalInfo" : {
"fullName" : "John Doe" ,
"email" : "[email protected] " ,
"phone" : "+1 234 567 890" ,
"website" : "johndoe.com" ,
"linkedin" : "linkedin.com/in/johndoe" ,
"github" : "github.com/johndoe" ,
"location" : "New York, NY" ,
"jobTitle" : "Software Engineer"
},
"summary" : "Experienced software engineer..." ,
"experience" : [
{
"id" : "uuid-here" ,
"company" : "Tech Corp" ,
"position" : "Senior Developer" ,
"location" : "San Francisco, CA" ,
"startDate" : "2020-01" ,
"endDate" : "2024-03" ,
"current" : false ,
"description" : "Led development of..."
}
],
"education" : [ ... ],
"skills" : [ ... ],
"projects" : [ ... ],
"customSections" : [ ... ],
"sectionOrder" : [
"personal-info" ,
"summary" ,
"experience" ,
"projects" ,
"education" ,
"skills" ,
"customSections"
]
}
The filename automatically includes the current date (e.g., resume-2026-03-04.json) to help you track versions.
JSON Import
Restore your resume from a previously exported JSON file.
Import Implementation
The ImportButton component (~/workspace/source/src/components/ImportButton.tsx:7) handles JSON import:
export const ImportButton = () => {
const { setResumeData } = useResume ();
const fileInputRef = useRef < HTMLInputElement >( null );
const [ error , setError ] = useState < string | null >( null );
const handleImport = ( event : React . ChangeEvent < HTMLInputElement >) => {
const file = event . target . files ?.[ 0 ];
if ( ! file ) return ;
const reader = new FileReader ();
reader . onload = ( e ) => {
try {
const content = e . target ?. result as string ;
const data = JSON . parse ( content ) as ResumeData ;
// Basic validation
if ( ! data . personalInfo || ! data . experience || ! data . education ) {
throw new Error ( 'Invalid resume data format' );
}
// Migrate old data if needed
if ( data . sectionOrder && ! data . sectionOrder . includes ( 'personal-info' )) {
data . sectionOrder = [ 'personal-info' , ... data . sectionOrder ];
}
setResumeData ( data );
setError ( null );
alert ( 'Resume data imported successfully!' );
} catch ( err ) {
setError ( 'Failed to import: Invalid JSON format' );
console . error ( 'Import error:' , err );
alert ( 'Failed to import resume data. Please check the file format.' );
}
};
reader . readAsText ( file );
// Reset input
if ( fileInputRef . current ) {
fileInputRef . current . value = '' ;
}
};
return (
<>
< input
ref = { fileInputRef }
type = "file"
accept = ".json"
onChange = { handleImport }
style = {{ display : 'none' }}
/>
< Button
onClick = {() => fileInputRef.current?.click()}
variant = "outline"
size = "sm"
icon = {<Upload size = { 14 } /> }
>
Import Data
</ Button >
</>
);
};
Source: ~/workspace/source/src/components/ImportButton.tsx:7
Import Process
Select File
Click “Import Data” button to open file picker Only .json files are accepted
Read File
FileReader API reads the file contents as text const reader = new FileReader ();
reader . readAsText ( file );
Parse & Validate
Parse JSON and validate required fields exist const data = JSON . parse ( content ) as ResumeData ;
if ( ! data . personalInfo || ! data . experience || ! data . education ) {
throw new Error ( 'Invalid resume data format' );
}
Migrate Data
Apply any necessary migrations for older data formats if ( data . sectionOrder && ! data . sectionOrder . includes ( 'personal-info' )) {
data . sectionOrder = [ 'personal-info' , ... data . sectionOrder ];
}
Update State
Replace current resume data with imported data The auto-save mechanism immediately persists it to localStorage
Data Validation
The import function validates that the JSON contains the required structure:
personalInfo object must exist
experience array must exist
education array must exist
Other fields will use default values if missing.
Data Migration
The import process includes automatic migration for older data formats:
// Ensure personal-info is in sectionOrder
if ( data . sectionOrder && ! data . sectionOrder . includes ( 'personal-info' )) {
data . sectionOrder = [ 'personal-info' , ... data . sectionOrder ];
}
Source: ~/workspace/source/src/components/ImportButton.tsx:28
This ensures backward compatibility when the app’s data structure evolves.
Importing a JSON file will completely replace your current resume data. Make sure to export your current data first if you want to keep it.
Use Cases
Backup & Version Control
Regular Backups
Version Control
# Export your resume weekly
resume-2026-03-04.json
resume-2026-03-11.json
resume-2026-03-18.json
Cross-Device Transfer
Export JSON on Device A
Transfer file via email, cloud storage, or USB
Import JSON on Device B
Continue editing with all your data
Sharing Templates
Share your resume structure (without personal data) with others:
Export your resume
Edit the JSON to remove personal information
Share the template structure
Others can import and fill in their own data
Combine PDF export for sharing your resume with recruiters, and JSON export for maintaining backups and transferring between devices.
Error Handling
The import process includes comprehensive error handling:
Invalid JSON:
try {
const data = JSON . parse ( content ) as ResumeData ;
} catch ( err ) {
setError ( 'Failed to import: Invalid JSON format' );
alert ( 'Failed to import resume data. Please check the file format.' );
}
Missing Required Fields:
if ( ! data . personalInfo || ! data . experience || ! data . education ) {
throw new Error ( 'Invalid resume data format' );
}
Source: ~/workspace/source/src/components/ImportButton.tsx:23
Error messages are displayed both in the UI and via browser alerts to ensure users are aware of import failures.