# Markpdf: a best in class Markdown -\> PDF tool

**URL:** <https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133>\
**Category:** Offtopic\
**Tags:** announces\
**Created:** [September 5, 2026, 9:21pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133 "2026-09-05T21:21:42Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 5, 2026, 9:21pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/1 "2026-09-05T21:21:42Z")

</div>

Markpdf is currently part of [GitHub - ralsina/markterm · GitHub](http://github.com/ralsina/markterm) (along with markterm and markmark)

It’s a markdown-\>PDF converter based on [litehtml](http://www.litehtml.com/) and [libharu](https://libharu.org/)

It parses markdown using markd then takes the HTML and uses libhtml to do layout and finally libharu to create a PDF.

Some of the highlights:

- Can create a 600 A4 page PDF of Brothers Karamazov in under 5 seconds.
- Tables
- Footnotes
- Annotations
- Fenced code blocks with syntax highlighting
- Inline and display math (cheating via [libtexprintf](https://github.com/bartp5/libtexprintf/)
- Fully justified with hyphenation (includes implementation of the TeX hyphenation algorithm)
- Outline based on headings
- Multiple image types, including svg (requires external tool)
- Inline HTML rendered
- HTML blocks rendered
- emoji, accents, CJK
- Page breaking with widow heading prevention
- Pageless mode: all your PDF is a single page. Yes, you can do a page with all of Brothers Karamazov in it.
- CSS stylesheets (a few included, user can add customized)
- Color schemes

There isn’t AFAIK, a tool with this much feature coverage that doesn’t involve installing chrome or TeX or Typst. Markpdf is a 9MB static binary.

Here is an example of how the output looks:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/2X/f/fe3d6f3c881bae452bd2e2d4c04603e270f7ab4d.jpeg)

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [September 6, 2026, 5:50am UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/2 "2026-09-06T05:50:58Z")

</div>

As someone who uses Pandoc with Docker, I’m somewhat interested in this tool, but I’m not sure if it’s right for me. A website where you can view sample PDFs created with markpdf might be helpful for people who are on the fence about trying it out.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 6, 2026, 7:22am UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/3 "2026-09-06T07:22:47Z")

</div>

There will be, at some point.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 6, 2026, 8:44pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/4 "2026-09-06T20:44:07Z")

</div>

There is now. Demo with full server-side rendering, can tweak the contents, look, templates, whatever.

> **[markpdf — Markdown to beautiful PDFs](https://markpdf.ralsina.me/)**
>
> markpdf turns Markdown into beautiful, print-ready PDFs. Edit markdown, tweak the styling knobs, and see the output live.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 6, 2026, 9:31pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/5 "2026-09-06T21:31:15Z")

</div>

Great hat-tip to @sdogruyol and the kemal project, which makes this sort of thing easy and enjoyable to create

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [September 6, 2026, 9:45pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/6 "2026-09-06T21:45:47Z")

</div>

I made a similar tool many years ago: [GitHub - straight-shoota/md2pdf: Convert markdown files to pdf with flexible template and stylesheet · GitHub](https://github.com/straight-shoota/md2pdf)  
It’s built on Crystal with markd as well, so I suppose it ticks most of the above features.  
But I used wkhtmltopdf for rendering. So not the entire Chrome browser, but the webkit engine. I don’t think that exists anymore. It was perhaps a bit easier to just delegate layout and rendering to a single library.

On top, it also integrates [Crinja](https://github.com/straight-shoota/crinja) for templating. Maybe that could be an inspiration for markpdf? 😉

---

<div class="post-metadata">

**Author:** ![Sija](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/sija/32/737_2.png) [@Sija](https://forum.crystal-lang.org/u/Sija)\
**Post date:** [September 6, 2026, 9:55pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/7 "2026-09-06T21:55:42Z")

</div>

Emojis are broken :(

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/2X/6/64334663f20464c9a426f7e2b650eedf6911fc96.png)

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 6, 2026, 10:07pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/8 "2026-09-06T22:07:21Z")

</div>

Probably lacking a font in the docker image :-)

I’ll look into it

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 6, 2026, 10:08pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/9 "2026-09-06T22:08:16Z")

</div>

I am half decided to support short codes (which are a way to embed crinja templates) but honestly it was so much work getting it to this stage I am hesitant.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 7, 2026, 12:17am UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/10 "2026-09-07T00:17:01Z")

</div>

Fixed!

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 7, 2026, 12:18am UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/11 "2026-09-07T00:18:20Z")

