DEV Community

Ian Cowley
Ian Cowley

Posted on

I built a minimal, zero-dependency PDF library for C# because I hate bloat

I built a minimal, zero-dependency PDF library for C# because I hate bloat

If you’ve been writing C# for a while, you know the drill. You need to generate a simple PDF—maybe an invoice, a quick report, or a receipt.

So, you open up NuGet, search for "PDF", and suddenly you are staring down the barrel of a 50MB dependency, a labyrinth of complex object models, and licensing terms that require a law degree to understand.

I’ve been a developer for 40 years. I mostly work on backend and integration software for the printing industry. I like keeping things close to the metal, and I generally despise pulling in massive frameworks when a pragmatic, lightweight solution will do the trick.

I didn't want a bloated library. I just wanted to draw some text, a few shapes, and maybe throw an image on a page.

So, I ported a minimal PDF generator to .NET 10. Meet tinypdf-csharp.

What is it?

It is a C# port of the original TypeScript tinypdf by Lulzx. But I didn't just translate it; I added a few quality-of-life features that make it significantly more useful for day-to-day backend development.

The entire library is just over 1,000 lines of code. It has zero external dependencies.

The "Batteries Included" Additions

While the original architecture was beautifully simple, I needed it to do a bit more heavy lifting for real-world tasks. Here is what I added over the original:

  • Markdown to PDF: This is my favorite addition. You can pass a raw Markdown string into the library, and it handles the layout and spits out a formatted PDF.
  • Flate (Deflate) Compression: Automatically compresses the PDF streams so your file sizes stay tiny. (You can toggle it off if you need raw streams).
  • Clickable Links: Full support for clickable hyperlinks, complete with optional underline styling.

Plus, it still has all the basics: text rendering (Helvetica, Times, Courier), shapes (rectangles, circles, wedges, lines), and JPEG image embedding.

Show me the code

It is designed to be ridiculously simple to use. Here is how you generate a PDF with some text and a red box:

using TinyPdf;

var builder = TinyPdfCreate.Create();

builder.Page(ctx => {
    ctx.Text("Hello World", 50, 700, 24);
    ctx.Rect(50, 650, 100, 20, "#FF0000");
});

byte[] pdf = builder.Build();
File.WriteAllBytes("output.pdf", pdf);

Enter fullscreen mode Exit fullscreen mode

Or, if you want to use the Markdown converter:

using TinyPdf;

string md = "# Header\n\nThis is a paragraph.\n\n- List item";
byte[] pdf = TinyPdfCreate.Markdown(md);
File.WriteAllBytes("markdown.pdf", pdf);

Enter fullscreen mode Exit fullscreen mode

Is it fast?

Because there's no massive object tree or bloated memory footprint, it flies. I ran a benchmark generating 1,000 multi-page invoice PDFs concurrently, and it finished in ~270 milliseconds. That’s 0.27ms per PDF. If you are generating receipts or pie charts, it drops to around 0.03ms per PDF.

Try it out

If you are building a microservice, an AWS Lambda, or a simple backend integration and you just need to spit out PDFs without sacrificing your app's payload size, give it a try.

NuGet:

dotnet add package TinyPdf

Enter fullscreen mode Exit fullscreen mode

GitHub: ian-cowley/tinypdf-csharp

Drop by the repo, take a look at the code (again, it's only ~1000 lines, so you can read the whole thing on your lunch break), and let me know what you think. If it saves you from installing a massive legacy PDF framework today, my job is done.

Top comments (0)