Erro

That cool thing to look interesting in the world of work

About

Yup. I host my LaTeX CV on a dedicated repository on GitHub and release every version of it using dedicated Releases. I really enjoyed the idea to review it as a coding project, making it buildable as a common project using build automation tools and release its binary (PDF) version.

Build it yourself

If you want to fork the project and produce your own resume, the local toolchain is:

Source data lives under src/langs/*.yml and templates under src/templates/*.{tex,html,txt}.j2.

Download

To download latest version, please, reach latest GitHub repository release. Otherwise, if you want to grab it from the shell (or in any other way you prefer), you can use (or adapt) the following snippet:

lang="en"          # supported: en, it
variant="europass" # supported: europass, personal
release="https://github.com/streambinder/erro/releases/latest"
curl "${release}/download/${variant}_${lang}.pdf" -o resume.pdf

The same release also publishes non-PDF variants generated from the very same data source:

New releases are tagged YYYY-MM-DD (UTC). A same-day re-push rolls the tag forward in place rather than minting a new one, so latest always points at the freshest build of the day.

Design

The first issue I faced was about few companies being very strict on the allowed CV format, hence asking for the EuroPass one, for example. On the other hand, I really enjoyed my custom format and didn't want to just drop it. And what if another company would have come asking for a CV formatted following another format?

All of this led me considering templating my documents: many tex files as many formats I wanted to support and a single database file keeping the information used to fill the templates.

On the other hand, I wanted my CV to be internationalized, maintaining a different version of each different format for each language supported.

After a first round in which I did implement all the features on my own (look at erro@be0c83e if interested), I moved to a more solid structure.

Templating

Different formats, or templates, are to be made and accessing same data based on a sort of identifiers. Despite how simple this issue could look, it's definitely not, at least if you want to keep something to be somehow proud.

Looking for a nice way to replace my old and misfiring templating engine, I discovered jinja. This library allows you to define block_start_string, variable_start_string and many other nice things to make it able to detect where exactly in your template you want placeholders and identifiers to be replaced with actual content.

This scales really good for LaTeX documents, actually:

latex = jinja2.Environment(
    block_start_string='\\jblock{',
    block_end_string='}',
    variable_start_string='\\jvar{',
    variable_end_string='}'
)

latex.get_template('template.tex') \
    .stream(author='streambinder') \
    .dump('resume.tex')
\begin{document}

    \jvar{author}'s CV.

    \jblock{for i in range(5)}
        \jblock{if i % 2 == 0}
            \textit{ \jvar{i} }
        \jblock{endif}
    \jblock{endfor}

\end{document}
\begin{document}

streambinder's CV.

\textit{ 0 }
\textit{ 2 }
\textit{ 4 }

\end{document}

Making the engine take the rendering parameters from a database file was pretty easy, too. The same result above can be achieved the following way:

with open('database.yaml', 'r') as database_fd:
    latex.get_template('template.tex')
        .stream(yaml.safe_load(database_fd))
        .dump('resume.tex')

With database.yaml like below:

author: streambinder

Internationalization

Once you have a perfectly working template engine with support for external data source, supporting internationalization is straightforward: introduce a different database file for each language.

for lang in ['en', 'it']:
    with open('database_{}.yaml'.format(lang), 'r') as database_fd:
        latex.get_template('template.tex')
            .stream(yaml.safe_load(database_fd))
author: streambinder in english
author: streambinder in italiano

Inline formatting in the database

The YAML data source supports a tiny markdown-inspired subset that gets translated on the fly to whatever the target template renders:

LaTeX special characters in surrounding prose (& % $ # _ { } ~ ^ \) are escaped automatically before rendering, so the YAML stays portable across the LaTeX, HTML and plain-text outputs without per-target authoring.

Output formats

Each language config is fanned out across three Jinja environments (tex, html, txt) with different delimiter sets, so the same data drives three distinct artifact families:

All variants ship together as assets of a single GitHub Release; see download for the URL pattern.