curriculr is an R package for producing data-driven curriculum vitae
documents. You maintain your CV content in an Excel workbook. curriculr reads
it, converts it into Typst layout blocks, and renders a polished PDF via
Quarto's Typst engine. No LaTeX. No vitae. No custom .cls files.
You can install curriculr from CRAN:
install.packages("curriculr")For the latest development features, install from GitHub:
# install.packages("pak")
pak::pak("erwinlares/curriculr")- R (>= 4.2.0)
- Quarto 1.4 or later (ships with Typst support built in)
Call create_cv() with no arguments. This copies the template workbook and a
placeholder profile image into your current working directory:
library(curriculr)
create_cv()You will see:
v Created cv-data-template.xlsx
v Created placeholder.png
i Next steps:
1. Open cv-data-template.xlsx and fill in the profile sheet.
2. Replace placeholder.png with your own profile photo.
3. Call create_cv(data = 'cv-data-template.xlsx', photo = 'your-photo.png')
Open cv-data-template.xlsx. Start with the profile sheet:
| field | value |
|---|---|
| first_name | Your first name |
| last_name | Your last name |
| job_title | Your current title |
| address | Your mailing address |
| your@email.edu | |
| website | yourwebsite.com |
| github | your-github-username |
| in/your-linkedin | |
| profile_statement | One or two sentence professional summary |
| photo | Relative path to your profile image |
Then fill in the remaining sheets with your CV content. The readme sheet
inside the workbook explains the column schema and date entry conventions
in detail.
create_cv(
data = "cv-data-template.xlsx",
photo = "your-photo.png"
)This writes CV.qmd and CV.pdf next to your workbook. Open CV.pdf to
review the output. To update your CV, edit the workbook and call create_cv()
again with overwrite = TRUE.
To render without a profile photo, omit the photo argument. The header
will use a single-column layout with your name, contact line, and profile
statement centered on the page:
create_cv(data = "cv-data-template.xlsx")When you want a shorter, focused version of your CV, use variant = "resume".
curriculr will include only the rows you have checked in the
include_in_resume column of each section sheet:
create_cv(
data = "cv-data-template.xlsx",
photo = "your-photo.png",
variant = "resume",
output_file = "resume.pdf"
)Check and uncheck rows directly in the workbook. No R code changes are needed to switch between CV and resume variants.
Open your workbook and edit the theme sheet. Each key maps to a visual
setting:
| key | what it controls |
|---|---|
font_family |
Body font (e.g. Lato, Arial) |
font_size |
Base font size (e.g. 8.8pt) |
body_color |
Main text color (hex code) |
accent_color |
Section headings, dates, and rules (hex code) |
dark_color |
Entry titles and name in the header (hex code) |
papersize |
Page size (us-letter or a4) |
margin_x |
Left and right margins (e.g. 0.62in) |
margin_y |
Top and bottom margins (e.g. 0.58in) |
Re-render after editing the theme sheet with overwrite = TRUE to see
the changes.
Edit the sections sheet in your workbook. Reorder rows to reorder sections.
Delete a row to remove a section.
Use add_section() to add a new sheet and register it in the sections
control sheet in one step:
add_section(
"cv-data-template.xlsx",
section = "patents",
label = "Patents",
date_fun = "year_only"
)The new sheet is pre-populated with the standard column spine. Open the workbook, add your data, and re-render.
The main entry point. No arguments triggers scaffold mode. With data
triggers render mode.
# Scaffold mode
create_cv()
# Render mode -- full CV with Font Awesome icons in the contact line
create_cv(
data = "cv-data.xlsx",
photo = "me.jpeg",
output_file = "erwin-lares-cv.pdf"
)
# Render mode -- resume variant, plain text contact line
create_cv(
data = "cv-data.xlsx",
photo = "me.jpeg",
variant = "resume",
use_icons = "none",
output_file = "erwin-lares-resume.pdf"
)Arguments:
data-- path to the workbook.NULLtriggers scaffold mode.photo-- path to the profile image.NULLrenders without a photo.output_file-- PDF filename. Defaults to"CV.pdf".overwrite-- whether to overwrite existing files. Defaults toFALSE.variant--"cv"(all rows) or"resume"(checked rows only).use_icons--"fontawesome"(default) or"none".
Adds a new sheet to an existing workbook and registers it in the sections
control sheet.
add_section(
"cv-data-template.xlsx",
section = "invited_talks",
label = "Invited Talks",
date_fun = "month_year",
where_col = "where"
)Reads all sheets from the workbook into a named list. The profile and
theme sheets become named character vectors; section sheets become data
frames; the sections sheet is returned in row order.
cv <- read_cv_data("cv-data-template.xlsx")
cv <- read_cv_data("cv-data-template.xlsx", variant = "resume")
cv$experience # a data frame
cv$sections # the sections control sheet
cv$profile[["email"]] # a scalar string
cv$theme[["accent_color"]] # a scalar stringAssembles the contact line from a profile vector. Useful when building custom Quarto templates.
cv_contact_line(cv$profile, use_icons = "fontawesome")
cv_contact_line(cv$profile, use_icons = "none")Iterates over a CV data frame and writes each row as a formatted Typst entry.
Called inside CV.qmd -- you will not normally call this directly.
Escapes Typst-sensitive characters in a string. Useful when building custom Quarto templates.
Returns a raw Typst string for a section heading. Useful when building custom Quarto templates.
Maps a date_fun token string to an R date formatting function. Useful when
building custom rendering logic outside the standard template.
Every section sheet shares a common column spine:
title | unit | startMonth | startYear | endMonth | endYear | where | detail | include_in_resume
title is always the primary entry label. unit is the secondary line.
include_in_resume is a boolean checkbox column -- check a row to include it
when rendering with variant = "resume". Leave cells blank rather than typing
NA.
| Situation | startMonth | startYear | endMonth | endYear |
|---|---|---|---|---|
| Ongoing role | Jan | 2018 | present | (blank) |
| Completed role | Mar | 2015 | Dec | 2022 |
| Single-year event | (blank) | 2021 | (blank) | (blank) |
| No date | (blank) | (blank) | (blank) | (blank) |
Detailed notes on upgrading from previous versions are available in the changelog. The key changes by version:
v0.2.0 to v0.3.0 -- photo = NULL now produces a no-photo layout
instead of falling back to a placeholder. Workbooks need an
include_in_resume column on every section sheet. An optional theme sheet
controls fonts, colors, and page layout. openxlsx2 replaces readxl.
v0.1.0 to v0.2.0 -- create_cv() gained scaffold mode (no arguments)
and render mode (with arguments). Workbooks need a sections sheet to
control which sections appear and in what order.
curriculr shares an author and design philosophy with three other R packages focused on reproducible research workflows:
- toolero -- research project scaffolding and data wrangling utilities
- containr -- containerization of R projects via Dockerfile generation
- submitr -- job submission to UW-Madison's CHTC from inside R
Together, toolero, containr, and submitr form the From the Notebook to the Cluster pipeline. curriculr is independent but follows the same conventions: small focused functions, data-driven workflows, and Quarto as the publishing layer.
curriculr was inspired by two prior projects:
- vitae by Mitchell O'Hara-Wild, Rob Hyndman, and contributors
- Awesome CV by Byungjin Park (posquit0)
If you use curriculr in your work, please cite it:
citation("curriculr")MIT (c) Erwin Lares
