Compose documents with Python components¶
Use Python functions for reusable document sections, pass data as arguments, and keep each component's default styles with its definition. Export the same tree as a PDF, styled HTML or unstyled HTML without writing HTML strings.
2.6.0a12 introduces fullbleed.components as the intended public namespace.
It preserves both earlier import paths and adds a complete document migration
example: two implementations produce the same A5 and Letter landscape reports.
Download the migration source kit Read the migration reference
The API remains alpha
Use Python 3.10 or later in a virtual environment and install
python -m pip install --pre "fullbleed==2.6.0a12".
Ordinary pip install fullbleed selects the stable channel.
The existing fullbleed.ui API remains supported. A public namespace does
not itself make the new API stable; the release status
records the remaining decisions.
Write a component with its own styles¶
Summary below is an ordinary reusable function. Title carries its default
appearance, while .muted is an explicit stylesheet rule:
from importlib.resources import files
from pathlib import Path
from fullbleed.components import (
Document, Flow, Heading, Page, Paragraph, Renderer, Theme,
component, mm, pt, style, styled,
)
Title = styled(Heading, font_size=pt(24), color="#183e36")
@component
def Summary(title, description):
return Flow(
Title(title, level=1),
Paragraph(description, class_name="muted"),
gap=pt(12),
)
document = Document(
Summary("Project summary", "Prepared by Northstar Studio."),
title="Project summary",
lang="en-US",
page=Page("A5", margin=mm(16)),
theme=Theme(text=style(font_family="Inter", font_size=pt(11))),
styles={".muted": style(color="#50665f")},
)
font = files("fullbleed_assets").joinpath("fonts/Inter-Variable.ttf")
renderer = Renderer(font_files=[str(font)])
Path("summary.pdf").write_bytes(document.render_pdf(renderer))
Path("summary.html").write_text(document.to_html(include_styles=True), encoding="utf-8")
Path("summary.unstyled.html").write_text(
document.to_html(include_styles=False), encoding="utf-8"
)
class_name="muted" writes the literal class muted. The matching .muted
rule in Document(styles=...) supplies its appearance. The dot belongs in the
selector. A function name or class name does not load a stylesheet automatically.
| Change you want | Where to put it |
|---|---|
| Reusable defaults for a heading, box or paragraph | styled(...) |
| One component instance | style=style(...) or .with_style(...) |
| A component's named internal part | .with_parts(...) |
| Shared typography and theme values | Theme(...) on Document |
| A literal CSS class | class_name="..." and a matching rule in Document(styles=...) |
| Paper size, orientation and margins | Page(...) on Document |
The styling notebook lets you edit these style mechanisms in a complete Common Ground report. It keeps its explicit alpha 11 pin; the earlier import path continues to work in alpha 12. The component reference covers style precedence, named parts and static Bootstrap 5.0.0 helpers.
Export with or without styles¶
document.to_html(include_styles=True) embeds component styles, the theme and attached selector
rules. document.to_html(include_styles=False) removes generated CSS and inline
styles while keeping semantic content and literal classes, ready for a host
stylesheet. Flow gaps work in styled browser HTML.
The default document.to_html() keeps the separate-CSS form used with
document.to_css(). Choose include_styles=True for a complete styled HTML
file, or False when another application owns the styles.
PDF uses the explicitly registered font. Browser HTML needs its own font loading
or fallback; registering a font with Renderer does not give a browser a font
URL. Continuous browser layout and native PDF pagination are separate outputs.
Bootstrap helpers are static in both: no Bootstrap JavaScript is included.
Keep existing imports working¶
If you already use an earlier alpha, change the import prefix when convenient:
# Earlier alpha: still supported.
from fullbleed.ui.experimental import Document, Paragraph
# Intended public namespace for the new API.
from fullbleed.components import Document, Paragraph
from fullbleed.components import bootstrap as bs
These two namespaces expose the same objects. Components, styles and Bootstrap helpers can be composed across them without a second style registry. Both have the same typed signatures and editor completions.
The older fullbleed.ui API is a different authoring model. Its Document is
a decorator; the new Document is a value that owns its page, theme and metadata.
Changing an import alone does not migrate an existing decorated document.
Migrate a whole document¶
Extract the source kit and open its fullbleed-component-migration directory:
python -m venv .venv
# Windows PowerShell:
.venv\Scripts\Activate.ps1
# macOS/Linux: source .venv/bin/activate
python -m pip install -r requirements.txt
python -I examples/component_migration/render.py --out output
Compare output/a5-legacy.pdf with output/a5-components.pdf, then the two
letter-landscape PDFs. Each report has three pages. The kit includes the four
saved PDFs in preview/ for inspection before installation.
Read legacy_document and migrated_document side by side in render.py:
| Existing document setting | New owner |
|---|---|
| Page CSS for paper, orientation and margins | Page(...) |
| Engine title and language options | Document(title=..., lang=...) |
| Body typography | Theme(text=style(...)) |
| Repeated class-based defaults | styled(...), with explicit selectors where useful |
| Font files and engine options | Renderer(...) |
Change ROWS for content, INK and MUTED for colors, or REPORTS for page
geometry. Both implementations retain explicit font registration and a fixed
document timestamp.
For gradual adoption, to_legacy(node, theme=...) adapts a new component into
an old tree. It does not move the old document's geometry, metadata, renderer
settings or resource-owning kits such as Bootstrap. The
migration reference
explains those boundaries.
Rich documents and earlier examples¶
The alpha 11 showcase kit retains the Northstar invoice, Common Ground reports and authored accessible community guide with its original package pin. It also demonstrates page bands and styled HTML. The paired-authoring guide shows the HTML/CSS and component implementations with the same rendered output.
Verification and scope¶
The alpha 12 release evidence records package provenance, saved outputs and checks. Local qualification passes 374 focused component tests and 980 full Python tests. Both import paths are checked with mypy, Pyright and real language-server completions.
The migration kit renders with Fullbleed alone. Its optional verifier checks page geometry, per-page text, title/language, resolved timestamp, missing glyphs, repeat bytes and exact PDFium pixels for the two paired reports. These examples demonstrate an explicit migration, not automatic conversion of arbitrary CSS.
The independent CSS corpus retains known failures. This release does not claim complete CSS conformance, browser/PDF layout equivalence, independent kit usability or human accessibility results. Existing accessible specimen results remain scoped to their exact verified PDFs.
Help shape the stable API¶
Try rebranding a report, reusing a component, or adding a table column. Share a small synthetic example in the component RFC, including your installed version, the change you wanted and any step that required raw HTML or knowledge of generated selectors. Those editing experiences help identify which authoring contracts still need work.