In the hunt for an open-source, free PDF generation solution, developers often face a maze of complexities. QuestPDF emerges as a beacon of hope in this landscape, distinguishing itself by leveraging SkiaSharp’s power for crafting immaculate PDFs. Unlike conventional HTML-to-PDF tools, QuestPDF sidesteps these challenges, offering a smoother path devoid of HTML interpretation quirks. With its direct rendering approach, it effortlessly handles intricate designs and layouts, freeing developers from convoluted APIs and steep learning curves. QuestPDF, backed by SkiaSharp, simplifies PDF generation woes, offering a reliable and efficient solution in a chaotic arena of document creation frameworks.

If you’re currently on the lookout for a robust PDF generation library, you should check out my article.

A License Tailored for Growth
#

For companies operating with an annual gross revenue of less than $1M USD, QuestPDF extends an open hand — a free passage under the liberating MIT license. It’s not just a gesture of goodwill; it’s a deliberate step towards supporting emerging ventures on their journey to success.

Uniting Technology and Continuity
#

Built upon the foundation of .NET 6, QuestPDF is usable in a wide range of applications. It can be easily used under .NET 8 without any problems and additional tools needed, and is therefore a good ally.

Empowering Ambitions, Unshackling Creativity
#

QuestPDF aims not only to level the playing field but also to fuel the aspirations of those charting new territories.

Step beyond the threshold; embrace a domain where innovation is unbound. With QuestPDF’s free Community License, barriers dissolve, paving the way for limitless creativity and unfettered exploration.

A Solid Starting Point for Document Development
#

Some things are better experienced than merely explained. For those eager to delve deeper and explore the code firsthand, the entire example is available on GitHub for your perusal and testing: QuestPDF Sample on GitHub.

Create a new .NET 8 Console Application

1
dotnet new console -n QuestPDFSampleAppcd QuestPDFSampleApp

Add the QuestPDFNuGet Packages

1
dotnet add package QuestPDF

Install the QuestPDF.Previwer via dotnet CLI for later use

1
dotnet tool install QuestPDF.Previewer -g

Open the solution in your preferred IDE and start with the following steps:

Create a simple DocumentModel and an AddressModel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class DocumentModel
{
    public string Name { get; set; } = null!;
    public AddressModel Address { get; init; } = null!;
}

public class AddressModel
{
    public string CompanyName { get; init; } = null!;
    public string Street { get; init; } = null!;
    public string City { get; init; } = null!;
    public string State { get; init; } = null!;
    public string Email { get; init; } = null!;
    public string Phone { get; init; } = null!;
}

Create a simple DocumentDataSource:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DocumentDataSource
{
    public static DocumentModel GetDetails()
    {
        return new DocumentModel
        {
            Name = Placeholders.Name(),
            Address = GenerateRandomAddress()
        };
    }
    
    private static AddressModel GenerateRandomAddress()
    {
        return new AddressModel
        {
            CompanyName = Placeholders.Name(),
            Street = Placeholders.Label(),
            City = Placeholders.Label(),
            State = Placeholders.Label(),
            Email = Placeholders.Email(),
            Phone = Placeholders.PhoneNumber() 
        };
    }
}

Create the Document and begin with a simple implementation of a page with margins, header and footer. A good starting point should be the following sample:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;

public class Document : IDocument
{
    private readonly DocumentModel _model;

    public MyDocument(DocumentModel model)
    {
        _model = model;
    }

    public Document(DocumentModel model)
    {
        _model = model;
    }

    public DocumentMetadata GetMetadata() => DocumentMetadata.Default;

    public void Compose(IDocumentContainer container)
    {
        // Implement document composition using container
        // Add pages, headers, footers, etc.

        container
            .Page(page =>
            {
                page.Margin(50);

                page.Header().Element(ComposeHeader);
                page.Content().Element(ComposeContent);

                page.Footer().AlignCenter().Text(text =>
                {
                    text.CurrentPageNumber();
                    text.Span(" / ");
                    text.TotalPages();
                });
            });
    }

    private void ComposeHeader(IContainer container)
    {
        container.PaddingBottom(24).Row(row =>
        {
            row.RelativeItem().Column(column =>
            {
                column
                    .Item().Text($"Data Protection")
                    .FontSize(20).SemiBold().FontColor(Colors.Blue.Medium);
            });
        });
    }


    private void ComposeContent(IContainer container)
    {
        container.Column(column =>
        {
            column.Spacing(48);
            column.Item().Element(ComposeDescription);
            column.Item().Element(ComposeInputs);
            column.Item().Text(Placeholders.Paragraphs());

            column.Item().Element(ComposeSignature);
        });
    }



    public class InputComponent : IComponent
    {
        private readonly string _label;

        public InputComponent(string label)
        {
            _label = label;
        }
        
        public void Compose(IContainer container)
        {
            container.Row(row =>
            {
                row.ConstantItem(100).AlignLeft()
                    .Text($"{_label}:")
                    .SemiBold();
                
                row.RelativeItem(10)
                    .ExtendHorizontal()
                    .BorderBottom(1).Padding(5)
                    .Background(Colors.Grey.Lighten1)
                    .AlignCenter();
            });
        }
    }

    // Implement other methods of IDocument for metadata or settings if needed
}

Last but not least and essential for our protoyping, we need to setup and generate our PDF generation. In our Program.cs., we implement the following code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
using QuestPDF.Export;

Settings.License = LicenseType.Community;

var documentModel = new DocumentModel();
var document = new MyDocument(documentModel);

// Generate and show the PDF
document.GeneratePdfAndShow();
// Or to use the previewer
// await document.ShowInPreviewerAsync();

What you see is what you get
#

The QuestPDF.Previewer with the Document we will create
The QuestPDF.Previewer with the Document we will create

In the realm of document creation, the ability to easily review and visualize your work is paramount. QuestPDF acknowledges this need and offers a solution that bypasses the labyrinth of trial and error: the QuestPDF.Previewer. If you followed all steps, you have already installed it. Now it is time to use it.

Integrating the capability for instant visualization of your work within your code is straightforward:

1
2
// Or to use the previewer
await document.ShowInPreviewerAsync();

This serves as an exceptional launching pad for anyone stepping into the realm of document development. It provides a practical and tangible introduction to utilizing the QuestPDF library, allowing you to experiment not only with the library itself.

Launching the application streamlines the entire process. Thanks to the Hot Reload functionality, widely supported by the most popular Integrated Development Environments (IDEs), crafting the document you envision becomes effortless, devoid of cumbersome trial-and-error iterations.

Special thanks to QuestPDF for providing a powerful library for PDF generation.