
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@ewwmy/cv-builder
Advanced tools
💻 A CLI utility to generate a well-formatted CV in PDF format 📕 based on JSON CV data and a Handlebars template
💻 A CLI utility to generate a well-formatted CV in PDF format 📕 based on JSON CV data and a Handlebars template.
fs-extra for convenient filesystem interactionshandlebars as the template processormarked to provide Markdown supportpuppeteer to generate PDFssharp to preload and process imagesyargs to manage and process command-line arguments convenientlychokidar to provide file watchingtslog to make logging more pretty and functionalinversify to handle dependency injection and improve code modularity.This project was inspired by JSON Resume. The main idea of this project is to provide you a convenient way to store the information about your work experience, achievments, and other CV data separately from its representation, in multiple languages, in one place, and to easily generate good-looking multilingual CVs in PDF format in one command.
For example, you might get tired of managing multiple CV versions in office document files. You want to add a new record in your CV and you might get confused which version is more actual or you need to add this record into all the versions. This application solves that problem.
npm install -g @ewwmy/cv-builder
mkdir cv-builder
cd cv-builder
git clone git@github.com:ewwmy/cv-builder.git .
npm ci
npm install -g .
npm uninstall -g @ewwmy/cv-builder
Note: The application directory located at
~/.config/ewwmy/cv-builderand all its contents will be preserved.
After installation, the utility creates all the necessary files and folders in ~/.config/ewwmy/cv-builder.
They are:
icons: default base folder for icons (in case of relative paths); includes a set of common iconsimages: default base folder for images (in case of relative paths); includes an example AI-generated user phototemplates: default folder for templates; includes an example templatecv-example.json: example JSON CV dataout: default folder for generated PDF filessettings/settings.json: configuration file with the user preferences.When you run the program, it:
Once installed, you can call the utility from anywhere using cv-builder command.
You can run it immediately with no additional setup:
cv-builder
This builds the included example.
As a common practice for CLI utilities, you can also check the version or access helpful usage information:
cv-builder --version
cv-builder --help
Main command-line options:
-l, --locales: locales (languages) to build (e.g., -l en-US -l ru-RU or -l en-US ru-RU)-t, templates: template files to build without .hbs suffix (e.g., -t example -t main -t another-cool-template or -t example main another-cool-template)-i, --input: path to the JSON file with the data of your CV (e.g., -i /home/user/my-cv.json)-o, --output: directory for the built PDF files (e.g., -o /home/user/my-cv)-d, --templates-dir: directory for the templates (e.g., -o /home/user/my-cv-templates)-w, --watch: watch the CV JSON file and the templates directory for changes and rebuild PDFs when it changes (for live updates)Command-line options override settings defined in settings/settings.json. For detailed information about the configuration, please refer to the Default Configuration section.
If you accidentally misconfigure something, you can restore the default setup:
cv-builder --restore
Note:
cv-builder --restoredoes not overwrite existing files. To force overwrite, use:
cv-builder --restore --force
Default settings file:
~/.config/ewwmy/cv-builder/settings/settings.json. You should not move or rename it.
These are configuration options and their corresponding command-line options:
| Option | Command-line | Type | Description |
|---|---|---|---|
LOCALES | -l, --locales | array | Locales (languages) to build |
TEMPLATES | -t, templates | array | Template files to build (omit the .hbs extension) |
INPUT_CV_FILE_PATH | -i, --input | string | Path to the JSON file containing CV data |
OUTPUT_DIR | -o, --output | string | Directory for the generated PDF files |
TEMPLATES_DIR | -d, --templates-dir | string | Directory containing the templates |
BASE_IMAGES_DIR | --images-base-dir | string | Base directory for relative image paths in the JSON CV data |
BASE_ICONS_DIR | --icons-base-dir | string | Base directory for relative icon paths in the JSON CV data |
The example file at
~/.config/ewwmy/cv-builder/cv-example.jsonis used by default. It demonstrates all features and provides a template for organizing your data. It's highly recommended to explore it.
You can create any structure, use any valid JSON data, but some field names are reserved for specific features. Refer to the Features Overview section for details.
CV Builder uses the Handlebars template engine and includes a couple of templates out of the box:
default.hbs — a basic template that demonstrates most of the features.international-strict.hbs — a template which is considered one of the best for IT specialists in 2025 (looks similar to well-known Jake's Resume).By default they're both on. Default location of the templates: ~/.config/ewwmy/cv-builder/templates.
You can create as many templates as needed. Template files must have the .hbs extension. Specify templates you need to generate PDF with in the TEMPLATES setting or via command-line options. Similarly, the directory for templates can be configured via the TEMPLATES_DIR setting or command-line options.
Please, refer to the Handlebars Guide for more information on using Handlebars.
Note: The options provided via command-line override the options from the
settings/settings.jsonconfiguration file.
The -w (--watch) option can be used to watch the CV JSON file and the templates directory for changes and rebuild PDFs when they change. This is useful for live updates (e.g., to develop templates, or to monitor changes in the JSON data).
You can use additional logical operators, such as eq, ne, lt, gt, lte, gte, and, or to make your templates much more flexible:
{{#if (eq foo "bar")}} → if (foo === "bar"){{#if (ne foo "bar")}} → if (foo !== "bar"){{#if (lt foo 3)}} → if (foo < 3){{#if (gt foo 3)}} → if (foo > 3){{#if (lte foo 3)}} → if (foo <= 3){{#if (gte foo 3)}} → if (foo >= 3){{#if (and (eq foo "bar") (lt baz 10))}} → if (foo === "bar" && baz < 10){{#if (or (eq foo "bar") (lt baz 10))}} → if (foo === "bar" || baz < 10)The content will only show if either section1 or section2 is present:
{{#if (or section1 section2)}}
{{content}}
{{/if}}
The content will only show if either section1 === "foo" or section2 !== "bar":
{{#if (or (eq section1 "foo") (ne section2 "bar"))}}
{{content}}
{{/if}}
{{#each data.experience}}
{{#if (lt @index 3)}}
{{!-- Show only 3 latest jobs --}}
{{/if}}
{{/each}}
You can use @first and @last aliases in templates to refer the first and the last array elements accordingly.
{{#each data.certificates}}
{{#if @first}}
{{!-- Show the latest certificate only --}}
{{/if}}
{{/each}}
You can use Markdown anywhere in your JSON data. To render Markdown in templates, use the {{markdown}} helper.
{
"description": "This is **bold** and _italic_"
}
{{markdown description}}
Note: The
markdownis the special helper name and thedescriptionrefers to the name of the JSON field.
To include an image, use a specific JSON structure and the {{{image}}} helper in the template.
{
"profilePicture": {
"type": "image",
"path": "profile.jpg",
"scale": 0.5
}
}
type: required; must be "image"path: required; relative to the base image folder or an absolute pathscale: optional; reduces image size; defaults to 1; useful if the original image is too large and can cause aliasing while{{{image profilePicture width='150px' height='150px' roundness=1}}}
width: optional; a valid CSS value for the resulting image in the generated PDFheight: optional; a valid CSS value for the resulting image in the generated PDFroundness: optional; defaults to 0 which means no roundness; 1 means an ideal circle.Note: The
imageis the special helper name and theprofilePicturerefers to the name of the JSON field.
Icons are loaded from SVG files. Use the icon field in your JSON and the {{{icon}}} helper in a template.
{
"social": {
"icon": "linkedin-logo.svg"
}
}
The path must be either absolute or relative to the base icons directory which is specified in the configuration or command-line.
{{{icon social.icon}}}
You can include translations for any field in JSON using locale keys (e.g., en, ru). Specify the locales when building the CV or set up the default locales in the configuration.
The locale determines which translation is used. If you have 2 translations in your JSON (e.g., en, ru) and specify both in the configuration or in command-line, it will create 2 PDF files with each translation provided.
{
"greeting": {
"en": "Hello",
"ru": "Привет"
}
}
{{greeting}}
Dates are formatted based on the specified locale. Use the {{date}} helper for pretty printing (year and month). Use the {{year}} helper to extract the year only from a date.
{
"startedAt": "2020-12-31"
}
The date must be in YYYY-MM-DD format.
Typical date:
{{date startedAt}}
Year only:
{{year startedAt}}
Any object with the property "hidden": true will be excluded from the output, even if it's called from a template, ensuring it never passes to the output. You can use it to safely store your notes (e.g., comments) in your JSON data that should never be visible in the result PDF.
{
"value": "Hidden text",
"hidden": true
}
It's especially useful in arrays to exclude some elements:
[
{
"email": "user@example.com"
},
{
"phone": "+0 (123) 456-78-90",
"hidden": true
}
]
FAQs
💻 A CLI utility to generate a well-formatted CV in PDF format 📕 based on JSON CV data and a Handlebars template
We found that @ewwmy/cv-builder demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.