Reportobello: Build Reports Rapidly
Reportobello is an API for building PDF reports. It's main goals are, in no particular order:
- Simplicity: Building a report is as easy as sending JSON to a predefined template
- Reliability: Build reports confidently, and diagnose issues quickly
- Performance: Reports should be built almost instantly (sub 500ms for most PDFs)
Reportobello uses Typst as the templating engine for making PDFs. Building reports is as easy as:
- Uploading your Typst files via our UI, CLI, or API.
- Send your data as JSON, get PDF output
- Repeat steps 2-3
You can use our API directly, or use one of our SDKs. We currently have support for Python, C#, and JavaScript/Typescript.
Keep reading to see how you can integrate Reportobello into your workflow.
Core Concepts
Here are a few basic concepts that will make using Reportobello a bit easier.
Templates
At the core of Reportobello are templates. Templates are Typst files that are used for creating reports.
For reports to be useful, they need data.
When building the report, Reportobello puts your JSON data in a global variable called data
:
#import "@rpbl/util:0.0.1": *
Gross earnings: $#data.total
In this example, @rpbl/util
is a Typst package which provides the data
global variable, along with other util functions.
To see all of the functions/variables this package provides, click here.
The package is versioned to prevent newer versions from breaking existing functionality.
If you can't (or don't want to) use the @rpbl/util
package for whatever reason, you can alternatively load the JSON data directly.
Reportobello stores the JSON data for building the report in a file called data.json
which your report can load and use:
#let data = json("data.json")
Gross earnings: $#data.total
Reports
Reports are PDFs that are built from templates. Reports also have some metadata like when they were built, who built them, etc.
In the event that a report failed to build, you can use the API to get recently built reports and diagnose why they failed.
Environment Variables
Often times you have data that is shared between lots of reports, for example, your company name, phone number, etc. Environment variables are ways to inject key-value pairs into all your templates.
For example, if you set the key company_name
to ACME Corp.
, you can use that value in your reports like so:
Company Name: #sys.inputs.company_name
Using environment variables has lots of advantages:
- One source of truth: Updating your values in one place will update them globally
- Less hard-coding: Using environment variables means less hard coded data in your templates and applications
- Less bandwidth: Storing these values server-side means that you don't have to re-send them along with your report data
You don't have to use environment variables, but they are there if you need/want them.
Reportobello currently does not support namespaced env vars, meaning all reports will be able to see all env vars. We are working on adding namespaces so that env vars are only scoped to specific reports or groups of reports.
API
This is documentation for how to interface with the Reportobello API directly. If you want to use Reportobello with a programming language like JavaScript or C#, refer to the client libraries page.
Authentication
Almost all API endpoints require an API key to function.
To get an API key, navigate to the login page and login with your GitHub account. We use GitHub to make the login experience quicker, and reduce the likelihood for spam and abuse.
You can also quickly spin-up your own self hosted Reportobello instance.
The reportobello.com site is currently being used for demo purposes, and is periodically reset. It should only be used for testing and should not be used for production!
Once you get an API key, make sure to set the Authorization
header like so:
Authorization: Bearer rpbl_YOUR_API_KEY_HERE
All API keys start with rpbl_
to indicate that it is a Reportobello API key.
Endpoints
Refer to the Swager Docs for a list of all the available endpoints, their purpose, and examples.
Rate Limits
By default, API endpoints are rate limited to 5 requests/second. Certain endpoints have stricter rate limiting, while others have no rate limits. Refer to the Swagger documentation to see what the rate limit is for a given endpoint.
Undocumented API endpoints (for example, in the UI) have different rate limits, and are subject to change without notice. Do not rely on them!
For self-hosted instances you can set the REPORTOBELLO_RATE_LIMIT_DISABLED
env var to 1
to remove
all API rate limits.
Currently there is no way to change rate limits for specific endpoints without modifying the code directly.
Reportobello CLI
If you want to interact with your Reportobello instance using the command line, the Reportobello CLI has you covered.
The Reportobello CLI is written in Python and uses the Python SDK.
Example CLI usage:
$ cat demo.typ
Example Title: #sys.input.TITLE
$ rpbl env set TITLE "Hello World"
$ rpbl push demo.typ
$ rpbl ls -a
╭──────────┬─────────┬─────────────────────────────────╮
│ Name │ Version │ Template │
├──────────┼─────────┼─────────────────────────────────┤
│ demo │ 1 │ Example Title: #sys.input.TITLE │
╰──────────┴─────────┴─────────────────────────────────╯
Installing
To install the Reportobello CLI, install the reportobello
package using pipx
:
$ pipx install reportobello
$ rpbl --help
Setup
You must set the REPORTOBELLO_API_KEY
environment variable in order to make certain API requests,
and if you are using a self-hosted version of Reportobello, you must set REPORTOBELLO_HOST
as well.
The CLI will automatically load a .env
file if it exists in the current directory.
For example, your .env
file might look like this:
REPORTOBELLO_API_KEY=rpbl_YOUR_API_KEY_HERE
REPORTOBELLO_HOST=https://example.com
You can also specify these env vars via the command line:
$ export REPORTOBELLO_API_KEY=rpbl_YOUR_API_KEY_HERE
$ export REPORTOBELLO_HOST=https://example.com
$ rpbl --help
Build a Template
Building On Your Reportobello Instance
$ rpbl build TEMPLATE [JSON]
Build the template TEMPLATE
on your Reportobello instance (not on your local machine).
To specify a JSON file to read and pass to the template, set the JSON
argument (defaults to data.json
).
Use -
to read from stdin
.
Build a File Locally
$ rpbl build TEMPLATE --local [JSON] [--env KEY=VALUE]
Build the template file TEMPLATE
on your local machine.
You can pass additional environment variables using the --env
flag. This can be repeated.
To specify a JSON file to read and pass to the template, set the JSON
argument (defaults to data.json
).
Use -
to read from stdin
.
$ rpbl watch TEMPLATE [JSON] [--env KEY=VALUE]
Use the watch
command to rebuild whenever TEMPLATE
changes.
You can read more about environment variables here.
Publish a Template
$ rpbl push TEMPLATE
Upload TEMPLATE
to your Reportobello instance, or if it already exists, create a new version of the template.
Pull a Template
$ rpbl pull TEMPLATE [--version 123]
Pull the latest version of a template TEMPLATE
, or pull a specific version using --version
or -v
.
List Templates
$ rpbl ls [--format=json]
List all templates your Reportobello instance. This will include:
- Template name
- Most recent version number
- Last time template was built (coming soon)
- Number of builds for this template (coming soon)
By default, a pretty-printed table is displayed. To display JSON instead, use --format=json
.
List Template Versions
$ rpbl ls TEMPLATE [-a] [--diff] [--format=json]
List template versions for TEMPLATE
. By default, the template content is not shown.
To show the template content, use -a
(for all).
To show only the differences between the templates, use the --diff
option. This implies -a
.
By default, a pretty-printed table is displayed. To display JSON instead, use --format=json
.
Diff output is not shown when using the JSON format.
List Recent Builds For Template
$ rpbl builds ls TEMPLATE [--format=json]
List recent builds for TEMPLATE
.
By default, a pretty-printed table is displayed. To display JSON instead, use --format=json
.
Environment Variables
List Environment Variables
$ rpbl env
$ rpbl env ls
List all environment variables in your Reportobello instance.
By default, a pretty-printed table is displayed. To display JSON instead, use --format=json
.
Set Environment Variables
$ rpbl env set KEY VALUE
Set the environment variable KEY
to VALUE
. If KEY
already exists, override it.
Remove Environment Variables
$ rpbl env rm KEY [KEY...]
Remove the environment variable KEY
. Can be repeated.
No error is returned when trying to delete a key that doesn't exist.
Client Libraries
Reportobello has SDK support for the following languages:
Feature Support Matrix
Reportobello is constantly adding new features, including upgrades to it's API. While we try to keep the SDKs up to date with the latest changes, they may fall behind when it comes to adding new features.
Here are all the supported API features and their SDK support.
Feature | C# | JS | Python |
---|---|---|---|
Get all templates (GET /api/v1/templates ) | ❌ | ❌ | ✅ |
Create/update template (POST /api/v1/template/{name} ) | ✅ | ✅ | ✅ |
Get template versions (GET /api/v1/template/{name} ) | ✅ | ✅ | ✅ |
Delete template (DELETE /api/v1/template/{name} ) | ❌ | ✅ | ✅ |
Build template (POST /api/v1/template/{name}/build ) | ✅ | ✅ | ✅ |
* Specify template version (?version=N ) | ❌ 1 | ❌ 1 | ❌ 1 |
* Download PDF as blob | ✅ 2 | ✅ | ✅ 2 |
* Download PDF as URL link (?justUrl ) | ✅ | ✅ | ✅ |
* Build pure PDF 3 (?isPure ) | ❌ | ✅ | ❌ |
Get recently built reports (GET /api/v1/template/{name}/recent ) | ❌ | ✅ | ✅ |
* Get reports build before a given date (?before ) | ❌ | ❌ | ✅ |
Get previously built PDF by filename (GET /api/v1/files/{filename} ) | ✅ | ✅ | ❌ 4 |
* Specify download name for PDF (?downloadAs=NAME ) | ✅ | ✅ | N/A |
* Automatically download PDF (in browser) (?download ) | ✅ | ✅ | N/A |
Get environment variables (GET /api/v1/env ) | ❌ | ❌ | ✅ |
Set environment variables (POST /api/v1/env ) | ✅ | ✅ | ✅ |
Delete environment variables (DELETE /api/v1/env ) | ✅ | ✅ | ✅ |
Convert existing file to template (POST /api/v1/convert/pdf ) | ❌ | ❌ | ❌ |
Upload data files for templates (POST /api/v1/template/{name}/files ) | ❌ | ✅ | ✅ |
Delete data files for templates (DELETE /api/v1/template/{name}/file/{filename} ) | ❌ | ❌ | ❌ |
Get/download data files for templates (GET /api/v1/template/{name}/file/{filename} ) | ❌ | ❌ | ❌ |
Defaults to latest version
PDF is not download directly as a blob, it grabs the URL then re-downloads it as a blob.
A "pure" PDF is a PDF built using only the JSON body, and doesn't use environment variables or non-deterministic side-effects like datetime.today()
. This means that if the JSON is the same, a cached version can be returned instead.
This endpoint is indirectly called when building a report, but the SDK does not allow for re-downloading a PDF with just a URL yet.
C#
This guide shows you how to use Reportobello with C#, specifically for backend applications, and Blazor frontends.
The full source code for this demo can be viewed here.
Reportobello should work with other .NET languages like F# and VB, but has not been tested.
Installing
Via the dotnet CLI:
$ dotnet add package Reportobello
$ dotnet add package Reportobello.Blazor
Or add the following PackageReference
directly:
<!-- Replace Version with the latest version -->
<PackageReference Include="Reportobello" Version="1.0.1" />
<PackageReference Include="Reportobello.Blazor" Version="1.0.0" />
The Reportobello
package provides the core SDK for the Reportobello API, and is a .NET Standard 2.0 package which can be used with most .NET projects.
The Reportobello.Blazor
package provides browser-only utilities like opening PDFs in new tabs, and only supports Blazor.
Only install Reportobello.Blazor
for Blazor projects!
Configuring Reportobello
Add the following to your Program.cs
file to setup dependency injection for Reportobello:
using Reportobello;
using Reportobello.Blazor;
// ...
builder.Services
// Reportobello API
.AddSingleton(
new ReportobelloApi(
builder.Configuration.GetValue<string>("Reportobello:ApiKey"),
builder.Configuration.GetValue<string>("Reportobello:Host")
)
)
// Blazor Utils
.AddScoped<ReportobelloUtil>();
Then, in your appsettings.json
, add the following:
{
"Reportobello": {
"ApiKey": "rpbl_YOUR_API_KEY_HERE",
"Host": "https://reportobello.com"
}
}
If you are using a self-hosted version of Reportobello, change the
Host
field to the URL for your local instance.
Now you will be able to inject Reportobello
or ReportobelloUtil
into your code!
Injecting Reportobello
To use Reportobello in you code, you need to inject 2 services:
ReportobelloApi
: The API instance for building the actual reportsReportobelloUtil
: A helper class for displaying/handling PDFs in the browser
Add the following code to your Blazor component:
[Inject]
public ReportobelloApi ReportobelloApi { get; set; } = default!;
[Inject]
public ReportobelloUtil Util { get; set; } = default!;
Note: If you aren't using Blazor, inject the services using your typical dependency injection system. As mentioned previously,
ReportobelloUtil
can only be used in Blazor projects, whileReportobelloApi
can be used with any .NET Standard 2.0 compatible project.
Creating Templates
Before you can build a report, you need to upload it's template file. You only need to upload a template when you first create it or when you modify it. You can upload it using the user interface, or by using a code-first approach, which is discussed below.
Reportobello uses Typst as it's templating language. Read the Typst docs for more info on how to make templates with Typst.
Weakly Typed Templates
If you don't want to create a record
or class
for your template data, you can specify the template name and contents directly:
await ReportobelloApi.UploadTemplate("quarterly_report", "// Template contents here");
While weakly typed templates are easier in to start out with, as your template becomes more complex, strong typing will make building reports easier and less error prone.
Strongly Typed Templates
To strongly type your template data, create a record
or class
that represents the structure of your template data:
record QuarterlyReport(int quarter, decimal total);
Then give a name to your template via the TemplateName
attribute:
[TemplateName("quarterly_report")]
record QuarterlyReport(int quarter, decimal total);
This gives you enough to upload the template:
string templateContent = "// Template content here";
await ReportobelloApi.UploadTemplate<QuarterlyReport>(templateContent);
Optionally, you can specify the template file in the record
itself.
If you already have a .typ
template file in repository, add the TemplateFile
attribute:
[TemplateName("quarterly_report")]
[TemplateFile("reports/quarterly_report.typ")]
record QuarterlyReport(int quarter, decimal total);
You can also specify the template contents directly:
[TemplateName("quarterly_report")]
[TemplateContent("""
// Template content here
""")]
record QuarterlyReport(int quarter, decimal total);
Then you can upload the template without specifying the content:
await ReportobelloApi.UploadTemplate<QuarterlyReport>();
Building Reports
To build a report, use the template we created above to build the report:
private async Task GeneratePdf()
{
// Build the report data
var report = new QuarterlyReport(quarter: 1, total: 123_456_789);
// Call the API, get resulting PDF url
var url = await ReportobelloApi.RunReport(report);
}
If you are using weakly-typed templates, you will need to specify the name of the template:
var url = await ReportobelloApi.RunReport("quarterly_report", report);
You don't have to use template objects with RunReport
, any JSON serializable object will do:
var report = new {quarter: 1, total: 123_456_789};
var url = await ReportobelloApi.RunReport("quarterly_report", report);
Displaying the PDF
The rest of this page is for Blazor projects that want to display/download PDFs in a browser.
Download Report PDF
Download the PDF directly, opening it in a new tab.
Function signature:
public async Task Download(Uri url, string downloadAs="report.pdf")
public async Task Download(string url, string downloadAs="report.pdf")
Arguments:
url
: The PDF URL to downloaddownloadAs
: Changes the default filename of the PDF when downloaded via the browser
Examples:
await Util.Download(url);
await Util.Download(url, downloadAs: "Earnings Report.pdf");
Open Report in New Tab
Opens the PDF in a new tab.
Function signature:
public async Task OpenInNewTab(Uri url, string? downloadAs=null, bool download=false)
public async Task OpenInNewTab(string url, string? downloadAs=null, bool download=false)
Arguments:
url
: The PDF URL to downloaddownloadAs
: Changes the default filename of the PDF when downloaded via the browserdownload
: Whentrue
, download the file in addition to opening it in a new tab
Examples:
await Util.OpenInNewTab(url);
await Util.OpenInNewTab(url, downloadAs: "Earnings Report.pdf");
// Equivalent to Download(url, name);
await Util.OpenInNewTab(url, downloadAs: "Earnings Report.pdf", download: true);
Open PDF in Existing Iframe
Open the PDF in an existing <iframe>
.
Function signature:
public async Task OpenInIframe(Uri url, object elementRef, string? downloadAs=null)
public async Task OpenInIframe(string url, object elementRef, string? downloadAs=null)
Arguments:
url
: The PDF URL to downloadelementRef
: A string CSS selector for the iframe, or anElementReference
to an iframedownloadAs
: Changes the default filename of the PDF when downloaded via the browser
Examples:
await Util.OpenInIframe(url, "#iframe");
// or, using `ElementReference`
public ElementReference Iframe { get; set; } = default!;
await Util.OpenInIframe(url, Iframe);
JavaScript/TypeScript
Installing
To install, run:
$ npm i reportobello
Configuring Reportobello
To use Reportobello, create a new API instance using your API key:
import { Reportobello } from "reportobello";
const api = new Reportobello({apiKey: "rpbl_YOUR_API_KEY_HERE"});
Never hard code API keys! This is only an example. In Node.js use
process.env.XYZ
to read sensitive data from environment variables. If you are using Reportobello from a browser, your API key will be available to anyone with the source code. We are working on fine-grained token permissions, which would allow you to expose read/write only API keys.
If you are using a self-hosted version of Reportobello, make sure to set the host
option:
const api = new Reportobello({apiKey: "rpbl_YOUR_API_KEY_HERE", host: "https://example.com"});
Creating Templates
Before you can build a report, you need to upload it's template file:
const template = `
#import "@rpbl/util:0.0.1": *
= Q#data.quarter Earnings Report
Generated: #datetime.today().display()
Earnings: $#data.earnings
`;
await api.createOrUpdateTemplate("quarterly_report", template);
Refer to the Typst docs to learn how to create Typst templates.
Building Reports
Once you have a template you can start building reports!
Use the runReport
function to build a report:
const url: URL = api.runReport(name, data);
This will return a URL
object which you can use to display, render, or download the PDF.
All the examples below will use the following globals:
const name = "quarterly_report";
const data = {"quarter": 1, "total": "123,456,678.00"};
Download Report PDF
Download the PDF directly, opening it in a new tab.
Function signature:
download(url: URL | string, downloadAs: string="report.pdf"): void;
Arguments:
downloadAs
: Changes the default filename of the PDF when downloaded via the browser.
Examples:
api.runReport(name, data).then(download);
// or
api.runReport(name, data).then(x => download(x));
api.runReport(name, data).then(x => download(x, "customName.pdf"));
// or
const url = await api.runReport(name, data);
download(url);
download(url, "customName.pdf");
Open Report in New Tab
Use the openInNewTab()
function to open the PDF in a new tab.
Function signature:
openInNewTab(url: URL | string, downloadAs?: string, download?: boolean=false): void;
Arguments:
downloadAs
: Changes the default filename of the PDF when downloaded via the browser.download
: Set totrue
to download the file in addition to opening it in a new tab.
Examples:
api.runReport(name, data).then(openInNewTab);
// or
api.runReport(name, data).then(x => openInNewTab(x));
// or
const url = await api.runReport(name, data);
openInNewTab(url);
Open PDF in Existing Iframe
Use this to open the PDF in an existing iframe.
Function signature:
openInIframe(url: URL | string, ref: string, downloadAs?: string): void;
Arguments:
ref
: The CSS selector for the iframe elementdownloadAs
: Set the name of the PDF when downloaded through the iframe
Examples:
api.runReport(name, data).then(x => openInIframe(x, "#id-of-iframe"));
// or
const url = api.runReport(name, data);
openInIframe(url, "#id-of-iframe");
PDF Building Options
Pure PDFs
A "pure" PDF is a PDF built using only the JSON body, and doesn't use environment variables or non-deterministic side-effects like datetime.today()
.
This means that if the JSON is the same, a cached version can be returned instead.
To use a cached PDF if one exists (or build one like normal if it doesnt exist), set the pure
option:
const url = await api.runReport(name, data, {pure: true})
Uploading Data Files
If you have a template that requires custom fonts, images, or other data files (JSON, txt, csv, etc),
you can upload these files using the uploadDataFiles()
method:
const files = document.querySelector("input[type=file]").files
// Using `FileList` object (from `<input type="file">` elements)
await api.uploadDataFiles(name, files);
// Using array of `File` objects
await api.uploadDataFiles(name, [files[0]]);
// Using array of manually built file objects
await api.uploadDataFiles(name, [
{
name: "file.txt",
blob: new Blob(["Hello world"], {type: "text/plain"}),
}
]);
After uploading these files you will be able to use the files in your template:
= Example Image
#image("img.jpg")
Note: Directories are stripped from filename when uploading. For example, if you upload
images/img.jpg
, the file will be uploaded asimg.jpg
.
Deleting Templates
When you delete a template it will "soft-delete" it, meaning you will not be able to access it, but it will still exist in the system for billing purposes.
When you delete a template you will not be able to access report metadata for reports built for that template. You will still be able to download PDFs if you have the direct URL.
await api.deleteTemplate("quarterly_report");
Get Recently Built Reports
To get a list of all the reports that have been built for a given template, use the following:
const reports = await api.getRecentReports("quarterly_report");
Note: The API currently does not allow for sorting, searching, or pagination, all reports will be returned. In the future pagination might be added, so do not rely on all results being returned.
Environment Variables
You can read more about environment variables in Reportobello here.
Creating/Updating Environment Variables
await api.updateEnvVars({
companyName: "ACME Corp.",
companyPhoneNumber: "123-456-7890",
});
Delete Environment Variables
await api.deleteEnvVars(["companyName", "companyPhoneNumber"]);
Using with TypeScript
If you are using TypeScript, you can use the generic version of runReport()
to type-check JSON data before it gets sent to Reportobello:
interface QuarterlyReport {
// ...
}
api.runReport<QuarterlyReport>(name, data).then(download);
Python
Installing
$ pip install reportobello
Configuring Reportobello
To start using Reportobello, create a new API instance:
from reportobello import ReportobelloApi
# Automatically read the REPORTOBELLO_API_KEY and REPORTOBELLO_HOST env var
api = ReportobelloApi()
# Explicitly pass API key
api = ReportobelloApi("rpbl_YOUR_API_KEY_HERE")
Never hard code API keys! This is only an example. Use
os.getenv()
to read API keys from environment variables.
If you are using a self-hosted version of Reportobello, make sure to set the host
argument:
api = ReportobelloApi(host="https://example.com")
Creating Templates
Before you can build a report, you need to upload it's template file. You only need to upload a template when you first create it or when you modify it. You can upload it using the user interface, or by using a code-first approach, which is discussed below.
from dataclasses import dataclass
from reportobello import Template
@dataclass
class QuarterlyReport(Template):
# The name to use for this template
name = "quarterly_report"
# Path to Typst template file
file = "path/to/report.typ"
# Template data
quarter: int
earnings: float
# Upload template via API
await api.create_or_update_template(template)
The path/to/report.typ
file is a Typst template file for building the report.
In this example, the report.typ
file will use the following contents:
#import "@rpbl/util:0.0.1": *
= Q#data.quarter Earnings Report
Generated: #datetime.today().display()
Earnings: #data.earnings
Typst is a powerful templating language which supports rich typesetting, variables, conditions, functions, and much much more. Refer to the Typst docs to learn more about Typst templates.
If you would rather store the template in the class directly you can set the content
property instead:
@dataclass
class QuarterlyReport(Template):
# ...
content = """
#import "@rpbl/util:0.0.1": *
= Q#data.quarter Earnings Report
Generated: #datetime.today().display()
Earnings: #data.earnings
"""
# ...
Building Reports
Once you have a template you can start building reports!
The QuarterlyReport
template we created can be passed to most template=
arguments,
and contains all the metadata needed for dealing with templates.
To build a template, run the following:
# Create a new template instance
template = QuarterlyReport(quarter=1, earnings=123_456)
# Build the report
pdf = await api.build_template(template)
In some cases though, it might be desirable to separate the template name from the template data, for instance, if you are not using dataclasses. In that case, you can pass the template name, and the template data as a dictionary or dataclass:
pdf = await api.build_template("quarterly_report", {"quarter": 1, "earnings": 123_456})
# or, if you want to use a Template object, but not the data:
pdf = await api.build_template(QuarterlyReport(), {"quarter": 1, "earnings": 123_456})
The rest of the code examples below will start with the following boilerplate:
template = QuarterlyReport(quarter=1, earnings=123_456)
pdf = await api.build_template(template)
Download PDF To Disk
To build a report and download the file directly use the following:
await pdf.save_to("output.pdf")
# or, using Path:
await pdf.save_to(Path("output.pdf"))
Download PDF In-Memory
To build a report and save the PDF blob directly to a variable, use the following:
blob = await pdf.as_blob()
Just Get URL
If you only want to get the URL of the built report, use the following:
url = pdf.url
Pure PDFs
A "pure" PDF is a PDF built using only the JSON body, and doesn't use environment variables or non-deterministic side-effects like datetime.today()
.
This means that if the JSON is the same, a cached version can be returned instead.
To use a cached PDF if one exists (or build one like normal if it doesnt exist), set the is_pure
keyword arg:
pdf = await api.build_template(template, is_pure=True)
Deleting Templates
When you delete a template it will be "soft-deleted", meaning you will not be able to access it, but it will still exist in the system for billing purposes.
When you delete a template you will not be able to access report metadata for reports built for that template, though you will still be able to download PDFs if you have the direct URL.
await api.delete_template("quarterly_report")
# or, using existing template instance
await api.delete_template(template)
Uploading Data Files
If you have a template that requires custom fonts, images, or other data files (JSON, txt, csv, etc),
you can upload these files using the upload_data_files()
method:
# You can upload files via Path or str objects
files = [Path("img1.jpg"), "img2.jpg"]
await api.upload_data_files(template, *files)
After uploading these files you will be able to use the files in your template:
= Example Image
#image("img.jpg")
Note: Directories are stripped from filename when uploading. For example, if you upload
images/img.jpg
, the file will be uploaded asimg.jpg
.
Get Recent Builds for a Template
To get a list of all the reports that have been built for a given template, use one of the following:
reports = await api.get_recent_builds("quarterly_report")
# or, using existing template instance
reports = await api.get_recent_builds(template)
To get reports built before a given time, use the before
keyword:
reports = await api.get_recent_builds(template, before=datetime.now(tz=utc))
Note that the datetime
object passed to before
must be a UTC datetime!
Note that the API/SDK currently does not support filtering, pages, or page size, it only supports the
before
keyword.
Environment Variables
You can read more about environment variables in Reportobello here.
Creating/Updating Environment Variables
await api.update_env_vars({
"company_name": "ACME Corp.",
"company_phone_number": "123-456-7890",
})
Delete Environment Variables
await api.delete_env_vars(["company_name", "company_phone_number"])
Self Hosting
This page is a breakdown of how to self-host your own Reportobello instance.
Local Testing
To experiment with Reportobello locally, run the following Docker command:
$ docker run -it \
--name reportobello \
-p 8000:8000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp:/tmp \
ghcr.io/reportobello/server
...
reportobello-1 |
reportobello-1 | "admin" API key: rpbl_8dCCwVD4kMtmk_s3qODaiaa9_6MVyHXnhTODuohdcZI
reportobello-1 |
reportobello-1 | 2024-10-20T01:22:27.952 INFO: Started server process [1]
reportobello-1 | 2024-10-20T01:22:27.952 INFO: Waiting for application startup.
reportobello-1 | 2024-10-20T01:22:27.952 INFO: Application startup complete.
reportobello-1 | 2024-10-20T01:22:27.952 INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
To start using Reportobello:
-
Copy the
rpbl_...
API key -
Navigate to http://localhost:8000
-
Log in using your API key
When you're done, type CTRL+C to stop the server.
Your data will be stored in the reportobello
container, and will be kept across restarts since the --rm
flag is not used.
To start, stop, or destroy you Reportobello instance, run the following commands:
# Start a previously stopped instance
$ docker start reportobello
# Stop the currently running instance
$ docker stop reportobello
# Destroy the instance
$ docker rm reportobello
Production
To use Reportobello in a production environment, you will probably want to enable/disable some environment variables:
General
REPORTOBELLO_DOMAIN
: The domain that the Reportobello instance is hosted from. Not setting this can cause CSRF issues when generating PDF URLs.REPORTOBELLO_RATE_LIMIT_DISABLED
: By default, API requests in Reportobello are rate-limited. To disable rate-limits, set this to1
. Note that this is different than monthly rate limits, which do not apply to the admin API key.REPORTOBELLO_ADMIN_API_KEY
: Hard-code the admin API key (by default a key is auto-generated once on initial boot). If provided, it must match the following regex:^rpbl_[0-9A-Za-z_-]{43}$
To securely create a random, valid API key, run one of the following:
# If you don't have a running instance $ docker run --rm --entrypoint mint_api_key ghcr.io/reportobello/server # If you do have a running instance $ docker compose exec reportobello mint_api_key
GitHub
Note: This probably should not be enabled, as it allows anyone with a GitHub account to create an account on your Reportobello instance.
REPORTOBELLO_GITHUB_OAUTH_CLIENT_ID
: If you want to enable GitHub OAuth support, set your OAuth client ID here.REPORTOBELLO_GITHUB_OAUTH_CLIENT_SECRET
: Same as above, but for the OAuth client secret.
Jaeger/OTEL
Note: This should probably not be set unless you need to debug Reportobello, or want to ingest it's telemetry data.
REPORTOBELLO_JAEGER_URL
: Frontend URL for a Jaeger instance.REPORTOBELLO_OTEL_TRACE_ENDPOINT
: HTTP URL for exporting Open Telemetry data.
Backups
To backup Reportobello, copy the data folder to safe location:
$ docker cp reportobello:/app/data /path/to/dir/rpbl_backup
To restore from a backup, create a new Reportobello instance and point it to the backup location:
$ docker run -it \
--name reportobello-restored \
-p 8000:8000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp:/tmp \
-v /path/to/dir/rpbl_backup:/app/data \
ghcr.io/reportobello/server
Building Templates
Reportobello uses Typst as it's templating engine. To learn more about Typst and how to use it, read their docs.
In addition to the existing Typst features, Reportobello adds some additional features to make building reports easier. To learn more about those, go to the next chapter.
The @rpbl/util
Package
Current package version:
0.0.1
The @rpbl/util
package is used by Reportobello to inject global variables and other helper functions which aren't provided natively in Typst.
Examples include ISO 8601 datetime parsing and automatically loading JSON data in the template.
Globals
data
This global variable stores the JSON payload passed to the report via the API (or CLI).
Example Usage:
{
"invoice": {
"number": 1234,
"rows": [
{
"item": "Widget",
"cost": "$1"
}
]
}
}
#import "@rpbl/util:0.0.1": *
Invoice \#: #data.invoice.number
Invoice Row 1: #data.invoice.rows.at(0)
This is the full JSON payload: #data
Functions
iso8601
This function parses a string in ISO 8601 datetime format and returns a datetime
object.
Note: Typst does not support timezones or sub-second percision, so those values are stripped before parsing. This behaviour might change in the future.
Example Usage:
#import "@rpbl/util:0.0.1": *
#iso8601("2024-11-11T19:51:41.711304+00:00")
#iso8601("2024-11-11T19:51:41.711304")
#iso8601("2024-11-11T19:51:41")
#iso8601("2024-11-11")