You’ve been there before: someone asks you for a copy of your resume, so you do a quick search on your computer, you pull up a list of files, try to figure out which one is up to date, find it, then open it, see it’s in the wrong format, find the one in the right format, update that, save it and send it out. But future you will go through the same process unless you come up with a better way. Most people, if not most software developers, likely have a bunch of documents saved in various formats in various locations on their computer. If they’re organized, maybe it will be a list of documents in a single folder. But unless you’ve done the leg work up front, coming up with the right resume can look like this every time.

I’ve seen some attempts to combat this bad behavior and make the process easier for people to manage, mainly in the form of some service where you go and update your resume, which is then consumable in some way, shape or form. But then I have to remember what service I used three years ago to save my resume. Then I have to remember my credentials (if I’m smart, I’m using a password manager and this isn’t an issue). Then I have to log in, and go through the process of learning things again before finally coming up with the end product. I’ve also seen some static resume generators as well, but they suffer from most of the same problems.

So as I found myself going through this process for the nth time recently, I decided I was going to be a friend to future Scott and come up with a better way. I wanted a way to have a single source of truth (JSON, YAML, some kind of file that represents all the data for my resume), then a way to tie that to a template, and a way to generate the actual files that people actually ask for (generally, PDF, but also Markdown/HTML in certain cases). Before this, I was keeping my resume updated in Microsoft Word, which meant sending out a DOC/DOCX file, which people could monkey with, or I’d have to take the trouble to update the Word doc, then save it to PDF every time there’s some change to my resume — a process I don’t care to repeat. So, to avoid monkeying and arduous processes, I decided to use processes I use every day to keep an up-to-date resume in a way that’s easy to update, has instructions for future me, is publicly accessible (so I’m not sending things around as an attachment), and bonus, has revision history!

What resulted was a tiny bundle of technologies pulled from my everyday life: Gulp, Gulp libraries and Mustache templates.

That’s pretty much it.

Gulp is a toolkit to automate building processes, and has a very active community constantly generating helpful libraries, of which I use several:

gulp-clean To clean out my dist folder (generally when files are being regenerated).

gulp-html2pdf To take a generated HTML file and convert it to a PDF.

gulp-mustache To take Mustache templates and output them to whatever text-based format I need them in.

gulp-rename To be able to rename files after they’re generated.

And Mustache templates are extremely simple templates that allow you to inject data in from a JSON file.

The end result is a very simple process where I update my JSON resume (which is just structured data), then run npm run build on my local system and all of the files are generated for me. I then commit those locally and push them up to Github where they are publicly accessible.

Here’s an example of me adding a couple of small changes to my resume and pushing those up:

