📖 Read the Deep-Dive: I built a minimal zero-dependency PDF library for C# because I hate bloat.
A minimal PDF creation library for .NET 10, ported from the original tinypdf by Lulzx.
- 1041 lines of code
- Zero external dependencies
- Text rendering (
Helvetica,Times,Courier) with alignment support - Clickable links with optional underlining
- Shapes (Rectangles, Lines, Circles, Wedges)
- JPEG images
- Optional Flate (deflate) compression for PDF streams
- Markdown to PDF conversion
- Multiple pages with custom sizes
This project targets .NET 10.
Install the package via the .NET CLI:
dotnet add package TinyPdfAlternatively, you can add the TinyPdf.csproj to your solution and reference it from your project:
dotnet add reference ../src/TinyPdf/TinyPdf.csprojusing TinyPdf;
var builder = TinyPdfCreate.Create();
// disable compression if you need uncompressed streams
// builder.Compress = false;
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);using TinyPdf;
// disable compression via options
var options = new TinyPdfCreate.MarkdownOptions(Compress: false);
string md = "# Header\n\nThis is a paragraph.\n\n- List item";
byte[] pdf = TinyPdfCreate.Markdown(md, options);
File.WriteAllBytes("markdown.pdf", pdf);builder.Page(842, 595, ctx => { // A4 Landscape
ctx.Line(0, 0, 842, 595, "#0000FF", 2);
});builder.Page(ctx => {
// ctx.Circle(cx, cy, radius, fill, stroke, lineWidth)
ctx.Circle(100, 700, 50, "#3498db");
// ctx.Wedge(cx, cy, radius, startAngle, endAngle, fill, stroke, lineWidth)
ctx.Wedge(300, 700, 50, 0, 90, "#e74c3c", "#000000", 2);
});builder.Page(ctx => {
ctx.Text("Visit our website", 50, 700, 12);
// Link(url, x, y, width, height, options)
ctx.Link("https://github.com/ian-cowley/tinypdf-csharp", 50, 700, 100, 12, new TinyPdfCreate.LinkOptions(Underline: "#2563eb"));
});From the repository root run:
dotnet testTo run the high-concurrency performance tests (1000 iterations per example):
dotnet run --project benchmarks/PerformanceTests/PerformanceTests.csprojAlternatively, to run the BenchmarkDotNet suite:
dotnet run -p benchmarks/TinyPdf.BenchmarksThe following results were obtained by generating 1000 PDFs for each example in parallel:
| Example | Iterations | Total Time (ms) | Avg Time (ms) | Complexity |
|---|---|---|---|---|
| Invoice | 1000 | 270.48 | 0.2705 | Methods: ~320 |
| Letter | 1000 | 146.33 | 0.1463 | Markdown: ~60 lines |
| PieChart | 1000 | 40.10 | 0.0401 | Methods: ~20 |
| Receipt | 1000 | 35.31 | 0.0353 | Methods: ~18 |
| Report | 1000 | 44.86 | 0.0449 | Methods: ~56 |
| Resume | 1000 | 99.03 | 0.0990 | Markdown: ~100 lines |
To release a new version to NuGet and GitHub:
- Open PowerShell in the repository root.
- Run:
./release.ps1 - Follow the prompts for the commit message.
The script will automatically increment the patch version, commit, push, and create a GitHub tag, which triggers the CI/CD workflow.
This C# port preserves the core logic of the original TypeScript library (font width tables and PDF object serialization) so generated PDFs are compatible in structure. The library is intentionally small and dependency-free to keep it easy to embed in small projects.
By default output streams are compressed (FlateDecode) — set builder.Compress = false or pass new TinyPdfCreate.MarkdownOptions(Compress: false) to TinyPdfCreate.Markdown to disable compression.
Security: do not commit secrets or sensitive configuration to this repository. Use dotnet user-secrets or environment variables for local development.