Typst and a CV template
Updated 2023-08-30
If you are interested in typesetting outside the normal options (Word, LibreOffice), and have had a gnawing feeling that LaTeX is, after all, a bit annoying to use (and I say that as a maybe not power user, but having used it for the past ten years, including all important documents), Typst may be for you.
It’s a new document language, conceptually somewhere between LaTeX and Markdown, has been hyped a bit recently – and
that hype is fully deserved. Having had no experience in it, I rewrote my CV on a Sunday morning
within less than two hours, and it looks better than the prior LaTeX version. Written in Rust, it is easily installable
through cargo, as a standalone binary, or usable on the web. I went the first route (as a matter of pride).
With that said, I don’t want to give a full introduction, because the documentation is amazing as well.
What I will leave here, is my little black-and-white CV template. It is useful enough for a real CV while being not very complicated to layout. Unfortunately, syntax highlighting doesn’t exist yet in my website generator :-)
Colors and spacings can be adjusted directly in the header. If you use it or make some modifications – it is admittedly quite bare-bones right now – I’d love to hear from you!
// example.typ
#import("cv.typ"): *
/* CV begins below here: */
/* ========================================================== */
#cv_title([Your Name])
#cv_h2()[
Personal Information
]
#grid(
columns: (20%, 80%),
rows: 16pt,
[_Address_], [123 Wonder lane, Example town, XY 81444],
[_Born_], [X city; Month 17, 19xy],
[_Phone_], [+1 234 567 89]
)
#cv_h2()[Experience]
#cv_h3[Work]
#cv_table(
[Year 2], [
*Great achievement*
Saving the world (full-time).
],
[Year 1], [
*General specialist*
Expert in everything.
],
)
#cv_h3[Education]
#cv_table(
[2003-2013], [*Degree*, Physics (4.0 GPA)],
[1998-2002], [High school, not worth talking about]
)
#cv_h2[Skills]
#cv_h3[General]
- Bullshitting (pro-level)
- Mansplaining (world-class)
- Complaining (if needed)
#cv_h3[Computers]
- Turning off and on again
- Screaming at
- Clicking _print_ three times instead of once
And this is the template package:
// cv.typ
#let cv_title(t) = [
#set align(center)
#text(t, font : "Fontin", weight : "bold", size : 26pt)
]
#let cv_h2(t) = [
#v(3pt)
#line(length: 100%, stroke: gray)
#smallcaps(text(t, font: "Fontin", size: 18pt, weight: "regular"))
]
#let cv_h3(t) = [
#smallcaps(underline(text(t, font: "Fontin", size: 14pt, weight: "regular"), offset: 5pt, stroke: gray))
]
/* Standard link, in blue. */
#let cv_link(t, lab) = text(link(t, lab), fill: blue)
/* Standard layout constants. */
#let cv_citysep = " "
#let cv_table_cell_width = 35em
/* Indents a block slightly to offset it from surrounding content. */
#let cv_inset(t) = par(hanging-indent: 1em, first-line-indent: 1em, t)
/* Indicates a station within an overall experience:
#cv_station([Apr 2019 - Apr 2020], [Taste University], [Flavortown, USA])
*/
#let cv_station(time, inst, loc) = [
*#time* #h(1em) *#inst* (#loc)
]
/* Not for external use: use cv_table() instead. Feel free to adjust colors etc. */
#let cv_table_cell(t, width: cv_table_cell_width) = block(t, fill: luma(250),
width: width, outset: 5pt, stroke: (left: black + 1pt))
/* Use like this:
#cv_table([2024\ 2020], [Some awesome job])
*/
#let cv_table(width1: 7em, row-spacing: 20pt, ..cellpairs) = [
#grid(
columns: (width1, cv_table_cell_width - width1 + 7em),
rows: auto,
row-gutter: row-spacing,
..(cellpairs.pos().enumerate().map(p => {
let (i, b) = p
if calc.even(i) [
#text(weight: "bold", b)
] else [
#cv_table_cell(b, width: cv_table_cell_width - width1 + 7em)
]
})
)
)
]
