A Curriculum Vitae LaTeX Typesetting Automation Adventure with Gitlab

Dimitrie
13 min readMay 25, 2016

--

Gitlab Repository

A personal résumé or CV is something everybody needs. Preferably it should be catered to the job opening you are going to apply for, plus it needs to be your way in. So it should be done well…

You start the process of selecting which program to use, which template to use or design, where to keep it backed up, etc, etc. Maybe you already have one? Even then, there is still the process of keeping it up to date! Not a simple task, even worse if you’re helping someone close to you.

So I began my journey working on my own résumé. Recently I had helped out a close relative with hers and now it was my turn. This process could — no should be improved if I want to help myself and others!

As a “product designer” leaning towards the technical side of approaching problems I am no stranger to the command line. Add to that, someone who is in love with beautiful typography, elegant interfaces, being up to date and geeking out on shiny new software.

So I once came about an open source project called LaTeX Boilerplates from Mattia Tezzele. This was a good excuse to let me dive into the guts of LaTeX and see if this could satisfy my CV Typography needs.

Note that Mattia Tezzele derived his project from Dario Taraborelli’s Typesetting your academic CV in LaTeX. We all start somewhere!

The LaTeX boilerplates would solve multiple problems. Namely content and markup abstraction, versioning in combination with git and last but not least, expert typesetting.

In short, the LaTeX boilerplates rely on Pandoc to stitch together a pdf out of a LaTeX template and a yaml content file. LaTeX itself is a high-quality typesetting system and because it’s not a word processor, but a markup language, it can be versioned with git.

Only the last piece of the puzzle uhh— pipeline was missing, auto generating the pdf output. And just because we were tinkering anyway, the template could use an upgrade with missing functions & features.

LaTeX meet Continuous Integration

Working with git we can make use of Gitlab which offers free private repositories, which are perfect for handling a project containing personal information. However versioning and backup is not the only thing Gitlab has to offer!

We can leverage Gitlab’s continuous integration to auto generate our pdf’s after each commit. A grand feature that makes use of a Docker image to create a container to compile the code.

The public repository I created for this project leverages the same functionality to output the pdf’s to Gitlab pages, so they are reachable by a web url.

So in steps:

1.I created a Docker image called “strages/pandoc-docker” based upon James Gregory’s Pandoc Docker image. As James’ image does not hold all needed LaTeX packages, I needed an image that was more complete.

The added benefit of this was, I now had a perfect local development environment, which I could startup in the local git repository with:

docker run -it -v `pwd`:/source strages/pandoc-docker

2.Gitlab CI needs a “.gitlab-ci.yml” file to configure what should happen. It downloads and runs the Docker image I previously built and uploaded to the Docker Hub. Then it copies the fonts from the“fonts” directory into the system image’s one, after which it needs to update the font cache in order for it to work. Lastly the makefile is called.

image: strages/pandoc-docker

