DEV Community

IronSoftware
IronSoftware

Posted on

ReportBro in Python: What Embedding a Designer Costs

Ask who is going to maintain the invoice layout in a year, and a ReportBro adoption answers with two package managers. reportbro-lib is the Python renderer a service runs, installed from PyPI. reportbro-designer is the JavaScript component the business user opens in a browser, installed from npm. They are versioned and upgraded separately, so a front-end build joins the dependency diagram of a feature Python renders, and both halves are AGPL-3.0, so the licence review has to clear both before anything ships. None of that is asked of a library that turns existing markup into a PDF and is installed once.

Full disclosure. We are the team at Iron Software behind IronPDF. This piece looks at what ReportBro's AGPL halves and PLUS-gated text shaping commit a team to, and how IronPDF renders a developer-owned template from one pip install.

What Does Embedding a Designer Commit You To?

Both components are licensed AGPL-3.0, so this is not an open renderer paired with a paid designer. Any team shipping a closed-source product needs the licence review to clear both halves, and the commercial alternative is sold as a bundle with ReportBro PLUS rather than as a standalone upgrade to either component. Text formatting sits inside that same decision. The AGPL build of reportbro-lib raises an explicit errorMsgPlusVersionRequired the moment an element sets its richText field or asks for text shaping, which gates both behind PLUS with no intermediate option, so a layout requirement that looks like formatting turns into a purchasing conversation. IronPDF keeps that step to a licence key applied once, with the same documented surface available to every deployment.

Who Is the Designer Actually For?

A non-developer opens the designer in a browser, drags fields onto a page, binds them to data, and previews the result live, without touching the Python that renders the file. Wiring it into a page takes a stylesheet and script include, a container div, and a new ReportBro(...) call against it. What comes out is not a binary or a proprietary blob but a plain Python dict, so a layout a business user builds can be committed to source control, diffed in a pull request, and reviewed the way code is reviewed. The same definition produces either a PDF or an XLSX file through generate_pdf() or generate_xlsx(), with no second template to maintain, and a full parameter, expression, and data-binding model configured visually rather than in a script. Nine years of work sits behind it, with roughly fifty reportbro-lib releases since the first PyPI upload in 2017 and 3.12.2 on 29 April 2026. Where a business user owns the layout and maintains it without a developer in the loop, that designer is the ceiling of what a reporting product can hand a non-technical author, and IronPDF answers the developer-owned half of the same problem from one package.

Rendering the definition is two lines once the data is in hand.

from reportbro import Report

report = Report(report_definition, data)
pdf_bytes = report.generate_pdf()
Enter fullscreen mode Exit fullscreen mode

That returns the finished PDF as bytes, ready to write to disk or stream back through a web response. Swapping generate_pdf() for generate_xlsx() produces the spreadsheet from the same definition, which is the part of the model that saves a second template, and the equivalent starting point on a markup-first path is pointing a renderer at the HTML that already exists rather than rebuilding it, with page setup handled in the render options.

Which Inputs Will the Renderer Take?

A report-definition dict and a data object, and nothing else. ReportBro exposes no method that takes an HTML string, a URL, or an existing template and returns a PDF, so content that already lives as markup, covering a marketing template, a live web page, or an email layout, gets rebuilt inside the designer's object model before it can be produced. That rebuild is the cost that lands on teams whose source material was authored somewhere else, and it recurs every time the design does.

Underneath, the PDF path runs through reportbro-fpdf2, a maintainer-controlled fork of fpdf2, with Babel, Pillow, XlsxWriter, python-barcode, qrcode, and simpleeval alongside it, all pure Python, and reportbro-lib declares support for Python 3.10 and above. Three constructor defaults are worth knowing before deployment, since Report() allows local images by default through allow_local_image=True, blocks external image URLs unless a team opts in through allow_external_image=False, and caps output at 10,000 pages through page_limit=10000 until that is raised explicitly. Those are sensible defaults for a tool rendering user-supplied data, and they are also three settings to carry into a deployment review next to whatever handles images and page furniture on the output side. Nothing else in that review is outstanding, since the GitHub Advisory Database under both the PyPI and npm filters, Snyk, and the NVD carry nothing against either package, which puts the whole of this decision in the licence and the authoring model.

Capability ReportBro 3.12.2 IronPDF for Python
PDF output Through a maintainer-controlled fpdf2 fork Through a bundled Chromium engine
HTML or CSS as input Report-definition dict plus data, no markup path RenderHtmlAsPdf, RenderUrlAsPdf, and RenderHtmlFileAsPdf
Who authors the layout A non-developer in the browser designer A developer, in HTML and CSS the team already owns
richText and text shaping Raises errorMsgPlusVersionRequired without PLUS Rendered as the browser renders it, every licence
Packages to install reportbro-lib on PyPI plus reportbro-designer on npm One package from pip, Python only
Licence AGPL-3.0 on both components, or a commercial bundle Commercial, one licence for every deployment
Python versions accepted 3.10 and later 3.7 and later

Table 1. Document output path only, ReportBro against IronPDF for Python, with tier gating shown where ReportBro applies it.

A rebuild is priced by the markup row, and a purchase order is triggered by the text-shaping row, where Unicode and text rendering sit inside the engine rather than behind a tier. Everything else answers the question of who sits in front of the layout.

What a Renderer Asks of the Team Instead

The other half of this problem starts with markup that already exists, whether a template, a live page, or a report some other system already renders.

from ironpdf import *

renderer = ChromePdfRenderer()
pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #4471</h1><p>Total due: $1,240.00</p>")
pdf.SaveAs("invoice.pdf")
Enter fullscreen mode Exit fullscreen mode

That writes the invoice with its CSS applied as a browser would paint it, on Windows, macOS, Linux, and in a container, on Python 3.7 and later. Where an internal Flask or Django view already renders the report as a page, handing the renderer that URL skips the report-definition step completely.

IronPDF renders a developer-owned template from one pip install, with no npm component in the build, no AGPL review to clear before production, and no tier gate standing between a formatting requirement and a purchase order. The narrow case that stays with ReportBro is a business user maintaining the layout in a browser with no developer in the loop. IronPDF has a free trial if you want to put your existing template through it before the licence review starts.

So who is actually staffing the next report on your side, a business user with a browser or a developer with an HTML template? Tell us in the comments which one your last project needed, because that answer usually settles the tooling before anyone opens a feature table.

ReportBro is the property of its maintainers, and we have no affiliation with the project. The licence, release, and default-configuration details above are taken from ReportBro's own documentation, PyPI listing, and npm package at the time of writing. If a detail has changed since, please let us know below.

Top comments (0)