Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: Generate PDFs in Python with components or HTML and CSS
description: Create your first PDF with reusable Python components or HTML/CSS. Copy either complete example, use bundled fonts, and render the same invoice.
title: Generate PDFs in Python with HTML/CSS or components
description: Create your first PDF from HTML/CSS or Python components. Copy either complete example, use bundled fonts, and render the same invoice.
---
# Create your first PDF in Python

Prefer to try it before setting up Python? [Open the browser playground](../playground.md)
to edit HTML/CSS and download a PDF or runnable project. Use the
[invoice notebook](notebook.md) to work with Python data in Colab.

Choose **Python components** to compose a document with functions, or
**HTML/CSS** to bring a template. Both examples below use the stable API, embed
Choose **HTML/CSS** to bring a template, or **Python components** to compose
a document with functions. Both examples below use the stable API, embed
the bundled Inter font, and write the same one-page invoice.

Install Fullbleed in your Python environment. If you need an isolated environment,
Expand All @@ -23,6 +23,25 @@ python -m pip install fullbleed
Choose one tab and save its complete example as `hello.py`. These examples are
checked with Fullbleed **2.5.34**.

=== "HTML/CSS"

```python
from importlib.resources import files
from pathlib import Path
import fullbleed

font = files("fullbleed_assets").joinpath("fonts/Inter-Variable.ttf")
engine = fullbleed.PdfEngine(font_files=[str(font)])
html = '<h1 class="invoice-title">Invoice INV-1042</h1><p>Consulting: USD 1,200.00</p>'
css = """
@page { size: A4; margin: 20mm; }
body { font-family: Inter; color: #203a36; }
.invoice-title { color: #175c52; }
"""
pdf = engine.render_pdf(html, css)
Path("invoice.pdf").write_bytes(pdf)
```

=== "Python components"

```python
Expand Down Expand Up @@ -51,26 +70,7 @@ checked with Fullbleed **2.5.34**.
Path("invoice.pdf").write_bytes(invoice.render_pdf(engine))
```

=== "HTML/CSS"

```python
from importlib.resources import files
from pathlib import Path
import fullbleed

font = files("fullbleed_assets").joinpath("fonts/Inter-Variable.ttf")
engine = fullbleed.PdfEngine(font_files=[str(font)])
html = '<h1 class="invoice-title">Invoice INV-1042</h1><p>Consulting: USD 1,200.00</p>'
css = """
@page { size: A4; margin: 20mm; }
body { font-family: Inter; color: #203a36; }
.invoice-title { color: #175c52; }
"""
pdf = engine.render_pdf(html, css)
Path("invoice.pdf").write_bytes(pdf)
```

`Invoice(...)` receives ordinary Python arguments. `@Document(styles=...)`
In the component example, `Invoice(...)` receives ordinary Python arguments. `@Document(styles=...)`
attaches the stylesheet to its result. The heading's
`class_name="invoice-title"` matches the `.invoice-title` rule; the HTML/CSS
example uses the same class and values.
Expand All @@ -89,7 +89,8 @@ or the [designed HTML/CSS invoice](../guides/invoices.md). The separate
[component alpha](../guides/component-preview-11.md) adds portable component
styles, themes, named parts, and styled/unstyled HTML export. It has its own
explicit installation instructions; the examples above use the stable
`fullbleed.ui` API.
`fullbleed.ui` API. The [release-status guide](../guides/component-status.md)
explains the distinction and the remaining stabilization work.

## Start with a complete project

Expand Down
2 changes: 2 additions & 0 deletions docs/guides/component-preview-11.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ authored accessible community guide.
Use Python 3.10 or later in a virtual environment. The kit pins
`fullbleed==2.6.0a11`; ordinary `pip install fullbleed` selects the stable
channel. Components under `fullbleed.ui.experimental` may change.
The alpha is merged into `master`; [merging and stabilization are separate
milestones](component-status.md). The existing `fullbleed.ui` API remains supported.

## Run the complete report

Expand Down
75 changes: 75 additions & 0 deletions docs/guides/component-status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
title: Python component release status and stabilization
description: Choose the stable Fullbleed Python component API or its opt-in 2.6 alpha. See what is verified and what remains before the new API becomes stable.
---

# Python component release status

