Charta 1.14.0

dotnet add package Charta --version 1.14.0
                    
NuGet\Install-Package Charta -Version 1.14.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Charta" Version="1.14.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Charta" Version="1.14.0" />
                    
Directory.Packages.props
<PackageReference Include="Charta" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Charta --version 1.14.0
                    
#r "nuget: Charta, 1.14.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Charta@1.14.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Charta&version=1.14.0
                    
Install as a Cake Addin
#tool nuget:?package=Charta&version=1.14.0
                    
Install as a Cake Tool

Charta

NuGet Downloads CI License: MIT

A permanently-MIT PDF generation library for .NET — fluent layout API, zero native dependencies, streaming output, NativeAOT-ready.

Why Charta? Every free .NET PDF option forces a trade-off: the modern fluent engine is revenue-gated, the permissive veteran has no layout engine or text shaping, the feature king is AGPL. Charta is MIT forever — no revenue thresholds, no dual-license switch — with a 166KB package that depends on nothing but the BCL.

Quick start

using Charta;

var result = Document.Create(doc =>
{
    doc.Page(page =>
    {
        page.Size(PageSizes.A4);
        page.Margin(2, Unit.Centimeter);
        page.Header().Text("Invoice #1042").FontSize(20).Bold();
        page.Content().Column(col =>
        {
            col.Spacing(10);
            col.Item().Text("Thanks for your purchase! Line breaking, kerning, and pagination are automatic.");
            col.Item().LineHorizontal(1);
            col.Item().Row(row =>
            {
                row.RelativeItem().Text("Total");
                row.ConstantItem(120).AlignRight().Text("€ 1.250,00").Bold();
            });
        });
        page.Footer().AlignCenter().Text("Page footer").FontSize(9);
    });
}).GeneratePdf("invoice.pdf");

// result.Diagnostics tells you if anything didn't fit — Charta clips and reports, it never throws.

Fonts resolve against explicitly registered files first (FontManager.RegisterFont(...) — the reproducible path for servers and containers), then against the operating system's installed fonts. Registered TrueType fonts are always subset and embedded.

Script support today

Scripts Status
Latin (incl. Turkish, Polish, Vietnamese), Cyrillic, Greek ✅ Full: correct rendering, kerning, and text extraction
CJK ✅ Rendering, UAX#14 line breaking, and extraction (no vertical text yet)
Hebrew and mixed-direction text ✅ Built-in UAX#9 bidi (100% conformant): correct reading order, mirrored brackets, correct extraction
Arabic, Indic, and other joining scripts ✅ with the Charta.Shaping.HarfBuzz add-on — cursive joining, contextual forms, and marks. Without it, reading order is correct but letters render unjoined and a LayoutDiagnostic says so.
// Enable full shaping for Arabic/Indic (optional add-on, one line at startup):
Charta.Shaping.HarfBuzz.ChartaHarfBuzz.Register();

Why another PDF library?

Every free .NET PDF option forces a trade-off: a modern fluent layout engine is revenue-gated, the permissively-licensed veteran has no modern layout engine or text shaping, and the most feature-complete library is AGPL. Charta aims to close that gap: a document generation engine that is MIT forever, has no revenue thresholds, no native binary payload in the core package, and treats digital signatures, complex-script text, and PDF/A + PDF/UA compliance as first-class free features.

Cookbook

Tables

page.Content().Table(table =>
{
    table.ColumnsDefinition(cols =>
    {
        cols.RelativeColumn(3);
        cols.ConstantColumn(80);
        cols.RelativeColumn();
    });
    table.Header(header =>            // repeats at the top of every page
    {
        header.Cell().Background(Color.FromHex(0x1E5AA8)).Padding(6)
              .Text("Product").FontColor(Color.White).Bold();
        // ...
    });
    foreach (var row in rows)
    {
        table.Cell().Padding(6).Text(row.Name);
        table.Cell().Padding(6).AlignRight().Text($"{row.Qty}");
        table.Cell().Padding(6).AlignRight().Text($"{row.Total:N2}");
    }
});

Cells are ordinary containers (Padding, Background, Border, … all work) and support ColumnSpan/RowSpan. Rows joined by a rowspan paginate as one unbreakable band.

