Skip to content
Colin Wren

Automating my Resume with HackMyResume & FRESH

JavaScript, Automation8 min read

resume review
Photo by Helloquence on Unsplash

As part of my Digital Spring Cleaning I decided to consolidate my various CV, Resumes and online profiles into one manageable document. I also wanted to automate as much of my CV & Resume as possible, making it easier to update and distribute, as it’s easier than my current process of using Adobe Illustrator and uploading a PDF.

After doing some research into the different formats and tools available for managing, generating and analysing resumes I settled on HackMyResume and FRESH. HackMyResume supports both JSONResume and FRESH but I decided to go with FRESH as it supports a lot more properties.

What is HackMyResume?

HackMyResume is a Node.JS tool that allows you to create, convert, validate and analyse JSONResume and FRESH format resumes, it also allows you to generate resume artefacts in a variety of formats using JSONResume themes or FRESH themes.

To get started with HackMyResume you can use the new command or point to an existing document. You can then run build to build the resume into an artefact using one of the themes or use analyze to get statistics on the keywords in the document as well as any gaps in your employment history.

The analysis of my resume was what initially drew me to HackMyResume as I could use this to ensure there were no gaps in my employment history as well as use the keyword analysis to ensure my resume highlighted the points I wanted potential employers to see.

An added bonus for me was that I could use the convert command to take the output of the tool I used to initially file out my resume, which took my LinkedIn profile and turned it into JSONResume and created a FRESH document.

Additionally as HackMyResume can use both JSONResume and HackMyResume themes it makes it the ideal tool for use with either format.

Why FRESH over JSONResume?

JSONResume is probably the most well-known of the two formats. There are multiple blog posts out there about it and there’s a lot of themes that enhance it.

When you visit the JSONResume website you’ll be advised to publish your CV to their web service, but this web service along with a number of tools in the JSONResume ecosystem just doesn’t seem to work, as they’re either running on old Node versions or the website gives you constant timeout errors.

HackMyResume isn’t much better on the website front as the fluentdesk website never resolves either; however, the actual tooling does work so this for me was the first step away from JSONResume.

Secondly if you compare the JSONResume and FRESH schemas the FRESH schema offers so much more. Both offer:

  • Basic information about the person
  • Online profiles
  • Employment history
  • Voluntary work
  • Education
  • Awards
  • Published works
  • Skills
  • Languages
  • Interests
  • References
  • Projects
  • Version control meta data

However FRESH has the following over JSONResume (at least at the time of writing)

  • Skills can be represented as a categorised list but also separate skills get their own entries (for more detailed skill lists)
  • ‘Published works’ is split into writing and speaking so you can add any conferences you spoke at
  • You can add your disposition towards travel and relocation as well as remote working
  • You can add testimonials as well as references so all those testimonials from LinkedIn don’t get mixed up with your list of people potential employers can contact
  • Projects and Samples are separated so you can have a more well defined set of samples to use and not just those linked to those made in employment
  • FRESH breaks out voluntary work into service and affiliation which makes recording work done for clubs and meetups easier
  • Pretty much everything in FRESH has both highlights and keywords while the use of highlights in JSONResume is reserved for a few properties

The highlights point for me is very important. In the UK we tend to use a single page document to summarise our employment history to potential employers so being able to record highlights makes the generation of bullet lists a lot easier.

Automating my Resume

I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it. — Bill Gates

One of the biggest issues I had with my previous set up was that once I’d decided on the skill set I wanted to have on my resume I then had to go and update my CV’s Adobe Illustrator document as well as the web version of my resume, then upload both to my website.

By using a combination of Github and Travis CI I was able to automate the validation, analysis and generation of both my CV and my resume as well as upload them, all just by making changes to the JSON document.

Using Git & Github to control my resume

I use Git every day at work so Git and Github are my go-to tools for version controlling anything non-binary.

I’m also a fan of feature branch development as the Pull Request used to merge everything back into the master or develop branch is a good reminder to critique the changes being made.

To make changes to my resume I create a feature branch, make the changes I want to update my resume with and then issue a Pull Request. I then let the ‘Checks’ tools that integrate with Github (in this case Travis CI) to indicate if the changes regress the quality of my resume before merging into my main branch if everything is OK.

If I then decide I want to publish a new version of my CV I create a git tag for that version. This is incase my changes to master branch don’t affect the final product they won’t trigger a re-upload, giving me better control over publishing my resume.

Using Travis CI to build and publish my resume

Travis CI is my go-to CI platform. I prefer it as it has a simple interface and the YAML format it uses allows for a lot flexibility (for instance my CV requires the Ubuntu font family which can installed using an apt-get command).

I have Travis set up to run HackMyResume’s validation and analysis tools on every commit so I can catch any issues quickly and rectify them.

I plan to eventually add a test suite that will use the output from the analysis to check that there’s no days added to the gap in my employment history and to also ensure that my keywords are portraying my experience in the manner I want it to.

There are a bunch of other tools I could have Travis run too, such as spelling and grammar checkers, reading age checkers and tone of my resume.