Reviewed **20 October 2026**. Fullbleed's released Python component API is
available today. The newer API remains an opt-in alpha.

| Channel | Install | Authoring surface |
| --- | --- | --- |
| Stable **2.5.34** | `python -m pip install fullbleed` | HTML/CSS rendering and the existing `fullbleed.ui` components |
| Alpha **2.6.0a11** | `python -m pip install --pre "fullbleed==2.6.0a11"` | New authoring values under `fullbleed.ui.experimental` |

Start with the [Python quickstart](../getting-started/quickstart.md) for either
HTML/CSS or stable components. Both examples produce the same invoice.
The [stable component guide](python-components.md) explains function components,
children, `class_name`, inline styles and attached stylesheets.

The alpha adds component-owned styles, named customization parts, column-based
tables, static Bootstrap helpers, repeating page bands, and HTML export with or
without styles. Its [current preview guide](component-preview-11.md) includes
installation instructions and a complete source kit.

For interactive walkthroughs, [Explore the versioned component notebook](../getting-started/component-notebook.md)
or [Try the current styling notebook](../getting-started/component-styling.md).
Each notebook states its own package pin and includes downloadable output.

## Decision: retain the alpha

The alpha is **merged into `master` and published on PyPI**. It is not an
unmerged prototype. Merging it makes the implementation available for development;
it does not make the new API a stable compatibility promise. Ordinary
`pip install fullbleed` continues to select the stable channel.

