A fully reproducible Markdown presentation environment

Hey everyone,

I’ve been working on a little side project during my time off, and I wanted to share it with the community.

I often present technical topics at work, but I’ve never liked PowerPoint, Google Slides, and similar tools. As a Nix enthusiast and Kubernetes/DevOps lead, it always feels clumsy to rely on WYSIWYG editors. It’s not code, it’s not reproducible: it’s a liability.

I found Marp a few years back and immediately adopted it to write and generate my slides. But I found myself constantly copying assets, snippets, and themes back and forth between presentations. I also always had to dig through online documentation or CLI help commands to remember how to do anything. And ultimately, without a pinned toolchain, it still wasn’t truly reproducible. Frustrating.

To solve this once and for all, I put together Marp Deck Directory, a public template that combines Marp with the absolute guarantees of Nix flakes. The goal is to store all your slide decks and assets in one place, and be guaranteed you can generate them identically 5 years from now.

Live Demo (built via GH Actions): Marp Deck Directory Introduction

The core of the project is a single derivation which dynamically discovers decks under the slides/ directory and builds them into HTML or PDF. It also dynamically generates cover images for your decks (either taken from the first slide or a dedicated Markdown file). The derivation handles intelligent path rewriting so you can seamlessly mix global assets (/assets) and deck-specific local assets without breaking local dev previews.

Because Nix builds run without network access, everything must be available offline, so I built a small derivation to vendor Twemoji assets locally during the build (during local dev preview, it just uses the online version).

I also had to create a small wrapper around the Brave browser (which is Chromium-based) to disable sandboxing (--no-sandbox), since normal sandboxing fails inside isolated Nix builds. Why Brave, you ask? Because Chromium isn’t natively available on aarch64-darwin, and headless Firefox currently struggles on Darwin (plus Marp rendering on Firefox differs from Chromium). So Brave was the safest cross-platform bet, though you can easily swap it for any Chromium-based browser.

Oh, one last thing! The template comes bundled with Catppuccin themes for Marp, which I built specifically for this project and is currently in the process of being handed over to the Catppuccin organization as an official port!

I’d love to get feedback from the community on the derivation structure (specifically in pkgs/slides.nix where the deck discovery and path rewriting happens). Let me know what you think! And if you wish to use this template, I’d love to hear about it!

10 Likes

Does it have feature parity with marp? If yes, I’m happy to try switching.

Yes, absolutely 100% feature parity!

It actually uses the official Marp CLI under the hood. The project doesn’t fork or replace Marp, it’s simply a Nix template (essentially some fancy Nix glue!) around Marp to handle the file discovery, offline Twemoji derivation, and cross-platform PDF browser setup so it’s perfectly reproducible.

Anything you currently do in Marp (directives, custom CSS, themes, scoped styles, etc.) will work exactly the same here.

I’d be thrilled if you tried switching over, let me know if you run into any friction porting your existing decks!

EDIT

Just realized I should mention one small caveat: the only Marp feature you can’t use directly is the CLI --preview window. You have to use the --server mode instead (which is wrapped by the serve command in the devshell).

The reason is that mixing global (/assets/...) and deck-specific local assets doesn’t work in --preview mode. Marp’s preview strictly expects all assets (even font imports inside CSS files) to be relative to the source Markdown file. It’s practically impossible to share global assets across different directory levels this way, so using the server mode maps the file system correctly!

Sweet! I’ll give this a try for my next presentation then.

1 Like

I would like to see a project like this for Typst.

I’ve heard a bit about Typst but don’t know/use it personally.

I’m heavily invested in the Markdown/CSS ecosystem of Marp and already have a backlog of presentations in that format, hence this project.

But I believe something similar could be built for Typst, based on Marp Deck Directory. In the end, the recursive file discovery, managing local vs. global assets, and automatically generating outputs for a CI pipeline is actually pretty engine-agnostic.

I won’t build a Typst version myself, but if you (or anyone else reading this!) wanted to fork this repo, strip out the marp-cli/Brave bits in pkgs/slides.nix, and slot the typst compiler in… it may very well work from the get-go.

If you ever end up building it, definitely drop a link. I’d love to see it!

What’s the reason you prefer typst over markdown? Is it specifically for mathematical and scientific notation symbols, or something else?

1 Like

I just like the Typst ecosystem. I do all my texts and presentations in Typst and I also need the mathematical notations symbols. But the ecosystem is a great Tool far more powerful than markdown.

1 Like