pages:
script:
- cp fonts/* /usr/share/fonts/
- fc-cache -f -v
- echo "fonts are installed"
- make
- echo "pdf generated, well done machine!"
artifacts:
paths:
- public

3.The makefile is changed to generate a pdf out of each yaml file in the directory called “public”. This is done in order to facilitate generating CV’s for each company or language, plus the directory name is a requirement for Gitlab Pages to work.

Note that the “.gitlab-ci.yml” is a hidden file due to the dot preceding the filename. This will not trigger the script!

4.The last thing that wasn’t configured correctly yet, was the content abstraction. For example the section titles were still in the LaTeX template instead of the yaml content file. This was key for users only having to edit the yaml files, which makes sense.

Ultimately the following is the output of this endeavour. For a better look at the pdf go here.

Up next is a better look at its features and typesetting qualities!

What makes a good CV?

That is a good question, which is also quite opinionated. Many jobs require subtle changes to the order of information, what kind of information and how detailed some of it should be.

Note that this article does not go in on the language to be used in writing a CV!

However the result of this project can be manipulated by its users to whatever degree they so desire. Though I think this template does provide a stable basis for each profession.

The real way to approach this problem is to think like someone who may hire you. What does he or she wants to know and in what order? Consolidate all of your information into a package consisting out of only the most important. Converting this information onto (digital) paper correctly all comes down to the features of your résumé.

Important information should be on the first page

This is of course a given, but I have narrowed it down to 4 sections:

  • Personal information

Consisting out of: Name, Title, Address, Birthdate, Contact Information, Online Presence and a photo to make it personal. We are human after all.

  • Introduction

Describe yourself, give the reader an insight to who you are and what you do. Keep it short, this should not be your cover letter. Lure your audience in to knowing more about you.

  • Skills, Area’s of Interests and Projects

Your skills, competencies or area’s of interests regarding the job you are going to apply for. Note them down, but don’t go into detail. These are things you can discuss in an interview. It is important to know for a company what you a capable of and with what tools you like to work.

As for projects:

This way you can list things you’ve accomplished without needing to associate them with a class or company. I however discourage detailed descriptions of these projects. Titles should be eye catching and be used for inspiration of talking points during the interview.

Probinso on HN

  • Last Job Experience

Job experience should be summed up with the most recent one placed on top. When all information of the previous 3 sections is filled out, one or two of your last jobs should snuggly fit in on the first page.

All other information can go to a secondary page, but try to keep it that way.

Never print double sided

You may never know if people will print out your résumé. Let’s not take the chance that someone will look over your secondary page.

The LaTeX template will never give out a pdf that is configured that way due to:

\documentclass[$fontsize$, a4paper, oneside]{article}

Page numbering formatting

Another hint we can give so the reader isn’t missing out on information is the page numbering. It’s formatted with:

“Lastname” Résumé — Page 1 of 2

This way it’s always clear where exactly we are in the process of reviewing this document. The “Lastname” part makes it easy by reminding the reader who we are again.

Contact details bottom page margin

Apart from your last name, at any given moment such a person could decide to contact you. Now they can, immediately, on whichever page they are with only the bare essentials: “phone or email”.

Second page sections

Speaking of the second page, it will hold all secondary information as noted before. However out of which sections should it consist?

Note that every section is optional, even the intro, projects or education section. Just “Toggle comments” on the whole section inside the yaml file, which basically means putting a “#” for each line. This is possible due to the sections built up by using Pandoc if statements in this way:

$if(projects)$
\subsection*{$projectstitle$}
\begin{itemize}
$for(projects)$
\item $projects$
$endfor$
\end{itemize}
$endif$
  • Business and Other Work Experience sections

Apart from your regular job experiences, it can be that you have experience in a field that is of less importance. If this is still valuable to put it in, it can now be put under “Other Work Experience”.

Note that when starting out your career, it is best to note it all under one work experience section.

  • Education section

Speaks for itself

Note that it is possible to jot down only one year, instead of an ending year aswell.

  • Endorsements section

Endorsements can be a big deal. Some expert in your field you have worked together with can vouch for you and give you a special recommendation. Put it in! Otherwise “Toggle comments” on the whole section, nifty!

  • Extra Information section

You may have other information not to be noted elsewhere. An example is your drivers license, your availability in the coming months, special circumstances or some other detail that your future employer needs to know.

A circle clipped round photo? But I don’t even…

To make this job easy, LaTeX and I automatically round clip your image by using:

\usepackage[skins]{tcolorbox}
\begin{tikzpicture}
\node[circle,inner sep=.85cm,fill overzoom image=$photo$] (A) {};
\end{tikzpicture}

Note that it is best to have a square image as input, so you know where your image center is.

Page colour

This one is more for fun, and should be used sparingly. You don’t want to come over as “trying to hard” by using a strange page colour. Plus you never know if your résumé reviewer will be printing it out, which will most likely result in a white border around your fancy page background colour. Although for digital it can give that stylish “old style” look.

Note that if you want a page colour and you’ll print it out yourself, it is recommended to buy coloured paper instead.

So we have quite a few features that improve upon the regular CV. Now let’s go for that extra edge:

Excellent Typography

LaTeX resumes can be considered to be a secret handshake of sorts, something that makes me significantly more likely to be inclined to hire a candidate.
zackelan on HN

One of the best qualities of LaTeX is the actual typesetting. You can be very precise and get a consistent result out of it every time. All the more reason to get into the typography features, which follow best practices from the experts!

Expert font

Let’s begin by stating that this document is optimised for “Linux Libertine O” . Its fonts are published under the terms of the GPL and OFL, so we can freely use them and distribute them under the same name.

Actually, “Linux Libertine O” is included in the docker image through the texlive-full package. However for making local development easy they are added to the repository.

Other fonts that I have considered are Hoefler Text, OFL Sorts Mill Goudy, Sabon LT Std and Cardo.

All have extended opentype features, such as small capitals, ligatures, kerning, Capital spacing etc. The features “Linux Libertine O” offers are for example:

Note this is generated by using LCDF Type Software

$ oftinfo -f fonts/LinLibertine_R.otfaalt Access All Alternates
c2sc Small Capitals From Capitals
case Case-Sensitive Forms
ccmp Glyph Composition/Decomposition
cpsp Capital Spacing
dlig Discretionary Ligatures
fina Terminal Forms
frac Fractions
hlig Historical Ligatures
kern Kerning
lfbd Left Bounds
liga Standard Ligatures
lnum Lining Figures
mark Mark Positioning
mkmk Mark to Mark Positioning
nalt Alternate Annotation Forms
onum Oldstyle Figures
pnum Proportional Figures
rtbd Right Bounds
salt Stylistic Alternates
sinf Scientific Inferiors
smcp Small Capitals
ss01 Stylistic Set 1
ss02 Stylistic Set 2
ss03 Stylistic Set 3
ss04 Stylistic Set 4
ss05 Stylistic Set 5
ss06 Stylistic Set 6
sups Superscript
tnum Tabular Figures
zero Slashed Zero

However for a project such as this, they should be freely usable and some of those are not. Hoefler Text and Sabon for example. Of which Sabon really is something else! Lovely typeface by Jan Tschichold, which was an expert typographer. I can recommend picking up The Form of the Book: Essays on the Morality of Good Design, but I digress…

Others were free, but I simply preferred this one above the others. Its a font thats relied on by the likes of Wikipedia and is used widely in the LaTeX community. Plus it has support for many languages.

If you so desire it is possible to use your own selected fonts, by putting them in the “fonts” directory. Use otf font files and call upon those from within the yaml file.

So now quite a few of those open type features you almost never see, are used throughout the résumé, by using:

\setromanfont [Ligatures={Common, Rare, Historic}, Numbers={OldStyle}, RawFeature={+ss02,+ss04,+ss05}]{$mainfont$}

Note that they are used according to what’s practical (what works) and known best practices.

(Discretionary) Ligatures are among my favourites. I love how they come out in my name:

Old style numerals work well together with small capitals. True italics are a simply beautiful way to emphasise. Em-dashes and en-dashes, also called mutton- and nut dashes, can and are used accordingly. Plus there is this gorgeous (italic) ampersand:

Which is made possible by activating small capitals or using “/amper” due to:

\makeatletter
\DeclareRobustCommand{\amper}{%
\texorpdfstring{%
\begingroup
\ifx\f@shape\scname
\smaller[1.2]%
\fi
\char”E050
\endgroup
}{\&}\xspace
}
\makeatother

Single and double curly opening and closing quotes based on language are activated by using the polyglossia package.

Hanging punctuation in the endorsement quotes by using “\andIquote” due to:

\def\andIquote{\makebox[0pt][r]{``}}

Not all thing worked out immediately as I tried out quote line indents. Ultimately they were not necessary and proved to be “not beautiful” as I tried it with the following code:

% \setlength{\tabcolsep}{.675em}
% {\small\item[]\hspace{-.75em}\begin{tabular}{|p{10cm}}\parbox{38em}{\andIquote $endorsements.quote$’’}\end{tabular}}

There is support for multilingual hyphenation, which means words are cut of correctly at the end of the sentence. This makes it so, that it’s not necessary to justify the intro text in order to have a neat not too ragged text block.

Vertical rhythm is hold on to the “Intro section”. This basically means a prettier reading experience.

Note that I am not going into too much detail into each feature as this case study is long enough on its own. Look towards Butterick’s Practical Typography for that.

The optimal line length is considered against the best practices (around ±65 characters per line), total page proportions, information in the first page and all round purpose of this document (giving information in concise readable package). This means the line length is a little longer, but practical.

Almost done, this is a subtle one!

Each paragraph except the first one in the “Intro section” has an em dash indent.

This is according to Jan Tschichold a good way of defining a paragraph without losing space due to paragraph spacing.

Lastly, a different top margin for the second page onwards. This is done by using the following code — generously provided by touhami:

\newlength\newtop
\setlength{\newtop}{$geometrysecondarypagestop$}
\makeatletter
\patchcmd\@outputpage{\global \@colht \textheight}{%
\global\textheight=\dimexpr\textheight+\newtop\relax%
\global\topmargin=\dimexpr\topmargin-\newtop\relax%
\global\@colht\textheight%
\global\newtop\z@}{}{\err}
\makeatother

It squeezes that last little bit space out of the additional pages.

If you reached this point. Congratulations!

You now know how and why I made this. You know where to get it! And you are free to do what you want with it, as I publish it under the same licence as Mattia — CC BY-SA 3.0!

Build upon it, give some pull requests back if you want and help others out.

This is by no means really done. One of the things I am considering is:

  • Adjusting the makefile and yaml file in order to be able to have multiple templates. They would then be selectable from within the yaml file by changing a single line.

Thank you for reading!

Follow me on Twitter or contact me on dhesign.com

If you liked this, click the ❤ below so other people will see this here on Medium.

One more thing…

Ah yes, helping others out…

Well, that’s the last part I didn’t exactly write about. How can we let other people make their own cv’s with us only configuring it once?

Gitlab meets Dropbox

When looking into the repository we can see that parts of the gitlab-ci.yml are commented out. This code activates the Dropbox-Uploader script by Andrea Fabrizi.

Details on how to use this script are in the Dropbox-Uploader repository. Basically you have to give the dropbox_uploader_config file the correct details.

What it does, is pulling in the yaml files you have in a shared folder, generating the pdf’s and uploading those back. This folder is shared with somebody you are helping out.

Of course we need that someone to have a way of triggering the rebuild of the gitlab repository.

Note there are possibly better ways of doing this, but this one works. File an issue with your idea!

We can do this by making use of a gitlab repository trigger (which can be found in the repository settings) and an IFTTT recipe.

Configure a special email address like [yourgmail]+[unique_string]@gmail.com, this is possible due to using an address alias. Fill in the other details and you are ready to go. Your build will now trigger whenever your friend sends a random email to this address.

Optionally you can configure a gitlab service to send him or her a build status email, in order to let them know if their build passed. Otherwise they will get a notification if the newly created pdf has arrived or updated in their dropbox upon succes!

Update: Cover Letter

Cover letters are now included in the repository!

They are created in the same fashion and complement your résumé in a beautiful way. Check it out:

Added features on top of Mattia’s version are Vertical Rhythm and the same controls (plus a few extra) as the CV.

Again, thank you for reading!

Follow me on Twitter or contact me on dhesign.com

--

--