The current release has substantial rendered-output evidence, including paired
HTML/CSS and component showcases, saved PDFs, styled/unstyled HTML, page-band
checks, typing checks and browser layout checks. The
[alpha 11 release](https://github.com/fullbleed-engine/fullbleed-official/releases/tag/v2.6.0a11)
records the exact package and fixture evidence. Passing those checks establishes
the tested behavior; it does not settle how the API should evolve for its callers.

Three stabilization gates remain:

| Gate | Current position | What closes it |
| --- | --- | --- |
| Public namespace and migration | `fullbleed.ui.Document` is a decorator; the experimental `Document` is a document value with explicit page, theme and renderer ownership. `to_legacy` bridges individual nodes. | Choose and document the supported stable import path, preserve existing imports, and qualify whole-document migration examples covering styles, geometry, metadata and renderer configuration. |
| Components from independent kits | Theme tokens are document-wide. Two kits using `token("accent")` share one value. Missing bindings raise `theme.missing`; explicit kit prefixes allow separate palettes. | Settle and qualify a documented kit-dependency convention with two independently authored kits: defaults, required values, conflicting names and local overrides must be clear without inspecting implementation details. A new scoping mechanism is not automatically required. |
| Authoring and customization feedback | Maintainer-authored fixtures cover the intended edits, but retained independent author feedback is still missing. | Have independent authors rebrand a document, reuse a component, add a table column, change page size and diagnose a layout failure. Record where internal selectors or undocumented knowledge are needed, then resolve those contract gaps. |

These are bounded API decisions, not a requirement to implement every CSS feature
before a stable release. The earlier
[implementation review](https://github.com/fullbleed-engine/fullbleed-official/blob/master/docs/component-authoring-design.md)
and [design follow-up](https://github.com/fullbleed-engine/fullbleed-official/blob/master/docs/component-authoring-next-iteration.md)
retain their dated findings. This page records the current release decision.

## What you can rely on now

- Existing `fullbleed.ui` imports remain supported. They are not deprecated by the alpha.
- `class_name` adds a literal class; a matching stylesheet supplies its appearance.
See the [stable styling examples](python-components.md#class-names-and-styles)
or the [alpha styling walkthrough](component-preview-11.md).
- The preview exports styled and unstyled HTML. Bootstrap components are static
in both HTML and PDF; no Bootstrap JavaScript is included.
- Token names are explicit, document-wide dependencies. For current reusable
kits, use concrete defaults or supply the complete documented theme with
distinct prefixes where meanings differ.
- Native PDF pagination and continuous browser HTML are different output
contexts. The [preview's verification scope](component-preview-11.md#verification-and-scope)
records the tested cases and limits.

JavaScript and .NET packages have their own versions and API coverage. Their
component APIs do not inherit the Python alpha's stability label or imply
cross-language feature parity.
81 changes: 20 additions & 61 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
---
title: PDF components and HTML/CSS for Python, JavaScript, Rust, and C#
description: Build PDFs with Python, JavaScript or C# components and optional JSX, or use HTML/CSS from Python, Rust, Node.js, C#, and browsers. Reusable templates, bundled fonts, and local output.
title: PDF generation for Python, Rust, JavaScript, and C#
description: Generate PDFs from HTML/CSS in Python, Rust, JavaScript, and C#. Build invoices, reports, and print documents with bundled fonts, reusable templates, and local output.
hide:
- toc
---

<div class="hero" markdown>
<div markdown>
<p class="eyebrow">Components + HTML/CSS to PDF · MIT licensed</p>
<p class="eyebrow">HTML/CSS to PDF · MIT licensed</p>

# Your data. Your design. Your PDF.

<p class="lead">Compose invoices, reports, and print documents with <a href="guides/python-components/">Python components</a>, <a href="guides/javascript-components/">JavaScript and JSX</a>, <a href="guides/csharp-components/">C# components</a>, or existing HTML/CSS templates. One Rust print engine, in your application.</p>
<p class="lead">Generate invoices, reports, and print documents from HTML/CSS. Keep your templates, fonts, and data in your application, with a deterministic Rust engine handling layout and PDF output.</p>

[Try PDF components](assets/react-demo/index.html){ .md-button .md-button--primary }
[Choose your language](#choose-your-language){ .md-button }
[Choose your language](#choose-your-language){ .md-button .md-button--primary }
[Try the PDF playground](playground.md){ .md-button }

Python, Rust, Node.js, C#, and browser JavaScript. One print engine.
</div>
Expand All @@ -24,68 +24,14 @@ Python, Rust, Node.js, C#, and browser JavaScript. One print engine.
</figure>
</div>

<p class="facts">Reusable components &nbsp; / &nbsp; Explicit fonts and assets &nbsp; / &nbsp; Repeatable output &nbsp; / &nbsp; Free for commercial use under MIT</p>
<p class="facts">HTML/CSS templates &nbsp; / &nbsp; Explicit fonts and assets &nbsp; / &nbsp; Repeatable output &nbsp; / &nbsp; Free for commercial use under MIT</p>

Building a store? [Try the WooCommerce editor in a sample store](guides/woocommerce.md),
then [evaluate an automated order workflow](guides/woocommerce.md#evaluate-an-automated-workflow)
for email attachments or customer downloads.

<span id="a-small-first-step"></span>

## Compose PDFs with Python components

Functions, props, children, lists and conditionals—familiar building blocks for
your print documents. Use named elements and Python style mappings to build a
complete invoice without writing HTML strings.
The component workflow below requires Fullbleed 2.5.25 or later.

```python
from importlib.resources import files
from pathlib import Path
import fullbleed
from fullbleed.ui import Document, Heading, Paragraph, Stack, Strong, component

@component
def Line(label, amount):
return Paragraph(Strong(label), ": ", amount)

@Document(title="Invoice", styles={
"@page": {"size": "A4", "margin": "18mm"},
"body": {"font_family": "Inter"},
})
def Invoice():
return Stack(Heading("Made for you", level=1), Line("Design", "$120"), gap="12pt")

font = files("fullbleed_assets").joinpath("fonts/Inter-Variable.ttf")
engine = fullbleed.PdfEngine(font_files=[str(font)])
Path("component-invoice.pdf").write_bytes(Invoice().render_pdf(engine))
```

[Build with Python components](guides/python-components.md){ .md-button .md-button--primary }
[Download the designed invoice](assets/components/project.zip){ .md-button }

Prefer JavaScript? [Compose the same kind of document with functions or JSX/TSX](guides/javascript-components.md).
Named components, typed props and reusable styles work with the Node and browser
renderers. [Try the live component invoice](assets/react-demo/index.html) or
[connect it to your React application](guides/react-pdf.md). Ordinary JavaScript functions need no build step or React runtime.

Using C#? [Compose PDFs with typed methods, LINQ and style objects](guides/csharp-components.md),
or [download the component invoice](assets/dotnet-components/project.zip).

Want to try the next Python authoring API? The
[component alpha](guides/component-preview-11.md) includes reusable styles,
named component parts, data tables, static Bootstrap helpers and repeating page
bands, with PDF and styled or unstyled HTML output. [Explore the versioned component
notebook](getting-started/component-notebook.md) in Colab or Jupyter, or download
the current source kit from the alpha guide.

[Try the current styling notebook](getting-started/component-styling.md) to
change theme colors, named parts and `class_name` rules, then compare PDF with
styled and unstyled HTML.

Building a web application? [Render PDFs in a browser worker](guides/browser-pdf.md) with
editable templates, previews, and downloads. [Try the live starter](assets/browser-demo/index.html).

## Choose your language

Pick your application stack. Generate a PDF locally or download one from the browser app.
Expand Down Expand Up @@ -292,6 +238,19 @@ Pick your application stack. Generate a PDF locally or download one from the bro

[C# and .NET quickstart →](getting-started/dotnet.md) · [Components and styles](guides/csharp-components.md) · [LINQ and variable data](https://github.com/fullbleed-engine/fullbleed-dotnet/tree/v0.2.0/samples/FullBleed.DotNet.LinqVdp)

<span id="compose-pdfs-with-python-components"></span>

!!! tip "Prefer to author with components?"
Build reusable document functions with [Python components](guides/python-components.md),
[JavaScript and JSX](guides/javascript-components.md), or
[C# components](guides/csharp-components.md). Pass data and children, attach styles,
and render through the same print engine.

[Try the live component invoice](assets/react-demo/index.html) or
[compare HTML/CSS and component versions of the showcase](guides/showcase-authoring.md).
The existing Python API is stable; its newer authoring API is an opt-in alpha.
[See the release status and remaining stabilization work](guides/component-status.md).

## Pick a document to build

<div class="grid cards" markdown>
Expand Down
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
site_name: Fullbleed
site_url: https://docs.fullbleed.dev/
site_description: Build PDFs with Python, JavaScript or C# components and optional JSX, or use HTML/CSS from Python, Rust, Node.js, C#, and browsers. MIT licensed.
site_description: Generate PDFs from HTML/CSS in Python, Rust, JavaScript, and C#. Build invoices, reports, and print documents with bundled fonts and local output. MIT licensed.
site_author: Fullbleed Engine
repo_url: https://github.com/fullbleed-engine/fullbleed-official
repo_name: Fullbleed on GitHub
Expand Down Expand Up @@ -84,6 +84,7 @@ nav:
- Examples and downloads: examples.md
- Build a document:
- Python components: guides/python-components.md
- Component release status: guides/component-status.md
- One design, two authoring paths: guides/showcase-authoring.md
- Accessible component showcase: guides/accessible-showcase.md
- JavaScript components and JSX: guides/javascript-components.md
Expand Down
2 changes: 1 addition & 1 deletion tools/check_component_notebook_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def log_message(self, *a):
if "unstyled" in filename:
assert page.locator("style, [style], link[rel=stylesheet]").count() == 0
for path, label_text in (
("/", "Explore the versioned component notebook"),
("/guides/component-status/", "Explore the versioned component notebook"),
("/getting-started/notebook/", "Try the component notebook"),
("/guides/bootstrap-components-preview/", "Try the component notebook"),
):
Expand Down
2 changes: 1 addition & 1 deletion tools/check_component_styling_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def log_message(self, *a):
page.screenshot(path=str(out / f"{label}-{'styled' if styled else 'unstyled'}-html.png"),
animations="disabled", full_page=True)
for path, title in (
("/", "Try the current styling notebook"),
("/guides/component-status/", "Try the current styling notebook"),
("/guides/component-preview-11/", "Try the styling notebook"),
("/guides/python-components/", "edit the styling notebook"),
):
Expand Down
1 change: 0 additions & 1 deletion tools/verify_component_starter.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def main():
assert rendered["ok"] and rendered["pages"] == 1 and rendered["repeated_pdf_equal"]
documentation_examples = []
for page, output, required in [
("index.md", "component-invoice.pdf", ["Made for you", "Design", "$120"]),
("guides/python-components.md", "invoice.pdf", ["Maple & Finch", "Design", "Review", "$120.00", "$40.00"]),
]:
source = (ROOT / "docs" / page).read_text(encoding="utf-8")
Expand Down
Loading
Loading