bagme is a Go library that renders HTML/CSS to PDF using the boxes and glue typesetting engine. It implements TeX's line-breaking and page-breaking algorithms, so you get high-quality typesetting with almost no effort.
Ready-to-run examples (HTML → PDF, accessible PDF/UA, tables, positioned snippets, multi-page documents) live in the boxesandglue-examples repository.
go get github.com/boxesandglue/bagme
Use RenderPages for automatic page breaks, @page margins, and multi-page output:
package main
import (
"log"
"github.com/boxesandglue/bagme/document"
)
func main() {
d, err := document.New("output.pdf")
if err != nil {
log.Fatal(err)
}
d.AddCSS(`
@page { size: A4; margin: 2cm; }
body { font-family: serif; font-size: 11pt; line-height: 1.4; }
h1 { page-break-before: always; }
`)
if err := d.RenderPages(`
<h1>Chapter 1</h1>
In olden times when wishing still helped one, there lived a king
whose daughters were all beautiful...
<h1>Chapter 2</h1>
Close by the king's castle lay a great dark forest, and under an
old lime-tree in the forest was a well...
`); err != nil {
log.Fatal(err)
}
if err := d.Finish(); err != nil {
log.Fatal(err)
}
}
Use OutputAt for precise placement on a page (labels, forms, letterheads):
package main
import (
"log"
"github.com/boxesandglue/bagme/document"
"github.com/boxesandglue/boxesandglue/backend/bag"
)
func main() {
d, err := document.New("out.pdf")
if err != nil {
log.Fatal(err)
}
d.AddCSS(`body { font-family: serif; font-size: 12pt; }`)
ps, _ := d.PageSize()
w := ps.ContentWidth
x := ps.MarginLeft
y := ps.Height - ps.MarginTop
d.OutputAt("<h1>Hello, World!</h1>
Placed at exact coordinates.
", w, x, y)
d.Finish()
}
@page rulespage-break-before / page-break-after (always, avoid)@top-center, @bottom-right, etc.) for headers/footersfont-feature-settings / font-variation-settingsSource + rendered PDF + preview PNG for every entry in boxesandglue-examples/bagme:
| Example | What it shows |
|---|---|
| Simple | Basic HTML rendering with CSS styling, lists and code blocks |
| Border | Borders, border-radius and background colors on elements |
| Accessible PDF | PDF/UA output with automatic structure tagging for screen readers |
| Multipage | Automatic page breaks, forced breaks with page-break-before |
| Positioned | Manual placement with OutputAt using absolute coordinates |
| Table | Tables with repeating headers across page breaks |
bagme is part of a broader ecosystem of PDF, typesetting and publishing technologies.
Contact: gundlach@speedata.de
License: New BSD License
Status: Beta — API may change.
Mastodon: boxesandglue@typo.social
$ claude mcp add bagme \
-- python -m otcore.mcp_server <graph>