Why I switched to Quarto for my Lecture Slides
During my time as a lecturer, I have primarily been a Keynote user. Keynote is pretty nice, the built in visuals are tasteful, and for me I find the outline view an absolute joy to use, especially on iPad1
However, something I have always found a tempting offer is Reveal.js. In terms of interactivity, Reveal is unparalleled. Your whole presentation being a website that you can customise with CSS and JS, use any libraries you want? As a piece of software, I have always found it intriguing.
However, there have always been a number of pain points that put me off…
- I don’t want to author in HTML. Reveal has Markdown support, but honestly it has always felt quite unnatural to me to use. I find myself making a single massive markdown cell, having to break it up arbitrarily to achieve a specific slide layout, or doing a markdown chunk per slide, or sacrificing customisation, and the whole experience feels pretty obtuse.
- Whilst HTML might open up a lot of interactivity, I do not have a web background; I don’t particularly like HTML, I find CSS a pain, and JavaScript has long been my least favourite programming language2. Whilst JS might open the door to customisation, the learning curve for me in particular would be high.
- One of the appeals to me of Reveal.js is being able to demonstrate Python code, something Jupyter allows you to achieve in its editor. However, it depends on having a backend running, which means you lose that interactivity when you publish the slides (Or have to maintain a Jupyter server for potentially hundreds of students to utilise simultaneously).
- Frankly, by default, Reveal is pretty ugly. Sorry if you are reading this and you were involved in picking the defaults, but it’s just not my style. To me, Reveal needs a lot of polish to get to a point I’d be happy with.
- Laying out slides is not convenient. Obviously something WYSIWYG like Powerpoint and Keynote means that being able to quickly reshape and redesign your slides layouts is incredibly convenient in a way Reveal does not match. Perhaps, again, if I were better with HTML I could alleviate this — But also, if I alleviate this issue with HTML, why am I using Markdown? I don’t want to have to drop to HTML over any and every issue.
This is all to say, whilst I love the concept of Reveal, I find it too inconvenient to use directly.
However, I’m always on the lookout for a convenient option or alternative.
For me, as a lecturer, I see a few options:
- Suck it up — Powerpoint and Keynote are alright.
- Reveal.js through Juptyer — Accept that you cannot distribute live slides, but enjoy some very dynamic visualisations; However, also accept some limitations compared to plain Reveal.js
- Look at upcoming frameworks like Marimo, which has a presentation framework (which I must experiment with…)
- Roll something entirely custom (an experiment for another day…)
- A billion different HTML presentation frameworks
- Quarto.
All of these have their own merits. Marimo in particular is very young, and I feel like it’s a real up-and-comping option — Whilst it’s not quite where I’d want it to be to consider it, I am keeping a close eye3…
For me, however, when I discovered Quarto, I started to see something powerful enough, flexible enough, and complete enough, that perhaps it might finally be what I had been looking for.
Quarto
For those unfamiliar with Quarto, it’s worth briefly explaining it.
Quarto is, in essence, a publication framework. In many ways, it can be seen more as a competitor to LaTeX and Juptyer than to Powerpoint — Documents are written in Markdown, can be exported to many formats, allow for referencing, embedding either code or the output of that code (in some languages) directly into your documents, and much more.
Your documents are authored in QMD files — Markdown with a little extra syntax added on top to make documents authoring and typesetting a little nicer. For the most part, QMD is nice enough to interact with; I do find myself having to look up syntax and style classes more than I’d like.
Your Quarto-authored documents are then exported to whichever formats you like, using whatever templates you like with mostly sane defaults:
- HTML
- Word
- Reveal.js
- Powerpoint
- Beamer
- Github Flavoured Markdown
- Hugo
- Some Wiki formats
- Jupyter
There a bunch of formats available, some of which I am barely aware of, some of which you might never need, but some of which make for very tempting offers. However, for me personally, there was only one interesting format — Reveal.js
My main complaint about Reveal.js — The feeling that I need to frequently drop out of Markdown and into HTML to format my slides — is mostly alleviated by Quarto and it’s few syntactic deviations from standard Markdown.
Syntax
For the most part, Quarto’s syntax is just Markdown.
In a few trivial ways, it differentiates.
For example, you can specify a div and assign any classes to it using:
::: {.cssclass}
content
:::
There’s a number of convenience classes added by default to allow you to layout your document or slides. For example:
::::{.columns}
:::{.column width=45%}
left column’s content
:::
:::{.column width=65%}
right column’s content
:::
::::
There’s also some simple classes such as:
:::{.r-vstack}
First item
Second item
:::
In this syntax, everything placed inside is stacked vertically. You can also use .r-hstack for a horizontal stack. Useful for positioning images.
You can also use .r-stack, where all items inside stack on top of each-other… Again, useful for specific cases in presentations.
Overall, you can achieve most things you would want. There are definitely limitations. If you’re used to a WYSIWYG presentation tool, you’re losing a great deal of positional flexibility — Quickly resizing text boxes, placing images wherever you want, etc.
Personally, I’m happy with the positional compromises — I don’t mind a more restrictive layout (versus a WYSIWYG editor) for an easier time composing my lectures (the same trade-off most academics make when they choose LaTeX).
The final critical piece of syntax is the fragment. In Reveal, a fragment is essentially an animation step. You’re saying “This thing should be added to the list of things to animate” — By default, this animation is just starting hidden and then appearing.
This allows you to do incremental animations, particularly useful for slowly revealing parts of the slide as you present.
Here’s some sample text.
[This text starts hidden, then appears!]{.fragment}
:::{.fragment}
This line will appear…
and this line will also appear at the same time!
Reveal will treat this all as one big chunk, even though it occupies multiple lines!
:::
:::{.incremental}
- This will appear first
- Then when you progress the slide this will appear second
- And finally this will appear third when you progress the slide again!
:::
The fragment system is the underpinning of most animations in Reveal.
Embedding and Presenting Code
A particular highlight for me with regard to Quarto is its ability to render, highlight, and demonstrate code blocks in a file.
Reveal is already excellent at rendering code blocks, but the syntax for doing this in Quarto feels very natural. For example, last term I demonstrated a lot of Java code, so I could just add a code block, specify it was Java, and get pretty clean syntax highlighting:
public static Optional<Integer> parseAge(String input) {
if (input == null) return Optional.empty();
try {
int age = Integer.parseInt(input);
if (age < 0 || age > 150) return Optional.empty();
return Optional.of(age);
} catch (NumberFormatException e) {
return Optional.empty();
}
}
You are able to not just demonstrate code, but make Quarto highlight individual lines of the code cell as a fragment, so when demonstrating code you can step through at your own pace as you present.
However, this goes a beyond just demonstrating code. Quarto is also happy executing code in your document, and embedding the output directly into your slide!. As someone who has spent a lot of time teaching Machine Learning concepts, this really excites me! I could write some Python code to demonstrate convolution, have it output a matplotlib figure as a .gif, and have that embed directly into my slides! In previous years, to demonstrate convolution, I have written the code to perform convolution, manually screenshot the outputs, and added them to my Keynote slides. It’s now entirely possible I could build something fully integrated into my slide. Awesome!
There’s support for a number of languages: Python, R, Julia, and JS with Observable. Each has their own quirks, but overall you can achieve a lot of very cool things4.
Plugins
This is where Quarto with Reveal.js starts paying off — The plugin ecosystem.
By default, Reveal is a fairly simple presentation framework, but with Plugins it can be extended to do much more. For example, there are a number of built-in plugins, such as the RevealMarkdown plugin that provides the markdown experience I mentioned earlier, RevealHighlight which provides syntax highlighting for code blocks, and RevealMaths which provides LaTeX maths support.
There are loads of really cool plugins. The reality is, when your entire presentation is a website, you get access to all the power of Javascript and can do some crazy things.
For example, I have a custom Reveal.js plugin with some Quarto magic attached called DAGraph — A plugin for rendering any directed acyclic graph, along with highlighting and annotating the graph, in an entirely declarative manner; For me, this allows me to achieve something I’ve long attempted to emulate before with painstaking manual animations in Keynote, visualising a git graph alongside the relevant commands in a git lecture.
A personal favourite of mine for lectures is Reveal’s multiplex plugin, which means that anyone viewing your presentation has their copy of the slides synchronised with yours; Any students in the audience can have a copy of the slides open on their laptops, and see exactly what’s on the projector. Both very useful for seeing the content more clearly (especially in large lecture theatres), and a really cool thing to show off to students.
Quarto has another layer of plugins on-top of Reveal, allowing for simplified authoring. If a Reveal plugin depended on you writing raw HTML, you might instead have a Quarto plugin implement a script in Lua that converts a simplified syntax into Reveal’s expected syntax. Personally, I find this highly compelling — I really do not want to have to write raw HTML when I’m authoring a presentation.
Reveal plugins unlock a lot of power through Javascript and access to JS libraries, and Quarto’s filters make utilising these libraries far simpler. The combination is honestly shockingly compelling…
Theming
Personally a slight pain-point for me with Reveal.js, as mentioned earlier, is that at the end of the day you have to embrace some web tech. For me, this means accepting that I have to write CSS…
Reveal.js slides are web pages. Just like any web page, you can style it with CSS. If you’re familiar with CSS, this will feel extremely comfortable and familiar, and I’m sure you can achieve a lot of amazing things really easily.
I am not.
I hate CSS.
I have tried my best to make my slides look pretty, but I’m no CSS wizard. I’m sure the web-devs of the world can achieve some excellent things — for me, I’m just happy with my slides looking good enough.
I do occasionally use some simple CSS to achieve some nice designs — Decorating boxes, highlighting text, doing some interesting visuals. Perhaps I’ll demonstrate some fun things in another post.
Workflow
For me, one of the nicest parts of using Quarto is the simple fact that everything is a plaintext.
My slides exist in a git repo. When I’m happy with a slide, I push it to my remote. On the remote, my CI compiles all my slides, and if the compilation succeeds all the slides are rsync’d to my server. For convenience for me, I have it also populate a sitemap of sorts that lets me find all my presentations so I can share and upload links to the slides.
All of this is entirely automated. I also have a modestly customised Docker image with Quarto and some extra Python dependencies, meaning my CI can simply use this image and cutting my build time down to about 40 seconds. When I send a commit, it’s compiled and uploaded to my server in about 2 minutes total.
If I’ve already uploaded a URL to my slides, notice a minor change, and want to quickly fix it, I can simply edit, commit, and get on with my life.
However, I will note that actually, I also upload a PDF of my slides for accessibility to our University’s Moodle, and this does not automatically update. So, for now, the workflow is not fully automated. Suggestions are welcome5.
I should also note that, personally, I have always valued the fact that in Keynote, if I wanted to sit on the sofa with my iPad, or take an iPad to a cafe and type up some thoughts, I could do that. I’ve always enjoyed the flexibility in being able to simply take an iPad and go somewhere comfortable and still feel highly productive.
For Quarto, whilst there are some janky workarounds, for the most part on an iPad you can write the raw QMD, but you cannot render the output and examine it. This means it’s perfectly capable when you’re simply typing up your content, but when you actually want to typeset and layout your slides, then you need a device capable of running the Quarto binary and Pandoc. I might investigate a janky workaround, or possibly even a non-janky workaround, but that’ll be a story for another time.
Thoughts
I won’t lie, a big part of why I’m even writing this article is that Quarto… kind of caught me off guard?
I had tried many tools, including an experiment with using Reveal.js directly, and nothing ever really clicked in the same way that Keynote does. A simple WYSIWYG editor will always have that advantage of just feeling more clean and organic. The workflow is clear.
Reveal.js simply doesn’t have that, and the effort of styling a slide makes the work of building a full slide deck just too tedious for me.
Quarto hit that really rare, spectacular sweet spot for me — writing feels incredibly natural, once you’re familiar laying out slides feels natural, and the nature of essentially plain-text slides makes authoring feel as natural as Keynote’s outline mode I covet so much; If anything, it’s superior because I can also layout my slides!
Quarto really walks that line for me where I can author slides in plain text like LaTeX, but get something far more interesting and dynamic out the other side. For me, that combination makes it extremely compelling.
Personally, now I have invested the time into Quarto and getting my publishing workflow into a place I’m happy with, I don’t see myself changing to anything else any time soon. I think Quarto has nailed exactly what I was looking for all along.
One particular treat with Quarto and Reveal comes from it’s plain-text, web stack underpinnings — With the right knowledge, you can pretty much bend6 Quarto and Reveal into anything you like. HTML, CSS, and Javascript — whatever you want, with enough time, you can shape and reshape your slides into pretty much anything you want.
In the post-AI world, this suddenly makes Quarto a fundamentally different offering; Now you have both a canvas to paint, and clay to reshape7.
In my next post, I’ll discuss some of the ways I’ve found of utilising Quarto with AI to make some much more compelling lecture materials, some of which were simply unachievable before.
I wish the Mac version had the simplified, full-screen experience the iPad has. I honestly find the Mac version pretty finicky and rarely use it. ↩︎
A tight competition with PHP. ↩︎
I have a real love-hate relationship with Python, and the idea of authoring my full lecture slides deck in Marimo is tempting but held back by my issues with Python. It’d still likely need a backend to run on, unless there’s something clever that can be done with Python running under WASM. Hmmmm……… ↩︎
This opens you up to literate programming, which is really awesome! Perhaps not so useful for presentations, but excellent for writing research papers. ↩︎
If your suggestion involved Moodle API access, it’s never gonna happen. Don’t ask. ↩︎
However, bend it far enough and it can break… ↩︎
All of these changes were achievable before AI, but the upfront cost was often too high to justify. AI lowers that cost significantly, if you’re open to exploration. ↩︎