When a new git tag is created then Travis will run a script to generate the HTML version of my CV (which is a separate more streamlined JSON file) and the HTML version of my Resume.

I use a custom theme for my CV which is optimised for a single A4 sheet and as such I struggled with the default printing options for HackMyResume, so instead I have a separate script that uses Puppeteer to generate the PDF from my CVs HTML document.

Once both the PDF and HTML of my CV and Resume are generated I then use a script to upload both to my website. If any of the steps fail then the Travis build will turn red which allows me to clearly see I need to manually intervene.

Building a HackMyResume theme

My CV uses a custom theme based on my existing Adobe Illustrator document I’ve used for the past 6 years. In order to keep things consistent I used the same layout and typography rules for the CSS while using Puppeteer to print the PDF as it gave me more control than WKHTMLtoPDF or PhantomJS on how the final PDF looked.

Building a custom HackMyResume theme is super simple. There’s a FRESH-themes repository on Github you can fork and once you’ve duplicated the basis theme you can hack away to your hearts content.

Here’s a few tips:

  • There are separate HTML and CSS documents for generating the PDF and HTML outputs for themes so make sure you update the correct one
  • You can override partial templates by putting them in the partials folder and updating the main template to remove the sections/ part of the template call (this will then use the partials in your partials folder)
  • You can use {{{ to have HandleBars not escape characters, useful for apostrophes in organisation names
  • It’s best to base64 encode any images instead of link to them
  • You can supply the date format used by the dateRange function after the period, such as {{dateRange . 'YYYY'}} to force it to show only years (by default it shows year and month

PDF printing

Printing was probably the hardest part of HackMyResume to get correct for me. As I needed to keep my CV template to one sheet of A4 I had to have more advanced options for controlling the printing setup. Unfortunately the WKHTMLtoPDF and PhantomJS options currently offered by HackMyResume failed to deliver so I used Puppeteer to control a headless Chrome browser.

I’ll document my findings from using different print options here just in case it helps someone out.

To control the printing setup you’ll need to create a JSON document that will set out the options passed to HackMyResume. In this document you can define the engine used to print by declaring wkhtmltopdf or phantomjs under the pdf key.

If you use the wkhtmltopdf engine you can then define a new object under the wkhtmltopdf key which will contain the arguments passed to WKHTMLtoPDF. These can include:

  • Margins
  • Paper Size
  • Paper Orientation
  • Title to use for the PDF

Even with all the flexibility offered by the options you can define I found that WKHTMLtoPDF and PhantomJS didn’t support a lot of the flex-box rules and fonts I defined in my CSS.

I went with Puppeteer as it allows you to use the Chrome which already has great PDF printing support and supply a host of options to control the output, my final Puppeteer script looked like this:

1const puppeteer = require("puppeteer");
2 const path = require("path");
3 const filePath = path.resolve(__dirname, '../out/cv.html');
4 (async () => {
5 const browser = await puppeteer.launch();
6 const page = await browser.newPage();
7 await page.goto(`file:///${filePath}`);
8 await page.pdf({
9 path: "out/CV.pdf",
10 format: "A4",
11 printBackground: true,
12 displayHeaderFooter: false,
13 margin: {
14 top: "10mm",
15 left: "10mm",
16 right: "10mm",
17 bottom: "10mm"
18 }
19 });
20 await browser.close();
21 })();

This script essentially tells Chrome to open the HTML file of my CV and print the PDF without headers or footers and to print background images (as I use these for a set of custom list item bullet points)

Improvements I’d like to make

Automating the generation of my resume and CV is really just the first step I’ll be making towards a goal I have of making it easier for those working to keep their resume up to date instead of only doing it every three years when they look to change jobs.

I’m currently using a monthly reminder to remember to sit down and log my latest projects, skills and highlights at work but this could be handled so much better with a conversational interface such as a chat bot (this is something I’m actively looking to build).

The chatbot could utilise the feature branching system I’m using to issue a Pull Request once I’ve conversed with it leaving me to accept the changes when I review my Github Notifications. This gives me better control over what goes in and with Travis running checks against the commits I can see regressions.

Once I trust the chatbot’s updates enough I’ll look to release straight from master branch instead of git tags so I can have a continuous delivery pipeline for my resume and CV. As mentioned above though I’d want a lot more checks in place for this to happen.

Another integration I’ll be looking to do is to update my LinkedIn, Stack Overflow Developer Story and other sites as part of the release process so everything stays in sync and is consistent.

I’ll also be looking to build an interactive HTML resume template. All the themes I’ve seen so far are very much geared towards providing static printable websites. My use case is a little different, so by being able to use tools like React and D3.js to visualise my resume’s data would help me stand out.


Keeping things up to date can be a pain, so automating the analysis and generation of my resume and CV allows me to focus on just changing text.

Abstracting need to change code into conversational interface can make updating things a doddle and it wouldn’t feel like I’m updating my CV, just having a chat about work and my projects instead.

While HackMyResume is better than JSONResume, the printing options aren’t perfect so you might need to roll your own printing script to ensure you get the output you want.