Home /dev/
CV Builder
React App
The Odin Project
Live
Mar 23, 2026

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. Built as part of The Odin Project React curriculum.

Timeline

March 2026

Role

Frontend Development

Deployed on

GitHub Pages

Stack

React 19

Vite

html2pdf.js

react-icons

CSS

6

Editable sections

PDF

One-click export

CV Builder preview

Preview

project description

Overview

A dynamic CV builder built as part of The Odin Project React curriculum. 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

Problems solved

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)

More work

Other dev projects