Page numbers and rich text

page.Footer().Text(t =>
{
    t.AlignCenter();
    t.Span("Page ").FontSize(9);
    t.CurrentPageNumber().FontSize(9).Bold();
    t.Span(" of ").FontSize(9);
    t.TotalPages().FontSize(9);       // triggers an automatic counting pass
});

Vector graphics and SVG

Draw vectors directly, or drop in an SVG (both managed, no extra dependency):

page.Content().Width(150).Svg(File.ReadAllText("logo.svg"));

page.Content().Canvas(300, 120, canvas =>
{
    canvas.Rectangle(10, 10, 80, 100).Fill(Color.FromHex(0x1E5AA8));
    canvas.Circle(200, 60, 40).FillAndStroke(Color.White, Color.Black, 2);
});

PDF/A archival compliance

Target PDF/A-2b for long-term archival — embedded sRGB output intent, pdfaid metadata, embedded fonts, validated by the official veraPDF validator in CI:

Document.Create(doc =>
{
    doc.Metadata(m => m.Title("Archived report"));
    doc.Page(page => page.Content().Text("..."));
}).GeneratePdf("archive.pdf", new PdfSaveOptions { Conformance = PdfConformance.PdfA2b });

Use a font that covers every character you render — PDF/A forbids showing the .notdef glyph, and Charta raises a layout diagnostic naming the page if any text would render as .notdef under a conformance level.

PDF/UA accessible (tagged) documents

Target PDF/UA-1 for accessibility — a full structure tree derived from the layout, marked content, /Lang, DisplayDocTitle, and decorations tagged as artifacts, validated by veraPDF in CI. A title is required; tag headings with .Heading(1..6) and give figures alternate text:

Document.Create(doc =>
{
    doc.Metadata(m => m.Title("Accessible report"));
    doc.Page(page => page.Content().Column(col =>
    {
        col.Item().Text("Quarterly results").FontSize(20).Heading(1);
        col.Item().Text("...");
        col.Item().Image("chart.png", altText: "Bar chart of revenue by quarter.");
    }));
}).GeneratePdf("accessible.pdf", new PdfSaveOptions
{
    Conformance = PdfConformance.PdfUA1,
    Language = "en-US",
});

Digital signatures

The optional Charta.Signing add-on signs a document with an X.509 certificate — a PAdES B-B signature, built on the .NET crypto stack (no BouncyCastle, no native dependencies):

using Charta.Signing;

var signer = PdfSigners.FromCertificate(certificate);
Document.Create(doc => /* ... */)
    .GenerateSignedPdf("signed.pdf", signer, new SignatureInfo { Reason = "Approval" });

Add a trusted RFC 3161 timestamp (PAdES B-T) by passing a timestamp authority — the signing time is then asserted by a third party, not the signer:

var tsa = TimestampAuthorities.Http(new Uri("https://freetsa.org/tsr"));
var signer = PdfSigners.FromCertificate(certificate, timestampAuthority: tsa);

Encryption

Protect a document with a password — AES-256 (the PDF 2.0 security handler, V5/R6), on the BCL crypto stack, no dependencies. Set a separate owner password to enforce permissions against readers who only have the user password:

Document.Create(doc => /* ... */)
    .GeneratePdf("protected.pdf", new PdfSaveOptions
    {
        Encryption = new PdfEncryption
        {
            UserPassword = "open-me",
            OwnerPassword = "full-control",
            Permissions = PdfPermissions.Print | PdfPermissions.Copy,
        },
    });

Encryption cannot be combined with a signature or a PDF/A / PDF/UA level (those forbid it), and encrypted output is not byte-reproducible — fresh random salts and keys are generated each time.

HTML to PDF

The optional Charta.Html add-on renders a subset of HTML/CSS. AngleSharp parses the markup; the cascade and layout are Charta's own — no browser, no native code. Unsupported features are reported, never thrown:

using Charta.Html;

Document.Create(doc => doc.Page(page => page.Content().Html("""
    <style>h1 { color: #003366 } .lead { color: #555 }</style>
    <h1>Report</h1>
    <p class="lead">A <b>bold</b> word and a <a href="https://example.com">link</a>.</p>
    <ul><li>first</li><li>second</li></ul>
    """))).GeneratePdf("page.pdf");

