CV Builder
A dynamic CV builder built with React 19 and Vite. Fill in your details across six sections, watch an A4 preview update in real time, and export a clean single-page PDF with one click via html2pdf.js.
- Scope
- BUILT
- Timeline
- March 2026
- Role
- Frontend Development
- Stack
- React 19Vitehtml2pdf.jsreact-iconsCSS
- Deployed on
- GitHub Pages
6
Editable sections
One-click export

Overview
The project
A dynamic CV builder, built as a self-directed practice project. You fill in six sections — personal info, education, experience, projects,
certificates, and skills / languages — and an A4 preview updates live as you type. When it looks
right, one click exports a clean, single-page PDF. Each repeatable section is an array in state
with add / edit / delete built on .map() and .filter(), and the PDF is generated directly from
the preview's DOM node via html2pdf.js rather than a screenshot, so the download stays crisp and
selectable. It's the project where lifting state up and managing dynamic lists in React finally
clicked for me.
What's inside
Features & pages
Personal & experience info
Capture name, contact, education, work history, projects, and certificates
Live A4 preview
The CV re-renders in real time as you edit, in an ATS-friendly semantic layout
One-click PDF export
Download a single-page A4 PDF generated straight from the HTML with html2pdf.js
Edit / preview toggle
Flip between an edit mode and a clean preview of the finished CV
What was hard
Challenges & solutions
Problem
Users add and remove any number of education, experience, and project entries, so the form couldn't rely on a fixed set of fields.
Solution
Held each section as an array in state and drove add / edit / delete with .map() and .filter(), giving every entry a stable id.
Problem
The CV had to download as a pixel-accurate single-page PDF — not a screenshot and not the browser's print dialog.
Solution
Targeted the preview node with a useRef and passed it to html2pdf.js to generate an A4 PDF on demand.
Problem
Edited values had to flow from the parent form state into child preview components and stay in sync.
Solution
Lifted state up to the App component and passed data and updater functions down as props, syncing local copies with useEffect where needed.
Built with
Tech stack
React 19
UI (Vite)
Vite
Build tool
html2pdf.js
PDF generation
react-icons
Icons
CSS
Styling (media queries)
GitHub Pages
Deployment (gh-pages)