From 1582d9f9651763f13eb46df2bee63691b861dc9d Mon Sep 17 00:00:00 2001 From: Lucien Cartier-Tilet Date: Wed, 8 Jul 2026 07:31:03 +0200 Subject: [PATCH] feat(resume): add typst code for PDF resume --- .gitignore | 3 + content/en/resume.typ | 128 ++++++++++++++++++++++++++++++++++++++++++ content/fr/resume.typ | 128 ++++++++++++++++++++++++++++++++++++++++++ nix/shell.nix | 10 ++++ 4 files changed, 269 insertions(+) create mode 100644 content/en/resume.typ create mode 100644 content/fr/resume.typ diff --git a/.gitignore b/.gitignore index 8aaa1f7..5b44cd8 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ node_modules result .data/ app/coverage/* + +# Typst +content/*/*.pdf diff --git a/content/en/resume.typ b/content/en/resume.typ new file mode 100644 index 0000000..ba732e6 --- /dev/null +++ b/content/en/resume.typ @@ -0,0 +1,128 @@ +// Based on https://github.com/stuxf/basic-typst-resume-template + +#import "@preview/basic-resume:0.2.9": * + +#let resumeData = json("resume.json") +#let i18nData = json("../../i18n/locales/en.json") +#let privateData = json("../../private/data.json") +#let projects = json("projects.json"); + +#let tool-chip(t) = link(t.link)[#t.name] +#let tool-list(tools) = tools.map(tool-chip).join(", ") + +#let name = i18nData.website.name +#let location = privateData.location +#let email = privateData.email +#let github = "github.com/phundrak" +#let gitea = "labs.phundrak.com/phundrak" +#let linkedin = "linkedin.com/in/lucien-cartier-tilet/" +#let phone = privateData.phone +#let personal-site = "phundrak.com" + + // dates: dates-helper(start-date: "Jan 2021", end-date: "Present"), +#let time-period(dates) = { + let end = dates.at("end", default: none); + if end == none { + [Since #dates.start] + } else { + dates-helper(start-date: dates.start, end-date: end) + } +} + +#show: resume.with( + author: name, + location: location, + email: email, + github: github, + linkedin: linkedin, + phone: phone, + personal-site: personal-site, + accent-color: "#5e81ac", + font: "New Computer Modern", + paper: "a4", + author-position: left, + personal-info-position: left, +) + +/* +* Lines that start with == are formatted into section headings +* You can use the specific formatting functions if needed +* The following formatting functions are listed below +* #edu(dates: "", degree: "", gpa: "", institution: "", location: "", consistent: false) +* #work(company: "", dates: "", location: "", title: "") +* #project(dates: "", name: "", role: "", url: "") +* certificates(name: "", issuer: "", url: "", date: "") +* #extracurriculars(activity: "", dates: "") +* There are also the following generic functions that don't apply any formatting +* #generic-two-by-two(top-left: "", top-right: "", bottom-left: "", bottom-right: "") +* #generic-one-by-two(left: "", right: "") +*/ + +== Work Experience + +#for e in resumeData.experience [ + #work( + title: e.title, + company: e.company, + dates: time-period(e.dates) + ) + #if e.description != "" [ + #par(e.description) + ] + #if "tools" in e and e.tools.len() > 0 [ + #par(text(size: 9pt, fill: gray)[#tool-list(e.tools)]) + ] +] + +== Technical Skills +- *Programming Languages*: #tool-list(resumeData.programmingLanguages) +- *Frameworks*: #tool-list(resumeData.frameworks) +- *Operating Systems*: #tool-list(resumeData.os) +- *Devops Technologies*: #tool-list(resumeData.devops) +- *Other Tools*: #tool-list(resumeData.otherTools) + +== Education + +#for e in resumeData.education [ + #edu( + institution: e.institution, + location: e.location, + dates: time-period(e.dates), + degree: e.degree, + ) + #if e.description != "" [ + #par(e.description) + ] +] + +== Projects + +#for p in projects.projects [ + #project( + name: p.name, + role: p.role, + url: p.links.at(0).url, + dates: time-period(p.dates) + ) + #par(p.description) +] + +== Extracurricular Activities + +#extracurriculars( + activity: "Conlanging", + dates: time-period((start: "2016")), +) + +Artificial language creation +/ Eittlandic: a sister language to the Nordic languages like Norwegian or Icelandic. + - #link("https://conlang.phundrak.com/eittlandic")[conlang.phundrak.com/eittlandic] + - Naturalistic language + - Evolved from theorized Early Old Norse (an in-between of Proto-Norse and Old Norse) +/ Proto-Ñyqy: a language made as the root language of the Ñyqy language family in a fictional setting. + - #link("https://conlang.phundrak.com/proto-nyqy")[conlang.phundrak.com/proto-nyqy] + - Relatively simple grammar + - Base for several related languages and sub-families, like the Mojhal languages (currently under construction) +/ Zikãti: Experimental language focused on vocabulary generation + - #link("https://conlang.phundrak.com/zik%C3%A3ti")[conlang.phundrak.com/zikãti] + - Vocabulary based on few root words for generic concepts, expanded with prefixes and suffixes diff --git a/content/fr/resume.typ b/content/fr/resume.typ new file mode 100644 index 0000000..8485d4b --- /dev/null +++ b/content/fr/resume.typ @@ -0,0 +1,128 @@ +// Based on https://github.com/stuxf/basic-typst-resume-template + +#import "@preview/basic-resume:0.2.9": * + +#let resumeData = json("resume.json") +#let i18nData = json("../../i18n/locales/fr.json") +#let privateData = json("../../private/data.json") +#let projects = json("projects.json"); + +#let tool-chip(t) = link(t.link)[#t.name] +#let tool-list(tools) = tools.map(tool-chip).join(", ") + +#let name = i18nData.website.name +#let location = privateData.location +#let email = privateData.email +#let github = "github.com/phundrak" +#let gitea = "labs.phundrak.com/phundrak" +#let linkedin = "linkedin.com/in/lucien-cartier-tilet/" +#let phone = privateData.phone +#let personal-site = "phundrak.com" + + // dates: dates-helper(start-date: "Jan 2021", end-date: "Present"), +#let time-period(dates) = { + let end = dates.at("end", default: none); + if end == none { + [depuis #dates.start] + } else { + dates-helper(start-date: dates.start, end-date: end) + } +} + +#show: resume.with( + author: name, + location: location, + email: email, + github: github, + linkedin: linkedin, + phone: phone, + personal-site: personal-site, + accent-color: "#5e81ac", + font: "New Computer Modern", + paper: "a4", + author-position: left, + personal-info-position: left, +) + +/* +* Lines that start with == are formatted into section headings +* You can use the specific formatting functions if needed +* The following formatting functions are listed below +* #edu(dates: "", degree: "", gpa: "", institution: "", location: "", consistent: false) +* #work(company: "", dates: "", location: "", title: "") +* #project(dates: "", name: "", role: "", url: "") +* certificates(name: "", issuer: "", url: "", date: "") +* #extracurriculars(activity: "", dates: "") +* There are also the following generic functions that don't apply any formatting +* #generic-two-by-two(top-left: "", top-right: "", bottom-left: "", bottom-right: "") +* #generic-one-by-two(left: "", right: "") +*/ + +== Expérience professionelle + +#for e in resumeData.experience [ + #work( + title: e.title, + company: e.company, + dates: time-period(e.dates) + ) + #if e.description != "" [ + #par(e.description) + ] + #if "tools" in e and e.tools.len() > 0 [ + #par(text(size: 9pt, fill: gray)[#tool-list(e.tools)]) + ] +] + +== Compétences Techniques +- *Langages de programmation*: #tool-list(resumeData.programmingLanguages) +- *Frameworks*: #tool-list(resumeData.frameworks) +- *Systèmes d’exploitation*: #tool-list(resumeData.os) +- *Technologies devops*: #tool-list(resumeData.devops) +- *Autres outils*: #tool-list(resumeData.otherTools) + +== Éducation + +#for e in resumeData.education [ + #edu( + institution: e.institution, + location: e.location, + dates: time-period(e.dates), + degree: e.degree, + ) + #if e.description != "" [ + #par(e.description) + ] +] + +== Projets + +#for p in projects.projects [ + #project( + name: p.name, + role: p.role, + url: p.links.at(0).url, + dates: time-period(p.dates) + ) + #par(p.description) +] + +== Autres activités + +#extracurriculars( + activity: "Idéolinguistique", + dates: time-period((start: "2016")), +) + +Création de langues fictives +/ Éittlandais: une langue sœur des autres langues nordiques, tel que le norvégien ou l’islandais. + - #link("https://conlang.phundrak.com/eittlandic")[conlang.phundrak.com/eittlandic] + - Émule une langue naturelle + - Évolué depuis une forme théorique intermédiaire du Proto-Norrois et Vieux Norrois +/ Proto-Ñyqy: une langue créée comme racine de la famille de langues construites Ñyqy dans un univers litéraire. + - #link("https://conlang.phundrak.com/proto-nyqy")[conlang.phundrak.com/proto-nyqy] + - Grammaire relativement simple + - Base pour plusieurs langues et sous-familles de langues, telles que les langues Mojhal (en cours de création) +/ Zikãti: Langue expérimentale centrée sur la génération de vocabulaire + - #link("https://conlang.phundrak.com/zik%C3%A3ti")[conlang.phundrak.com/zikãti] + - Vocabulaire basé sur un nombre réduit de mots et concepts racines, dérivés par la suite via des affixes diff --git a/nix/shell.nix b/nix/shell.nix index 2ed8cf1..18cbb06 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -18,8 +18,17 @@ inputs.devenv.lib.mkShell { # Node nodejs_24 nodePackages.pnpm + + typst + tinymist # Typst LSP ]; + processes = { + frontend.exec = "pnpm dev"; + resume-fr.exec = "typst watch content/fr/resume.typ --root ."; + resume-en.exec = "typst watch content/en/resume.typ --root ."; + }; + enterShell = '' echo "🚀 Nuxt.js development environment loaded!" echo "📦 Node.js version: $(node --version)" @@ -27,6 +36,7 @@ inputs.devenv.lib.mkShell { echo "" echo "Run 'pnpm install' to install dependencies" echo "Run 'pnpm dev' to start the development server" + echo "Or run 'devenv up' to start the development server and compile the PDFs" ''; } ];