</div>

Just noticed, this is where I got the idea! Thanks @hugopl !!!

> [@A small utility to convert markdown to html (for publishing on social media, Medium, etc)](https://forum.crystal-lang.org/t/a-small-utility-to-convert-markdown-to-html-for-publishing-on-social-media-medium-etc/4543/4):
>
> I have a pet project on my queue waiting for years… that is get [GitHub - litehtml/litehtml: Fast and lightweight HTML/CSS rendering engine](https://github.com/litehtml/litehtml) and some library that can generate pdfs and create a HTML-\>pdf renderer that doesn’t depend on X, Qt, GTK, etc… i.e. doesn’t depend on wkhtmltopdf. But unfortunately this project couldn’t be written in Crystal because the idea is to expose a C API, so any other language could use it with no problems.

---

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [September 7, 2026, 2:13pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/12 "2026-09-07T14:13:31Z")

</div>

Thank you for implementing something I wanted but would never have time to do so… at least until my kids grow.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 7, 2026, 2:26pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/13 "2026-09-07T14:26:03Z")

</div>

Mine’s 19, so keep hope! 🙂

---

<div class="post-metadata">

**Author:** ![beta-ziliani](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/beta-ziliani/32/1821_2.png) [@beta-ziliani](https://forum.crystal-lang.org/u/beta-ziliani)\
**Post date:** [September 8, 2026, 11:58am UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/14 "2026-09-08T11:58:43Z")

</div>

![imagen](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/2X/d/da62ba89322858b627c90794f7b3890d92a3a924.png)

The footnote is not on the foot 😊 but maybe is the issue with a text that span just a tiny bit over a page?

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 8, 2026, 12:09pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/15 "2026-09-08T12:09:58Z")

</div>

They are technically endnotes :-)

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [September 18, 2026, 12:45pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/16 "2026-09-18T12:45:24Z")

</div>

This command-line tool is handy, and I like the concept behind it. However, I’ve run into a few minor issues when trying to use it on macOS or when working with Japanese text, so I might submit a few pull requests in the future.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [September 18, 2026, 1:15pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/17 "2026-09-18T13:15:06Z")

</div>

There is no text shaping so support for some scripts is … iffy.

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [October 11, 2026, 6:54pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/18 "2026-10-11T18:54:09Z")

</div>

Now with decent math:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/2X/8/86e2d71f0a932f4dbc2ede945a279dc1e90c0f6e.png)

And without TeX!

Ok, it links in MicroTeX, which is a C++ library and does a bridge to libharu so the output looks nice in the PDF

---

<div class="post-metadata">

**Author:** ![paulocoghi](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/paulocoghi/32/1429_2.png) [@paulocoghi](https://forum.crystal-lang.org/u/paulocoghi)\
**Post date:** [October 12, 2026, 6:59pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/19 "2026-10-12T18:59:39Z")

</div>

@ralsina is it possible to use it with a set of formatting rules, in my case for scientific / academic papers, when generating the PDF from a markdown?

---

<div class="post-metadata">

**Author:** ![ralsina](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ralsina/32/2139_2.png) [@ralsina](https://forum.crystal-lang.org/u/ralsina)\
**Post date:** [October 12, 2026, 8:02pm UTC](https://forum.crystal-lang.org/t/markpdf-a-best-in-class-markdown-pdf-tool/9133/20 "2026-10-12T20:02:20Z")

</div>

It supports CSS (within limits)
