Metadata
This page explains how to add metadata to PDF documents with rix/pdf.
The examples use the public Rix facade:
#include <rix.hpp>and access PDF through:
rix.pdfPDF metadata helps describe a generated document. It can include the title, author, subject, creator, and keywords.
Basic metadata example
Create a file:
mkdir -p ~/rix-pdf-metadata
cd ~/rix-pdf-metadata
touch metadata.cpp2
3
Add:
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Rix PDF Metadata Example")
.set_author("Rix")
.set_subject("PDF metadata")
.set_keywords("rix,pdf,vix,cpp");
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Metadata",
1);
y -= 10.0F;
page.paragraph(
page.x_left(),
y,
page.content_width(),
"This PDF includes title, author, subject, creator, and keyword metadata.");
auto saved = rix.pdf.save(doc, "metadata.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "metadata.pdf");
return 0;
}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
Run it:
vix run metadata.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run metadata.cpp2
This creates:
metadata.pdfWhat metadata is
Metadata is information about the PDF document.
It is not the visible page content.
Visible content is added with pages:
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Visible text");2
3
4
5
6
Metadata is added to the document itself:
doc.set_title("Document title");
doc.set_author("Rix");2
PDF viewers may display this information in document properties.
Available metadata fields
rix/pdf supports these metadata fields:
title
author
subject
creator
keywords2
3
4
5
Use them to describe generated reports, invoices, exports, receipts, documents, and application output.
Set the title
Use:
doc.set_title("Rix PDF Metadata Example");The title describes the document.
Example:
auto doc = rix.pdf.document();
doc.set_title("Monthly Report");2
3
Set the author
Use:
doc.set_author("Rix");The author can be a person, application, organization, or service.
Example:
doc.set_author("Vix.cpp Application");Set the subject
Use:
doc.set_subject("PDF metadata");The subject explains what the document is about.
Example:
doc.set_subject("Generated report");Set the creator
Use:
doc.set_creator("my-app");The creator identifies the software or tool that created the PDF.
By default, the creator is:
rix/pdfIf the creator is set to an empty value, it is normalized back to the default creator.
Set keywords
Use:
doc.set_keywords("rix,pdf,vix,cpp");Keywords should be short and useful.
Example:
doc.set_keywords("report,invoice,export");Chain metadata setters
The document metadata setters are chainable.
doc.set_title("Rix PDF Metadata Example")
.set_author("Rix")
.set_subject("PDF metadata")
.set_keywords("rix,pdf,vix,cpp");2
3
4
This is the recommended style when setting several metadata fields together.
Metadata with visible content
Metadata does not create visible content.
If you want the title to appear on the page, also write it as a heading or text:
auto doc = rix.pdf.document();
doc.set_title("Monthly Report")
.set_author("Rix");
auto &page = doc.add_page();
page.heading(
page.x_left(),
page.y_top(),
"Monthly Report",
1);2
3
4
5
6
7
8
9
10
11
12
The metadata title is for the PDF info dictionary.
The heading is visible on the page.
Read metadata
Access metadata with:
const auto &metadata = doc.metadata();Example:
const auto &metadata = doc.metadata();
rix.debug.print("title:", metadata.title());
rix.debug.print("author:", metadata.author());
rix.debug.print("subject:", metadata.subject());
rix.debug.print("creator:", metadata.creator());
rix.debug.print("keywords:", metadata.keywords());2
3
4
5
6
7
Update metadata directly
You can update metadata through the metadata object:
doc.metadata().set_title("Updated title");
doc.metadata().set_author("Updated author");2
The document helpers are usually cleaner:
doc.set_title("Updated title")
.set_author("Updated author");2
Clear metadata
Use the metadata object to clear user-provided metadata:
doc.metadata().clear();This clears:
title
author
subject
keywords2
3
4
The creator is reset to:
rix/pdfCheck whether metadata is empty
Use:
doc.metadata().empty()Example:
if (doc.metadata().empty())
{
rix.debug.print("metadata is empty");
}2
3
4
The default creator does not make metadata non-empty.
Metadata in a report
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Project Report")
.set_author("Rix")
.set_subject("Generated project report")
.set_keywords("rix,report,pdf");
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Project Report",
1);
y -= 10.0F;
page.paragraph(
page.x_left(),
y,
page.content_width(),
"This document uses metadata for document properties "
"and visible headings for page content.");
auto saved = rix.pdf.save(doc, "project-report.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "project-report.pdf");
return 0;
}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
Run:
vix run metadata.cppMetadata with make_text
The high-level make_text helper accepts an optional title:
auto saved = rix.pdf.make_text(
"hello.pdf",
"Hello from rix.pdf",
"Rix PDF");2
3
4
The title is used as document metadata and as the visible heading.
Use make_text when you only need a simple text PDF.
Use document() when you need more control over metadata and content.
Metadata with tables
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Table Report")
.set_author("Rix")
.set_subject("Generated table")
.set_keywords("table,pdf,rix");
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Table Report",
1);
y -= 20.0F;
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F,
160.0F});
table.add_header({
"Name",
"Language",
"Project"});
table.add_row({
"Ada",
"C++",
"Rix"});
table.add_row({
"Gaspard",
"C++",
"Vix.cpp"});
page.table(
page.x_left(),
y,
table);
auto saved = rix.pdf.save(doc, "table-report.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "table-report.pdf");
return 0;
}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
Metadata with generated exports
For generated exports, metadata can identify the source:
doc.set_title("CSV Export")
.set_author("my-app")
.set_subject("Generated CSV report as PDF")
.set_creator("my-app")
.set_keywords("csv,export,pdf");2
3
4
5
This is useful when PDF files are produced automatically by a backend service.
Metadata and file names
The metadata title and output file name are separate.
doc.set_title("Monthly Report");
auto saved = rix.pdf.save(doc, "report-2026-06.pdf");2
3
The title describes the document.
The file name describes the saved file path.
They can be the same, but they do not have to be.
Write metadata to bytes
Metadata is included when writing PDF bytes:
auto bytes = rix.pdf.write(doc);
if (bytes.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(bytes.error()),
bytes.error().message());
return 1;
}2
3
4
5
6
7
8
9
10
11
Use write when another part of your application will handle the bytes.
Use save when you want to write directly to a PDF file.
Save the PDF
Use:
auto saved = rix.pdf.save(doc, "metadata.pdf");Always check errors:
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}2
3
4
5
6
7
8
9
Use in a Vix project
Create a Vix application:
vix new pdf-metadata --app
cd pdf-metadata2
Add Rix:
vix add rix/rix
vix install2
In vix.app, make sure Rix is listed under deps:
deps = [
"rix/rix",
]2
3
A small vix.app can look like this:
name = "pdf-metadata"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
packages = [
"vix",
]
links = [
"vix::vix",
]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Then use metadata in src/main.cpp:
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Metadata example")
.set_author("Rix")
.set_subject("PDF metadata")
.set_keywords("rix,pdf");
auto &page = doc.add_page();
page.heading(
page.x_left(),
page.y_top(),
"Metadata example",
1);
auto saved = rix.pdf.save(doc, "metadata.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "metadata.pdf");
return 0;
}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
Build and run:
vix build
vix run2
Single-file usage
For small scripts, examples, and experiments:
vix run metadata.cppIf Rix is installed globally for single-file usage:
vix install -g rix/rix
vix run metadata.cpp2
For project usage, prefer:
vix add rix/rix
vix install2
and keep the dependency in vix.app:
deps = [
"rix/rix",
]2
3
Use only PDF with the facade
If you want the rix.* facade style but only want PDF mounted, define the feature macro before including rix.hpp:
#define RIX_ENABLE_PDF
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Metadata example")
.set_author("Rix");
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
return rix.pdf.save(doc, "metadata.pdf").ok() ? 0 : 1;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.
Use the independent package
For independent usage, install:
vix add rix/pdf
vix install2
In vix.app:
deps = [
"rix/pdf",
]2
3
Then include:
#include <rix/pdf.hpp>Use this style when a project only needs PDF and does not need the full unified Rix facade.
For most application documentation, prefer:
#include <rix.hpp>Common mistakes
Expecting metadata to appear on the page
Metadata is not visible page content.
This sets document metadata:
doc.set_title("Monthly Report");To show the title on the page, also add a heading:
page.heading(
page.x_left(),
page.y_top(),
"Monthly Report",
1);2
3
4
5
Forgetting to add a page
Metadata alone can be written, but most documents should have visible content:
auto &page = doc.add_page();Not checking save errors
Wrong:
rix.pdf.save(doc, "metadata.pdf");Better:
auto saved = rix.pdf.save(doc, "metadata.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}2
3
4
5
6
7
8
9
10
11
Confusing title and file name
This is the PDF metadata title:
doc.set_title("Monthly Report");This is the output path:
rix.pdf.save(doc, "report.pdf");They are related, but not the same thing.
Setting empty creator
If the creator is empty, it is reset to the default creator:
rix/pdfUse a real value if your application should identify itself:
doc.set_creator("my-app");Confusing deps and packages
For a Vix project, do not put Rix packages in packages.
Wrong:
packages = [
"rix/rix",
]2
3
Correct:
deps = [
"rix/rix",
]2
3
deps is for Vix Registry packages.
packages is for CMake package discovery.
What you should remember
Create a document:
auto doc = rix.pdf.document();Set metadata:
doc.set_title("Title")
.set_author("Rix")
.set_subject("PDF metadata")
.set_keywords("rix,pdf,vix,cpp");2
3
4
Set the creator:
doc.set_creator("my-app");Add visible content separately:
auto &page = doc.add_page();
page.heading(
page.x_left(),
page.y_top(),
"Title",
1);2
3
4
5
6
7
Save:
auto saved = rix.pdf.save(doc, "metadata.pdf");Check errors:
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
}2
3
4
5
6
7
For a Vix project, install Rix:
vix add rix/rix
vix install2
and use:
deps = [
"rix/rix",
]2
3
Next step
Learn how to handle PDF errors.
Next: Errors