Racheal Ehiwe
Back to portfolio

Case Study · 01

Smart CV Path-folio

An AI-powered CV/resume platform designed to help users create structured, ATS-oriented CVs through a guided workflow.

React · Node.js · Express · PostgreSQL · Gemini AI · Netlify Functions

Features

multi-step guided formAI-assisted CV generationstructured datadata normalizationvalidationfallback handlingeditable CV outputCV previewPDF generationATS-oriented structurereusable React componentspersistence
Team repository on GitHub

The problem

Most people do not fail interviews because they lack experience — they fail earlier, because their CV is unstructured, inconsistent and unreadable to applicant tracking systems.

Smart CV Path-folio set out to turn CV writing into a guided workflow: collect structured information from the user, use generative AI to draft strong, role-relevant content, and render it into a clean, ATS-oriented document the user can still edit and control.

Architecture

A React frontend drives a multi-step guided form. Each step captures a well-defined slice of the CV (profile, experience, education, skills, projects) and writes into one normalized CV data object rather than free-form text.

A Node.js/Express API — deployed as Netlify Functions — mediates every AI call. Gemini AI is never called directly from the browser: the server owns prompt construction, model access and response parsing. PostgreSQL persists user CV data so a session can be resumed and multiple CV versions maintained.

The contract between layers is the normalized CV schema. Everything — AI output, manual edits, preview rendering and PDF generation — reads and writes that same shape.

Engineering decisions

Structured data over generated prose: AI returns data that maps to the schema, not a finished document. That makes output editable, comparable and renderable in more than one template.

Normalization and validation at the boundary: AI responses are parsed, coerced and validated before they reach the UI, with fallback handling when the model returns partial or malformed output so the app degrades instead of breaking.

Server-owned AI: keys, prompts and parsing stay behind the API. The client stays a rendering and editing surface.

Reusable React components: CV sections are composed from small components so the same data can render in edit mode, preview mode and print.

The CVPreview challenge

CVPreview was the component I spent several months developing and refining, and it was by far the hardest part of the project.

It has to be two things at once: an editable surface and a faithful preview of the printed document. Toggling between editable and preview modes without losing state, focus or formatting required careful separation between the data model and the rendered layout.

It has to survive real data. Missing sections, empty arrays, very long job titles, inconsistent dates and partially generated AI output all had to render sensibly rather than crash or produce a broken page.

It has to print. Browser print and PDF generation behave differently from screen rendering: page breaks, margins, fonts, colours and spacing all needed explicit handling so the exported CV matched the preview the user approved.

The solution

I refactored CVPreview from one large component into a composition of section components driven by the normalized schema, with a single mode flag controlling editable versus preview rendering.

Validation and defaulting moved upstream so the component could assume a predictable shape. Print-specific styling was made explicit rather than inherited, and PDF output was tested against the same data variations that had previously broken the layout.

Lessons learned

Design the data contract before the UI. Once the schema was stable, every other problem became smaller.

Treat AI output as untrusted input. Validation, normalization and fallbacks are the difference between a demo and a product.

Preview and print are separate rendering targets, and pretending otherwise costs weeks.

Persistence changes user behaviour: being able to return to a draft is what makes the guided workflow usable at all.