Covers block flow, inline styling, lists, tables (with colspan/rowspan), rules, and images, with type/.class/#id selectors. See the package readme for the full support matrix.

Fonts on servers and in Docker

Register fonts explicitly — output becomes reproducible and independent of what the host has installed. Registered fonts are always subset and embedded:

FontManager.RegisterFontFile("fonts/Inter-Regular.ttf");
FontManager.RegisterFontFile("fonts/Inter-SemiBold.ttf");
FontManager.RegisterFontFile("fonts/Inter-Bold.ttf");
// The first registered family is also the default when no FontFamily(...) is set.

.Bold(), .SemiBold(), and .Italic() select a face by weight and style. Resolution matches the nearest registered weight on the OS/2 axis (SemiBold is 600, Bold is 700), so register the face you want to use — Charta never synthesizes a heavier weight from a lighter one.

Without registration Charta falls back to OS fonts (Windows font directory, fontconfig on Linux, macOS font folders — no native calls).

When something doesn't fit

Charta never throws for layout problems. Content that cannot fit even a full page is clipped and reported in result.Diagnostics with what/where/why; treat a non-empty list as a warning in development and log it in production. Prefer exceptions in CI? Opt in with new PdfSaveOptions { Overflow = OverflowBehavior.Throw }. To see where content was clipped, turn on new PdfSaveOptions { DebugLayout = true } — clipped regions get a red overlay in the output.

Text supports letter-spacing (.LetterSpacing(2)), and rich-text spans support .Superscript() / .Subscript(), underline, and strikethrough.

Design principles

  • MIT forever. No dual-license switch, no revenue gates. The trademark is the only reserved right.
  • Zero dependencies in the core. The Charta package references nothing but the BCL. Optional capabilities (HarfBuzz shaping, HTML rendering) live in opt-in add-on packages.
  • Never throw on overflow. Content that does not fit is clipped, shrunk, or expanded according to policy — and reported through layout diagnostics. Exceptions are opt-in, for CI strictness.
  • Streaming by default. Pages are serialized and flushed as they finish. Memory stays flat whether the document has 5 pages or 5,000.
  • NativeAOT and trimming clean. No reflection, no runtime code generation. Verified by a publish-and-run gate in CI.

Roadmap

Milestone Scope
M0 Walking skeleton: streaming COS writer, valid "Hello PDF"
M1 Real text: font parsing, subsetting, embedding; images
M2 Layout engine: measure/arrange, pagination, overflow policy
M3 Fluent API, first NuGet release
M4 Tables with correct rowspan pagination
M5 Digital signatures (PAdES B-B/B-T)
M6 RTL and complex-script shaping (optional add-on)
M7 PDF/A-2b/3b and PDF/UA
M8 HTML/CSS subset rendering

License

MIT © Utku Çelebi

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Charta:

Package Downloads
Charta.Html

HTML/CSS subset rendering for Charta: turn a fragment of HTML — headings, paragraphs, lists, tables, inline styling, images and links — into a laid-out PDF. Parses with AngleSharp; the cascade and layout are Charta's own. Unsupported features are reported as diagnostics, never thrown.

Charta.Shaping.HarfBuzz

HarfBuzz text shaping for Charta: correct cursive joining and mark positioning for Arabic, Indic, and other complex scripts. Reference this package and call ChartaHarfBuzz.Register().

Charta.Signing

PAdES digital signatures for Charta: sign generated PDFs with an X.509 certificate. Uses only the .NET cryptography stack — no BouncyCastle, no native dependencies.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.14.0 131 7/20/2026
1.13.0 119 7/10/2026
1.12.0 122 7/10/2026
1.11.0 126 7/10/2026
1.10.1 111 7/10/2026
1.10.0 103 7/10/2026
1.9.0 104 7/10/2026
1.8.0 127 7/10/2026
1.7.0 122 7/10/2026
1.6.0 105 7/10/2026
1.5.0 122 7/10/2026
1.4.0 101 7/9/2026
1.3.0 104 7/9/2026
1.2.0 126 7/9/2026
1.1.0 126 7/9/2026
1.0.0 114 7/9/2026

See CHANGELOG.md in the repository.