~/Documents/Resume master* ❯ git diff | cat diff --git a/src/data/resume.json b/src/data/resume.json index 41d6802..923b079 100644 --- a/src/data/resume.json +++ b/src/data/resume.json @@ -4,7 +4,7 @@ "email": "[email protected]", "phone": "949-209-9040", "website": "https://scottmw.com", - "about": "Scott has been programming since the age of 10 and has over 15 years of professional experience in web application development. While his focus has been mainly on PHP-based development platforms (Drupal, WordPress, Magento), more recently he has focused on the benefits of using Node.js+React in conjunction with REST API to create a much-improved, isomorphic experience for the end user that scales well. Outside of work, his interests run from writing short fiction to creating/improving open source projects.", + "about": "Scott has been programming since the age of 10 and has over 15 years of professional experience in web application development. While his focus has been mainly on PHP-based development platforms (WordPress, Magento, etc.), more recently he has focused on the benefits of using React and Redux in conjunction with REST API to create a much-improved experience for the end user that scales well. Outside of work, his interests run from writing short fiction to creating/improving open source projects.", "profiles": [ { "service": "Github", @@ -46,7 +46,7 @@ "skills": [ { "title": "Progamming Languages", - "items": "PHP7, JavaScript ES6/7, CSS, SASS, Stylus, HTML, Python, Ruby, MySQL" + "items": "PHP7, JavaScript ES6/ES7/Node.js, CSS, SASS, Stylus, HTML, Python, Ruby, MySQL" }, { "title": "Frameworks", ~/Documents/Resume master* ❯ git add src/data/resume.json ~/Documents/Resume master* ❯ git commit -m "Move Node.js to Programming skills" [master fdaccbe] Move Node.js to Programming skills 1 file changed, 2 insertions(+), 2 deletions(-) ~/Documents/Resume master ❯ npm run build > [email protected] build /Users/scott/Documents/Resume > gulp build [14:12:52] Using gulpfile ~/Documents/Resume/gulpfile.js [14:12:52] Starting 'build'... [14:12:52] Starting 'clean'... [14:12:52] Finished 'clean' after 7.86 ms [14:12:52] Starting 'html'... [14:12:52] Finished 'html' after 3.55 ms [14:12:52] Starting 'markdown'... [14:12:52] Starting 'pdf'... [14:12:52] Finished 'markdown' after 1.79 ms [14:12:52] Finished 'pdf' after 5.2 ms [14:12:52] Finished 'build' after 20 ms ~/Documents/Resume master* ❯ git add dist/ ~/Documents/Resume master* ❯ git commit -m "Add built files" [master 55b7274] Add built files 3 files changed, 2 insertions(+), 2 deletions(-) ~/Documents/Resume master ⇡ ❯ git push -u Enumerating objects: 11, done. Counting objects: 100% (11/11), done. Delta compression using up to 8 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 1.17 KiB | 1.17 MiB/s, done. Total 6 (delta 4), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (4/4), completed with 4 local objects. To github.com:tdlm/resume.git fdaccbe..55b7274 master -> master Branch 'master' set up to track remote branch 'master' from 'origin'.

If you aren’t used to working with any kind of Git-like source control, this might seem like a lot; if you’re used to it, however, you can probably see how this is just like your daily flow in a lot of ways, and it’s just a matter of changing the right files.

Another cool thing you can do with Gulp is watch for changes and perform actions afterward. In this example, I am updating my resume.json file in Visual Studio Code editor and changes are being “seen” by Gulp, which then re-generates the files several times as I edit:

~/Documents/Resume master ❯ npm run watch > [email protected] watch /Users/scott/Documents/Resume > gulp watcher [14:25:28] Using gulpfile ~/Documents/Resume/gulpfile.js [14:25:28] Starting 'watcher'... [14:25:28] Finished 'watcher' after 12 ms [14:29:52] Starting 'clean'... [14:29:52] Finished 'clean' after 9.33 ms [14:29:52] Starting 'html'... [14:29:52] Finished 'html' after 4.62 ms [14:29:52] Starting 'markdown'... [14:29:52] Starting 'pdf'... [14:29:52] Finished 'markdown' after 2.28 ms [14:29:52] Finished 'pdf' after 4.76 ms [14:30:50] Starting 'clean'... [14:30:50] Finished 'clean' after 2.17 ms [14:30:50] Starting 'html'... [14:30:50] Finished 'html' after 2.2 ms [14:30:50] Starting 'markdown'... [14:30:50] Starting 'pdf'... [14:30:50] Finished 'markdown' after 1.88 ms [14:30:50] Finished 'pdf' after 3.16 ms [14:32:05] Starting 'clean'... [14:32:05] Finished 'clean' after 1.87 ms [14:32:05] Starting 'html'... [14:32:05] Finished 'html' after 2.32 ms [14:32:05] Starting 'markdown'... [14:32:05] Starting 'pdf'... [14:32:05] Finished 'markdown' after 2.25 ms [14:32:05] Finished 'pdf' after 3.41 ms [14:32:27] Starting 'clean'... [14:32:27] Finished 'clean' after 2.45 ms [14:32:27] Starting 'html'... [14:32:27] Finished 'html' after 1.92 ms [14:32:27] Starting 'markdown'... [14:32:27] Starting 'pdf'... [14:32:27] Finished 'markdown' after 7.8 ms [14:32:27] Finished 'pdf' after 11 ms ^C ~/Documents/Resume master* 7m 37s ❯ git status On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: dist/scott-weaver_resume.html modified: dist/scott-weaver_resume.md modified: dist/scott-weaver_resume.pdf modified: src/data/resume.json no changes added to commit (use "git add" and/or "git commit -a") ~/Documents/Resume master* ❯ git add dist/ src/ ~/Documents/Resume master* ❯ git commit -m "Add gun.io experience" [master c013317] Add gun.io experience 4 files changed, 51 insertions(+) rewrite dist/scott-weaver_resume.pdf (63%) ~/Documents/Resume master ⇡ ❯ git push -u Enumerating objects: 17, done. Counting objects: 100% (17/17), done. Delta compression using up to 8 threads Compressing objects: 100% (8/8), done. Writing objects: 100% (9/9), 28.62 KiB | 14.31 MiB/s, done. Total 9 (delta 4), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (4/4), completed with 4 local objects. To github.com:tdlm/resume.git 901745a..c013317 master -> master Branch 'master' set up to track remote branch 'master' from 'origin'.

What this process lets me do is see changes as I make them; I make the change, hit save, then navigate to the file in Finder, open it in the appropriate app (Preview, Chrome, whatever) and I can instantly see the updated change in the appropriate style. Only when I am satisfied to I then commit the file up to the repo.

Of course, this is me using this the first time. The real test will come the next time I’m hunting for a job and need to pull up my latest resume. Hopefully the time it takes me to deliver the document is significantly lower. Another benefit I forgot to mention is that this way encourages me to list projects as I complete them rather than waiting to try and remember them at some later date!