Skip to content

An opinionated (and probably over-engineered) workflow to produce a fancy LaTeX, web or docx Curriculum Vitae document from a JSON data source using Jinja2 (a data-driven CV)

avivace/j2-resume

Repository files navigation

J2-résumé

An opinionated workflow to produce different versions of a Curriculum Vitae (résumé) document allowing different localisations, templates, styles and formats without having to mantain them all.

Example

If you want to take a look at a potential final result, my CV is built using this tool.

Architecture

Architecture

Goals

  • Logically and practically separate templates/tools and data source;
  • Have an agnostic data source (JSON) and edit ONLY that when updating the informations (API access to a remote endpoint exposing a compliant JSON is trivially implementable, too);
  • Have data source compliant and validated against a formal specification or schema (use JSON schema and possibly the JSON-Resume specification?). Templates must respect this schema too;
  • Allow a sane versioning of both the data source and templates, separately;
  • Easily update and version the data source using a text editor or a (visual) JSON editor;
  • Keep the hybrid Jinja2 templates clean and similar to their plain format versions (that's why a LuaLaTeX solution was scraped).

How the code looks like

This is your JSON data source:

{
    [...]
    "name": "Maximilian Mustermann",
    "address": "Wien, Austria",
    "age": "44",
    "phone": "(+43) 231 7484174 ",
    "website": "https://maxmusterman.com",
    "github": "https://github.com/maxmusterman",
    "email": "max@mustermann.at",
    [...]
    "education": [
        {
            "title":"Bachelor's Degree",
            "field":"Engineering Science",
            "school":" Technical University of Munich",
        },
        {
            "title":"Master of Science",
            "field":"Computational Science and Engineering",
            "school":"Vienna University of Technology",
        }
    ],
    "work": [
        {
            "position": "API Developer",
            "place": "Time Lord Academy (Mount Cadon)",
            "field": "Untempered Schism",
            "period": "453 -- Present",
            "description": "Protecting the ancient Law of Gallifrey exposing time-travel-as-a-service. Implementing psychic paper proof authentication protocol."
        }
    ]
}

LaTeX

This is how a Jinja2-templated LaTeX document looks like:

[...]
\begin{document}

\jv{data.name}

\address{ 
\href{\jv{data.website}}{\jv{data.website[8:]}}\\ 
\href{\jv{data.github}}{\jv{data.github[8:]}}\\
\jv{data.email}\\ 
} % Your address 2

\address{
\jv{data.address} \\
\jv{data.age} years old\\
\jv{data.phone}
}

\jb{ for edu in data.education }
    {\sl \jv{edu.school}} \hfill \jv{edu.period} \\ 
    {\sbb \jv{edu.title}}, \jv{edu.field} \\
\jb{ endfor }


\jb{ for experience in data.work }
    {\sl \jv{experience.place} } \hfill \jv{experience.period}\\
    {\sbb \jv{experience.position} } \hfill \jv{experience.field}}\vspace{4pt} \\
    \small{\textcolor{darkgray}{
    \jv{experience.description}
    }
\jb{ endfor }

[...]

Basically, a clean TeX file with some Jinja2 syntax inside the \jb and \jv special tags.

We plug those two and we get a fancy LaTeX render, obtaining:

latex preview

React/Vue

Recent tools have native support for plugging JSON data. E.g. on a Vue component:

<title>{{ name }} résumé</title>
Name: {{ name }}
Address: {{ address }}
Age: {{ age }}
Phone: {{ phone }}
Website: {{ website }}
GitHub: {{ github }}
Email: {{ email }} 

<subtitle> Education </subtitle>
<template v-for="degree in education">
    <h3>{{ degree.title }}</h3>
    <subtitle>{{ degree.school }}<br>
    <i>{{ degree.field }}</i></subtitle>
</template>

Build

Requirements

  • a TeX distribution
  • XeLaTeX
  • Python3

On Debian:

sudo apt install texlive-base pandoc python3 texlive-xetex fonts-roboto

On Fedora:

sudo dnf install texlive-collection-fontsrecommended texlive-xetex texlive-latex texlive-collection-latexextra texlive-titlesec 'tex(datetime.sty)' 'tex(eu1enc.def)' 'tex(polyglossia.sty)'
sudo dnf install google-roboto-fonts.noarch

LaTeX workflow

python j2tex.py
xelatex resume.tex

TODO

  • Résumé JSON schema
  • Example Vue template for the web workflow
  • Example MD/HTML5 template for the pandoc workflow
  • pandoc preprocessor to allow Markdown in the field of the json, then preprocess to the target language in each workflow.

Related projects

If you wish to remain sane, something like pandoc-resume could fit your use-case with less effort (BUT it doesn't provide a serialized data source, it's markdown).

References

Various resources, links and threads examined for the project.