Basic Usage
Creating a Document
Every PDF starts with creating a Document using template.New():
import (
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
doc := template.New(
template.WithPageSize(document.A4),
template.WithMargins(document.UniformEdges(document.Mm(20))),
)
Document Options
| Option | Description |
|---|---|
WithPageSize(size) | Page dimensions — document.A4, A3, Letter, Legal |
WithMargins(edges) | Page margins using document.UniformEdges() or custom document.Edges{} |
WithFont(family, data) | Register a TrueType font (pass font file bytes) |
WithDefaultFont(family, size) | Set the default font family and size |
WithMetadata(meta) | Set title, author, subject, creator |
Adding Pages and Content
Content is organized in a hierarchy: Document → Page → Row → Column → Elements
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) { // Auto-height row
r.Col(12, func(c *template.ColBuilder) { // Full-width column
c.Text("Hello, World!", template.FontSize(24), template.Bold())
})
})
┌─ Page ────────────────────────────────┐
│ ┌─ Row ─────────────────────────────┐ │
│ │ ┌─ Col(12) ─────────────────────┐ │ │
│ │ │ Hello, World! │ │ │
│ │ └───────────────────────────────┘ │ │
│ └───────────────────────────────────┘ │
└───────────────────────────────────────┘
Text Styling
Apply styles as functional options on c.Text():
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
// Font sizes
c.Text("Font Size 8pt", template.FontSize(8))
c.Text("Font Size 12pt (default)", template.FontSize(12))
c.Text("Font Size 24pt", template.FontSize(24))
c.Text("Font Size 36pt", template.FontSize(36))
// Weight and style
c.Text("Normal text")
c.Text("Bold text", template.Bold())
c.Text("Italic text", template.Italic())
c.Text("Bold + Italic text", template.Bold(), template.Italic())
// Colors
c.Text("Red text", template.TextColor(pdf.Red))
c.Text("Custom color", template.TextColor(pdf.RGB(1.0, 0.5, 0.0)))
c.Text("Hex color", template.TextColor(pdf.RGBHex(0x336699)))
// Background
c.Text("Yellow background", template.BgColor(pdf.Yellow))
c.Text("White on dark",
template.TextColor(pdf.White),
template.BgColor(pdf.RGBHex(0x333333)),
)
// Alignment
c.Text("Left aligned (default)", template.AlignLeft())
c.Text("Center aligned", template.AlignCenter())
c.Text("Right aligned", template.AlignRight())
})
})
┌─────────────────────────────────────────────┐
│ Font Size 8pt │ ← small text
│ Font Size 12pt (default) │
│ Font Size 24pt │ ← large text
│ Font Size 36pt │ ← very large text
│ │
│ Normal text │
│ Bold text │ ← bold
│ Italic text │ ← italic
│ Bold + Italic text │ ← both
│ │
│ Red text │ ← colored
│ Custom color │ ← RGB(1.0, 0.5, 0.0)
│ Hex color │ ← #336699
│ │
│ Yellow background │ ← highlighted
│ White on dark │ ← inverted
│ │
│ Left aligned (default) │
│ Center aligned │
│ Right aligned │
└─────────────────────────────────────────────┘
Two-Column Layout
Use the 12-column grid to create multi-column layouts:
page.AutoRow(func(r *template.RowBuilder) {
r.Col(6, func(c *template.ColBuilder) {
c.Text("Left column")
})
r.Col(6, func(c *template.ColBuilder) {
c.Text("Right column")
})
})
┌──────────────────────┬──────────────────────┐
│ Left column │ Right column │
└──────────────────────┴──────────────────────┘
Tables
Create tables with headers and data rows:
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Table(
[]string{"Name", "Age", "City"},
[][]string{
{"Alice", "30", "Tokyo"},
{"Bob", "25", "New York"},
{"Charlie", "35", "London"},
{"Diana", "28", "Paris"},
},
)
})
})
┌─────────────────────────────────────────┐
│ Name │ Age │ City │ ← header
├────────────┼───────┼────────────────────┤
│ Alice │ 30 │ Tokyo │
│ Bob │ 25 │ New York │
│ Charlie │ 35 │ London │
│ Diana │ 28 │ Paris │
└────────────┴───────┴────────────────────┘
Styled Tables
Add custom column widths, header styles, and stripe colors:
darkBlue := pdf.RGBHex(0x1A237E)
lightGray := pdf.RGBHex(0xF5F5F5)
c.Table(
[]string{"Product", "Category", "Qty", "Unit Price", "Total"},
[][]string{
{"Laptop Pro 15", "Electronics", "2", "$1,299.00", "$2,598.00"},
{"Wireless Mouse", "Accessories", "10", "$29.99", "$299.90"},
{"USB-C Hub", "Accessories", "5", "$49.99", "$249.95"},
},
template.ColumnWidths(30, 20, 10, 20, 20),
template.TableHeaderStyle(
template.TextColor(pdf.White),
template.BgColor(darkBlue),
),
template.TableStripe(lightGray),
)
┌─────────────────────────────────────────────────────────┐
│ Product │ Category │ Qty │ Unit Price │ Total │ ← white on dark blue
├───────────────┼─────────────┼─────┼────────────┼────────┤
│ Laptop Pro │ Electronics │ 2 │ $1,299.00 │$2,598 │ ← white bg
│ Wireless.. │ Accessories │ 10 │ $29.99 │ $299 │ ← light gray stripe
│ USB-C Hub │ Accessories │ 5 │ $49.99 │ $249 │ ← white bg
└───────────────┴─────────────┴─────┴────────────┴────────┘
Lines and Spacers
// Horizontal rule
c.Line()
c.Line(template.LineColor(pdf.Red), template.LineThickness(document.Pt(2)))
// Vertical spacing
c.Spacer(document.Mm(10))
Output
// Option 1: Get PDF as byte slice
data, err := doc.Generate()
if err != nil {
log.Fatal(err)
}
os.WriteFile("output.pdf", data, 0644)
// Option 2: Write to any io.Writer (http.ResponseWriter, file, buffer...)
err := doc.Render(w)
Complete Example: Invoice
doc := template.New(
template.WithPageSize(document.A4),
template.WithMargins(document.UniformEdges(document.Mm(20))),
template.WithMetadata(document.DocumentMetadata{
Title: "Invoice #INV-2026-001",
Author: "ACME Corporation",
}),
)
page := doc.AddPage()
// Company header
page.AutoRow(func(r *template.RowBuilder) {
r.Col(6, func(c *template.ColBuilder) {
c.Text("ACME Corporation", template.FontSize(24), template.Bold(),
template.TextColor(pdf.RGBHex(0x1A237E)))
c.Text("123 Business Street")
c.Text("San Francisco, CA 94105")
})
r.Col(6, func(c *template.ColBuilder) {
c.Text("INVOICE", template.FontSize(28), template.Bold(),
template.AlignRight(), template.TextColor(pdf.RGBHex(0x1A237E)))
c.Text("#INV-2026-001", template.AlignRight(), template.FontSize(12))
c.Text("Date: March 1, 2026", template.AlignRight())
})
})
// Separator
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Spacer(document.Mm(5))
c.Line(template.LineColor(pdf.RGBHex(0x1A237E)), template.LineThickness(document.Pt(2)))
c.Spacer(document.Mm(5))
})
})
// Items table
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Table(
[]string{"Description", "Qty", "Unit Price", "Amount"},
[][]string{
{"Web Development - Frontend", "40 hrs", "$150.00", "$6,000.00"},
{"Web Development - Backend", "60 hrs", "$150.00", "$9,000.00"},
{"UI/UX Design", "20 hrs", "$120.00", "$2,400.00"},
},
template.ColumnWidths(40, 15, 20, 25),
template.TableHeaderStyle(
template.TextColor(pdf.White),
template.BgColor(pdf.RGBHex(0x1A237E)),
),
template.TableStripe(pdf.RGBHex(0xF5F5F5)),
)
})
})
// Total
page.AutoRow(func(r *template.RowBuilder) {
r.Col(8, func(c *template.ColBuilder) {})
r.Col(4, func(c *template.ColBuilder) {
c.Text("Total: $17,400.00", template.AlignRight(),
template.Bold(), template.FontSize(14))
})
})
data, _ := doc.Generate()
┌─ A4 ──────────────────────────────────────────────┐
│ │
│ ACME Corporation INVOICE │
│ 123 Business Street #INV-2026-001 │
│ San Francisco, CA 94105 Date: March 1, 2026 │
│ ─────────────────────────────────────────────── │
│ │
│ ┌─────────────┬────────┬───────────┬──────────┐ │
│ │ Description │ Qty │Unit Price │ Amount │ │
│ ├─────────────┼────────┼───────────┼──────────┤ │
│ │ Frontend │ 40 hrs │ $150.00 │$6,000.00 │ │
│ │ Backend │ 60 hrs │ $150.00 │$9,000.00 │ │
│ │ UI/UX │ 20 hrs │ $120.00 │$2,400.00 │ │
│ └─────────────┴────────┴───────────┴──────────┘ │
│ │
│ Total: $17,400.00 │
│ │
└───────────────────────────────────────────────────┘
Next Steps
- Grid Layout — Master the 12-column grid system
- Styling — Colors, text decoration, and typography
- Elements — All available content elements