Your first letter
First make the library available to your build. These examples use the no-argument generator and engine-provided standard fonts. No font/image assets or framework configuration are required.
Choose an input
Section titled “Choose an input”The Java tabs contain complete runnable programs. The JSON and HTML tabs contain complete resource files used by the runners below. These exact inputs are compiled/rendered by the project’s documentation integration test.
import com.nsdev.lettergenerator.Letter;import com.nsdev.lettergenerator.LetterPdfGenerator;import java.nio.file.Files;import java.nio.file.Path;
/** A complete first letter using the fluent API and engine-provided standard fonts. */public final class FluentQuickstart { private FluentQuickstart() {}
public static void main(String[] args) throws Exception { var letter = Letter.builder().body("Hello from Letter Generator").build(); byte[] pdf = new LetterPdfGenerator().generate(letter); Files.write(Path.of(args.length == 0 ? "letter.pdf" : args[0]), pdf); }}import com.nsdev.lettergenerator.LetterPdfGenerator;import com.nsdev.lettergenerator.model.LetterDocument;import com.nsdev.lettergenerator.model.Section;import com.nsdev.lettergenerator.model.block.Paragraph;import com.nsdev.lettergenerator.model.text.TextRun;import java.nio.file.Files;import java.nio.file.Path;import java.util.List;
/** The same letter constructed directly from immutable public model values. */public final class TypedQuickstart { private TypedQuickstart() {}
public static void main(String[] args) throws Exception { var letter = new LetterDocument( LetterDocument.SUPPORTED_SCHEMA_VERSION, null, null, List.of( new Section( "body", null, List.of( new Paragraph( List.of( new TextRun( "Hello from Letter Generator", null, null)), null)))), List.of(), null, null); byte[] pdf = new LetterPdfGenerator().generate(letter); Files.write(Path.of(args.length == 0 ? "letter.pdf" : args[0]), pdf); }}{ "schemaVersion": 1, "sections": [{ "name": "body", "blocks": [{ "type": "paragraph", "runs": [{ "text": "Hello from Letter Generator" }] }] }]}<letter page="a4"> <main> <p>${message}</p> </main></letter>Run JSON or HTML from Java
Section titled “Run JSON or HTML from Java”Save the resource above as src/main/resources/letters/hello.json or hello.html. The HTML value map supplies literal text to ${message}; it does not insert markup.
import com.nsdev.lettergenerator.LetterPdfGenerator;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;
/** Render a strict JSON resource with the same defaults as Java construction. */public final class JsonQuickstart { private JsonQuickstart() {}
public static void main(String[] args) throws Exception { String source; try (var stream = JsonQuickstart.class.getResourceAsStream("/letters/hello.json")) { if (stream == null) { throw new IllegalStateException("Missing /letters/hello.json resource"); } source = new String(stream.readAllBytes(), StandardCharsets.UTF_8); } byte[] pdf = new LetterPdfGenerator().generateJson(source); Files.write(Path.of(args.length == 0 ? "letter.pdf" : args[0]), pdf); }}import com.nsdev.lettergenerator.Letter;import com.nsdev.lettergenerator.LetterPdfGenerator;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;import java.util.Map;
/** Bind literal data to trusted letter markup and render through the shared model. */public final class HtmlQuickstart { private HtmlQuickstart() {}
public static void main(String[] args) throws Exception { String source; try (var stream = HtmlQuickstart.class.getResourceAsStream("/letters/hello.html")) { if (stream == null) { throw new IllegalStateException("Missing /letters/hello.html resource"); } source = new String(stream.readAllBytes(), StandardCharsets.UTF_8); } var letter = Letter.template(source) .values(Map.of("message", "Hello from Letter Generator")) .build(); byte[] pdf = new LetterPdfGenerator().generate(letter); Files.write(Path.of(args.length == 0 ? "letter.pdf" : args[0]), pdf); }}Build and run
Section titled “Build and run”The example ZIP already contains all four programs and their resources. In the extracted directory:
mvn package dependency:copy-dependenciesjava -Djava.awt.headless=true -cp "target/classes:target/dependency/*" FluentQuickstartUse TypedQuickstart, JsonQuickstart or HtmlQuickstart for the other routes. Windows uses ; between classpath entries. Each writes letter.pdf, or the first supplied argument. The parent directory of a chosen output path must exist.

What happens at each step
Section titled “What happens at each step”- Authoring creates content and styles. The typed/JSON routes supply the immutable model structure explicitly.
build()resolves builder configuration into a document; it does not generate PDF bytes.generate(...)prepares themes/components, validates input and performs real pagination/layout.Files.write(...)belongs to your application; the library itself returns owned PDF bytes.
Use generator.render(document) when you need the actual page count and diagnostics. Reuse the generator across calls; use a fresh mutable builder for each authoring operation. Invalid input or rejected layout throws without returning a partial PDF.
Continue with API guides, styled text, headers or the energy-letter walkthrough.