Skip to content

Quick Start

The fastest way to understand Folio is to generate a document. You can use the PHP builder API, a .folio template, or both in the same project.

PHP Builder API

Describe the document structure directly in PHP:

php
use Folio\Pdf\Document\Pdf;
use Folio\Pdf\Nodes\Column;
use Folio\Pdf\Nodes\Heading;
use Folio\Pdf\Nodes\Page;
use Folio\Pdf\Nodes\Text;

Pdf::make()
    ->page(
        Page::a4()->withContent(
            Column::make(null, [
                Heading::h1('Invoice'),
                Text::make('Customer: John Doe'),
                Text::make('Amount: $100.00'),
            ])
        )
    )
    ->save('invoice.pdf');

Every node is immutable. Column::make(null, [...]) creates a column with a list of children and no style. Page::a4()->withContent(...) builds an A4 page. Pdf::make() is the fluent entry point.

Template Language

Create invoice.folio:

folio
var customer = "John Doe"
var amount = "100.00"

page {
  heading "Invoice"
  text "Customer:"
  text customer
  text "Amount:"
  text amount
}

Compile and render it from PHP:

php
use Folio\Pdf\Template\PhpTemplateCompiler;

$compiler = new PhpTemplateCompiler();

$pdf = $compiler->render(file_get_contents('invoice.folio'), [
    'customer' => 'Jane Smith',
    'amount' => '250.00',
]);

$pdf->save('invoice.pdf');

render() compiles the template to a PHP closure, merges the provided data, and returns a Pdf instance ready to save.

Templates with Control Flow

folio
var title = "Monthly Report"

page {
  heading title
  foreach products as product {
    column {
      heading product.name
      text product.description
      text product.price
    }
  }
}
php
$pdf = $compiler->render(file_get_contents('report.folio'), [
    'title' => 'Q4 Sales Report',
    'products' => [
        ['name' => 'Product A', 'description' => 'Premium widget', 'price' => '99.00'],
        ['name' => 'Product B', 'description' => 'Standard widget', 'price' => '49.00'],
    ],
]);

$pdf->save('report.pdf');

Page Chrome

Headers and footers are defined as pageheader and pagefooter blocks. They are rendered on every page unless you scope them with only.

folio
pageheader(height=40) {
  text "Acme Corporation"
  text "123 Business Street"
}

pagefooter(height=30) {
  text "Page:"
  pagenum(format="{page} / {pages}", size=8)
}

page {
  heading "Document"
  text "Content begins here."
}

Next Steps

Engineered for teams that care about predictable PDF output.