course poster templates
with quarto and typst
I’ve described in previous blog posts 1 2 my experimental workflow to produce posters by combining a graphics tool such as Figma for the layout, and a typesetting engine such as LaTeX for processing the content.
The LaTeX side of things has always been a little tricky / painful, and so I got curious to experiment with Typst to see if it might make things easier (spoiler: it does). Having an instant preview when tinkering with the template on the web app is a huge boost in productivity, compared to LaTeX compilation (and staring at obscure error messages – or worse, my new nemesis “tlmgr updating”).
Here’s what the new version looks like, side-by-side:
The template file is much more readable than it was in LaTeX; here are some excerpts:
#let myfont = "Source Sans Pro"
#let scps-poster(
coursetitle: "course title",
courseid: "rand101",
coursemajor: none,
courseimage : none,
coursepoints: "15",
coursetrimester: none,
courselecturers: ("nature",),
courseformat: none,
courseprereqs: none,
imagecredit: none,
coursedescription: none,
// The main content.
body
) = {
// set up dimensions
let (pagewidth, pageheight, bleed) = (297mm, 420mm, 6mm)
let margin-body-left = 33.5mm
let margin-shaded-top = 125mm
let padding-body = 0.5em
// ...
let image-width = pagewidth - 2*margin-body-left
// ...
// computed variables
// extract the course discipline and course code
let coursediscipline = courseid.slice(0,4)
let coursecode = courseid.slice(4,7)
// year dictates the background colour
let year = coursecode.at(0)
let col = (
"1": rgb(235,157,12),
"2": rgb(0,158,224),
"3": rgb(86,163,38),
"4": rgb(226,0,122),
).at(year)
// • is coloured accordingly
show "•": text.with(weight: "extralight", fill: col)
// set up page
set page(height: pageheight, width: pagewidth, margin: 0mm, background: bkg(col: col))
set text(font: myfont, size: 13pt)
set par(justify: false, leading: 0.2em)
show raw: set text(font: "Source Code Pro", size: 1.1em, tracking: -0.1pt)
// logo
place(
dx: margin-body-left,
dy: pageheight - margin-shaded-bottom + address-top,
image("vuwlogofaded.svg", height: logo-height)
)
// title
let title = [
#set align(center+bottom)
#set par(leading: 0.4em)
#show text : smallcaps
#set text(font: myfont, size: 46pt, fill: col, tracking: 0pt)
#text(weight: "thin")[#coursediscipline]#h(0.042em)#text(fill: black, weight: "medium")[#coursecode]\ #text(weight: "semibold", tracking: 0pt, fill: black)[#coursetitle]
]
place(
dx: 0mm,
dy: title-top,
block(width:pagewidth, height:45mm, inset:1em)[#title]
)
// ...
} // end body
It’s really nice to have access to programming constructs in the language. I’m still struggling with some of the logic in Typst, but then again the language is evolving as we speak, and I think the proposed #context
construct will make much more sense to me.
quarto
With this template, I don’t have as much need for pre-processing as in the previous iteration, where the input file – a combination of markdown and yaml, needed some Lua filters (to replace “•” with a LaTeX macro to colour it according to the course year, and similar tricks). The QR codes were also generated with a R script, whereas Typst now has a plugin to do it on-the-fly.
Still, I ported the template to Quarto out of curiosity, to understand the mechanics with the typst format, and it has the advantage of automation: I typically need to process ~25 such posters, and having them all in a Quarto projects lets me run
quarto render
and grab a cup of tea while everything happens (it’s actually relatively fast even for gong fu style brewing, definitely much faster than through LaTeX).
The input format is therefore very close to the previous iteration: a combination of markdown and yaml, somewhat simplified since I can more easily style things in the Typst template. Here’s a side-by-side view of the input and output files, as run by Quarto.
and a couple of outputs to show the variations:
Overall, I’m pretty happy with the results. There are a few glitches in Typst and it’s not quite stable yet, but for simple documents like these, it’s very usable, and the instant preview is a huge advantage.
I’m also experimenting with the other poster template, porting it to Typst (work in progress below).
small frictions
A few glitches and pain points I have yet to resolve:
- redefining the colour of characters such as “•” in typst cannot be done multiple times
- CMYK images look terrible as the colour profile is ignored
- helper functions need to be defined in order of appearance, which I find inconvenient
- I was unable to generate a regular expression from a string created programmatically (combining two sub strings)
- pdf images aren’t supported, and I’ve had some issues with SVGs
- measuring the body to decide on vertical spacing was tricky; the new
#context
framework sounds like it’ll make things easier
and on the Quarto side, I am a bit confused by the way the whole template is injected in the output document, as opposed to kept as a separate file alongside the document. But that’s probably just my misunderstanding of how custom templates should be used in this case.