EasyCV is a framework-free CV renderer that lets you maintain a single source of truth for your resume, publish it on the web, and produce a polished PDF using the browser's native print dialog.
- Single Source of Truth: Maintain one YAML file for both web and PDF versions—no more duplicate effort.
- Web-First: Publish your CV online with a clean URL, making it easy to share and update.
- Easier Than Word/LaTeX: Skip the tedious layout tweaks of word processors and LaTeX while still achieving professional results.
- Print-Ready Design: Browsers can convert web-based CV to high-quality PDFs by printing.
If you just want a fresh copy of EasyCV, the fastest path is the scaffolder:
npx create-easycv my-cv
cd my-cv
npm install
npm start
# Edit public/cv_data.yml to customize your CVThe generator pulls the latest main branch from this repository, strips build artifacts, and updates package.json with your project name. Because it shells out to git, make sure Git ≥2.0 is installed locally. Use npx create-easycv --help to see extra flags such as --ref <tag> (pin to a release), --repo <owner/name> (use your own fork), or --force (allow writing into a non-empty directory).
Already have a site (React, Vue, Astro, vanilla HTML, etc.)? Import the renderer, load your YAML, and mount it wherever you want.
-
Install dependencies
npm install easycv js-yaml
js-yamlis only needed if you load YAML in the browser (as shown below). Because your app imports it directly, keep it as a top-level dependency—package managers like pnpm will otherwise block access to transitive deps. If you provide the data as JSON or pre-parse it on the server, you can skipjs-yaml. -
Add your data
Place
cv_data.ymlin whatever folder your bundler copies to the web root (for example,public/). -
Render the CV
import { load as loadYaml } from "js-yaml"; import { renderCv } from "easycv"; async function mountCv() { const response = await fetch("/cv_data.yml"); const yaml = await response.text(); const data = loadYaml(yaml); // Accepts an element or any CSS selector renderCv("#cv-root", data, { titleTemplate: "%s — My CV", // optional actions: true, // show Back to Top + Download buttons }); } mountCv().catch((error) => { console.error("Failed to load CV data", error); });
The CSS and Font Awesome icons ship with the package, so importing renderCv automatically applies the correct styles.
If heavy customization is needed, you can fork this repository and modify the source code directly. After forking and cloning, run the following commands to start the development server:
npm install
npm startEasyCV renders your CV by walking a consistent hierarchy:
title: comes fromheader.nameplusheader.contact, giving the page banner and quick ways to reach you.section: each item insectionsdefines a top-level block such as Education or Publications.subsection: optional grouping inside a section; useful when you need multiple tables under a single heading. For example, Publications can have Conference Papers and Journal Articles as subsections.table: every section or subsection is rendered as a table so content and metadata stay aligned, even in condensed layouts.table entry: the smallest unit that describes one item in your CV, such as a job, degree, or publication. An entry has 3 parts: index, meta, and content. Index and meta are optional, but content is required. The content field supports multiple lines for rich descriptions. The first row of the content is the entry title (bold text), and subsequent rows are additional details or bullet points.
The public/cv_data.yml file stitches these pieces together. It starts with global metadata and then lists sections in the order they should appear:
version: 1
header:
name: "Ada Lovelace"
contact:
email: "[email protected]"
website: "ada.dev"
sections:
- id: experience
title: "Experience"
entries:
- content:
- "Analyst Programmer"
- "Analytical Engines Inc."
meta:
- "1843 - Present"
- id: publications
title: "Publications"
subsections:
- title: "Conference Papers"
entries:
- index: "1."
content:
- "On the Analytical Engine"
meta:
- "1843"This repository includes a GitHub Actions workflow that automatically builds and deploys your CV when you push to the main branch.
Setup Steps:
-
Fork the repository on GitHub
-
Update the homepage URL in
package.json:"homepage": "https://YOUR_USERNAME.github.io/webcv"
-
Enable GitHub Pages in your repository:
- Go to Settings → Pages
- Under Source, select GitHub Actions
-
Push your changes to the
mainbranch:git add . git commit -m "Update CV data" git push origin main
-
Access your CV at
https://YOUR_USERNAME.github.io/webcv
The GitHub Actions workflow (.github/workflows/deploy.yml) will automatically build and deploy your site on every push to main.
If you prefer manual deployment to GitHub Pages:
-
Build the project
npm run build:demo
-
Deploy the build folder
# Install gh-pages if you haven't already npm install -g gh-pages # Deploy to gh-pages branch gh-pages -d build
-
Enable GitHub Pages pointing to the
gh-pagesbranch
EasyCV can be deployed to any static hosting service:
- Netlify: Connect your GitHub repository and set the build command to
npm run build:demo - Vercel: Import your GitHub repository for automatic deployments
- AWS S3: Upload the contents of the
build/folder to an S3 bucket with static hosting enabled - Firebase Hosting: Use
firebase deployafter building
All CV content is stored in public/cv_data.yml. Here's a detailed example:
version: 1
header:
name: "Ada Lovelace"
tags:
- "Software Engineer"
- "London, UK"
contact:
phone:
value: "+44 20 1234 5678"
icon: "fa-solid fa-phone"
href: "tel:+442012345678"
display: true
email:
value: "[email protected]"
icon: "fa-solid fa-envelope"
href: "mailto:[email protected]"
display: true
website:
value: "ada.dev"
icon: "fa-solid fa-globe"
href: "https://ada.dev"
display: true
newTab: true
sections:
- id: experience
title: "Professional Experience"
entries:
- content:
- "**Senior Software Engineer**"
- "Analytical Engines Inc."
- "Led development of innovative computing solutions"
meta:
- "2020 - Present"
- "London, UK"
- id: education
title: "Education"
entries:
- content:
- "**BSc Computer Science**"
- "University of London"
meta:
- "2016 - 2020"
- id: publications
title: "Publications"
subsections:
- title: "Conference Papers"
entries:
- index: "1."
content:
- "Lovelace, A. (1843). *Notes on the Analytical Engine*. Scientific Memoirs."
meta:
- "1843"Key Features:
- HTML Support: Use
{html: "<strong>text</strong>"}for rich formatting - Icons: Use FontAwesome classes (e.g.,
fa-solid fa-phone) or image URLs - Links: Set
newTab: trueto open links in a new window - Condensed Layout: Add
condensed: trueto sections for compact display - Subsections: Group related entries under a common heading
Customize the visual appearance by editing src/App.css:
- Colors: Modify the color scheme (currently dark blue
#1d2f4b) - Typography: Adjust font families, sizes, and weights
- Spacing: Change margins, padding, and layout dimensions
- Print Styles: Customize the PDF output in the
@media printsection
Example color customization:
/* Change primary color from blue to green */
.header-title {
color: #2d5016; /* Was #1d2f4b */
}- Manual DOM control:
createCvElement(data, { actions: false })returns the fully rendered.cv-containernode so you can insert it into a shadow-root, virtual scroller, etc. - Custom document titles:
renderCv(container, data, { titleTemplate: "Résumé – %s" })changes how the<title>tag is generated. PasssetDocumentTitle: falseto opt out entirely. - Bring your own data: You are not limited to YAML. The renderer only cares about plain JavaScript objects that follow the schema shown above, so you can fetch JSON from an API, hydrate from CMS data, or generate it at build time.
The create-easycv/ directory contains the code that powers npx create-easycv. To publish a new version:
- Update
create-easycv/package.jsonwith the desired version - From the repository root, run:
cd create-easycv npm publish - Verify with
npx create-easycv --help
The CLI relies on git to download this repository, strips build artifacts (build/, dist/, node_modules/, etc.), and writes your chosen project name into package.json.
Issue: npm run build or npm run build:demo fails with errors
Solutions:
- Ensure Node.js 18+ is installed:
node --version - Delete
node_modulesand reinstall:rm -rf node_modules package-lock.json && npm install - Check for YAML syntax errors in
public/cv_data.ymlusing a YAML validator
Issue: CV doesn't load, or content appears broken
Solutions:
- Validate your YAML syntax at yamllint.com
- Ensure proper indentation (use spaces, not tabs)
- Check that all quotes are properly closed
- Verify array syntax uses hyphens for list items
Issue: Changes don't appear on the deployed site
Solutions:
- Check the Actions tab in GitHub to see if the workflow succeeded
- Verify the
homepagefield inpackage.jsonmatches your repository - Clear your browser cache or try incognito mode
- Wait a few minutes for GitHub's CDN to update
Issue: PDF doesn't look right when printing
Solutions:
- Use Chrome or Edge for best PDF export results
- In the print dialog, ensure:
- "Background graphics" is enabled
- Margins are set to "None" or "Minimum"
- Scale is set to 100%
- Customize print styles in
src/App.cssunder@media print
Contributions are welcome! Here's how you can help:
-
Fork the repository and create a feature branch
git checkout -b feature/my-improvement
-
Make your changes and test thoroughly
npm start # Dev server npm run build # Library bundle npm run build:demo # Static site bundle
-
Commit your changes with clear messages
git commit -m "Add feature: improved table layout" -
Push to your fork and submit a pull request
git push origin feature/my-improvement
Ideas for Contributions:
- Additional YAML examples or templates
- Improved styling or layout options
- Better print/PDF optimization
- Documentation improvements
- Bug fixes or performance enhancements
If EasyCV helps your project, please credit Yifan Sun and link back to this repository. A simple note such as "CV powered by EasyCV by Yifan Sun" in your README or site footer is perfect.
See LICENSE for details.