{"id":49695722,"url":"https://github.com/demchaav/graphcompose","last_synced_at":"2026-05-31T23:01:33.316Z","repository":{"id":347321848,"uuid":"1041599549","full_name":"DemchaAV/GraphCompose","owner":"DemchaAV","description":"Declarative Java PDF layout engine for structured business documents — semantic node tree, atomic pagination, theme tokens, PDFBox-backed","archived":false,"fork":false,"pushed_at":"2026-05-25T21:59:38.000Z","size":58411,"stargazers_count":56,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-25T23:28:12.389Z","etag":null,"topics":["business-documents","cv-templates","declarative-api","document-generation","invoice-template","java","java-17","layout-engine","maven","pagination","pdf","pdf-generator","pdf-lib","pdf-library","pdfbox3","report-generation","snapshot-testing","template-engine"],"latest_commit_sha":null,"homepage":"https://demchaav.github.io/GraphCompose/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DemchaAV.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-20T18:16:34.000Z","updated_at":"2026-05-25T17:02:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DemchaAV/GraphCompose","commit_stats":null,"previous_names":["demchaav/graphcompose"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/DemchaAV/GraphCompose","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DemchaAV%2FGraphCompose","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DemchaAV%2FGraphCompose/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DemchaAV%2FGraphCompose/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DemchaAV%2FGraphCompose/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DemchaAV","download_url":"https://codeload.github.com/DemchaAV/GraphCompose/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DemchaAV%2FGraphCompose/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33752286,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["business-documents","cv-templates","declarative-api","document-generation","invoice-template","java","java-17","layout-engine","maven","pagination","pdf","pdf-generator","pdf-lib","pdf-library","pdfbox3","report-generation","snapshot-testing","template-engine"],"created_at":"2026-05-08T00:01:19.857Z","updated_at":"2026-05-31T23:01:33.310Z","avatar_url":"https://github.com/DemchaAV.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GraphCompose\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/GraphComposeLogo.png\" alt=\"GraphCompose logo\" width=\"300\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eDeclarative Java DSL for structured business PDFs.\u003c/b\u003e\u003cbr/\u003e\n  Describe what the document \u003ci\u003esays\u003c/i\u003e; the engine resolves layout, pagination, themes, and PDFBox rendering. \u003cb\u003eCinematic by default.\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/DemchaAV/GraphCompose/actions/workflows/ci.yml?query=branch%3Amain\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/DemchaAV/GraphCompose/ci.yml?branch=main\u0026style=for-the-badge\u0026label=CI\" alt=\"CI\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/DemchaAV/GraphCompose/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/DemchaAV/GraphCompose?style=for-the-badge\u0026label=Release\" alt=\"Latest release\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://central.sonatype.com/artifact/io.github.demchaav/graph-compose\"\u003e\u003cimg src=\"https://img.shields.io/maven-central/v/io.github.demchaav/graph-compose?style=for-the-badge\u0026label=Maven%20Central\" alt=\"Maven Central\"/\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Java-17%2B-orange?style=for-the-badge\u0026logo=openjdk\" alt=\"Java 17+\"/\u003e\n  \u003cimg src=\"https://img.shields.io/badge/PDFBox-3.0-red?style=for-the-badge\" alt=\"PDFBox 3.0\"/\u003e\n  \u003cimg src=\"https://img.shields.io/badge/License-MIT-blue?style=for-the-badge\" alt=\"MIT License\"/\u003e\n\u003c/p\u003e\n\n\u003e **Release status** \u0026mdash;\n\u003e 🟢 **Latest stable**: [v1.6.5](https://github.com/DemchaAV/GraphCompose/releases/tag/v1.6.5)\n\u003e \u0026nbsp;·\u0026nbsp; 🟡 **In develop**: v1.6.6 (Maven Central debut; zero breaking from v1.6.5)\n\u003e \u0026nbsp;·\u0026nbsp; ⚪ **Planned next**: v1.6.7 (dependency cleanup), v1.7.0 (new canonical DSL primitives)\n\u003e \u0026nbsp;·\u0026nbsp; See [API stability policy](./docs/api-stability.md) for tier definitions.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://demchaav.github.io/GraphCompose/\"\u003e\u003cb\u003eLive Showcase\u003c/b\u003e\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"./examples/README.md\"\u003e\u003cb\u003eExamples Gallery\u003c/b\u003e\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"./CHANGELOG.md\"\u003e\u003cb\u003eChangelog\u003c/b\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/readme/repository_showcase_render.png\" alt=\"GraphCompose render preview\" width=\"780\"/\u003e\n\u003c/p\u003e\n\n## Why GraphCompose\n\n- **Author intent, not coordinates.** Fluent DSL for sections, paragraphs, tables, lists, layer stacks, themes \u0026mdash; the engine handles measurement, pagination, and rendering.\n- **Deterministic by design.** Two-pass layout. Snapshots are stable across machines, so layout regressions are catchable in tests before any byte ships.\n- **Cinematic-by-default.** `BusinessTheme` + soft panels + accent strips + transforms + advanced tables are first-class primitives, not workarounds.\n- **PDFBox isolated, DOCX optional.** Single backend interface. Apache POI\u0026ndash;backed DOCX export is available for compatible semantic content \u0026mdash; see [support matrix](#output-support) for limitations.\n\nSits between **iText** (low-level page primitives) and **JasperReports** (XML-template-driven layout): a Java DSL describes the document semantically, the engine renders.\n\n## Scope and comparison\n\n### Output support\n\n| Format | Status | Notes |\n|---|---|---|\n| PDF | Production | Fixed-layout backend on PDFBox 3.0. Full DSL coverage. |\n| DOCX | Partial | Semantic export via Apache POI. Unsupported nodes (`shape`, `line`, `ellipse`, `barcode`) are dropped silently \u0026mdash; layout fidelity is best-effort for paragraph / list / table content. |\n| PPTX | Skeleton | Validates supported node types and emits a manifest. **Not a real PowerPoint export yet** \u0026mdash; planned only if there is demand. |\n\n### When to use GraphCompose\n\n- **Server-side PDF generation in Java** \u0026mdash; invoices, CVs, reports, proposals, statements, schedules.\n- **Templated documents from data** \u0026mdash; themed presets (`ModernProfessional`, `InvoiceTemplateV2`, \u0026hellip;) you parameterise instead of re-styling every time.\n- **Regression-tested layouts** \u0026mdash; `DocumentSession#layoutSnapshot()` makes layout changes visible in PRs before any byte ships.\n- **Streaming PDFs from web backends** \u0026mdash; Spring Boot `@RestController` writing straight to the response ([`HttpStreamingExample`](./examples/src/main/java/com/demcha/examples/features/streaming/HttpStreamingExample.java)).\n- **Higher-level than PDFBox, lighter than JasperReports** \u0026mdash; Java DSL describes semantics; no XML templates, no manual coordinates.\n\n### What GraphCompose is not\n\n- Not a hosted PDF rendering service \u0026mdash; it is a library you embed.\n- Not a WYSIWYG editor \u0026mdash; the DSL is code, not drag-and-drop.\n- Not a reporting engine like JasperReports \u0026mdash; no datasource bindings, no XML templates, no compiled `.jasper` files.\n- Not a browser / HTML-to-PDF renderer \u0026mdash; the engine has its own layout pipeline; HTML/CSS input is not supported.\n\n### Compared with similar Java libraries\n\n| Library | API style | Layout | License | Best for |\n|---|---|---|---|---|\n| **GraphCompose** | Java DSL, semantic nodes | Two-pass, deterministic, snapshot-testable | MIT | Code-first business documents with layout regression tests |\n| **PDFBox** | Low-level text / path primitives | Manual coordinates | Apache 2.0 | Direct PDF manipulation, parsing, extraction |\n| **iText 7** | Low-level page primitives + high-level helpers | Manual + helpers | AGPL / commercial | When AGPL is acceptable or you have a commercial licence |\n| **OpenPDF** | iText 4 fork | Manual + helpers | LGPL / MPL | Legacy iText 4 codebases |\n| **JasperReports** | XML templates compiled to `.jasper` | Template-driven | LGPL | Tabular reports with datasource bindings |\n\nGraphCompose uses PDFBox under the hood as the rendering backend \u0026mdash; the comparison is about authoring surface, not the renderer.\n\n### Which API should I use?\n\n| You want to\u0026hellip; | Surface | Entry point |\n|---|---|---|\n| Generate a one-off PDF programmatically | DSL | `GraphCompose.document(...).pageFlow(...)` \u0026mdash; see [Hello world](#hello-world) below |\n| Generate a CV / cover letter from data | Layered templates | `ModernProfessional.create().compose(session, cvDocument)` \u0026mdash; see [layered templates](./docs/templates/v2-layered/README.md) |\n| Add a custom visual primitive | Engine extension | `NodeDefinition` + `PdfFragmentRenderHandler` \u0026mdash; see [extension guide](./docs/contributing/extension-guide.md) |\n| Regression-test generated layouts | Layout snapshots | `DocumentSession#layoutSnapshot()` \u0026mdash; see [snapshot testing](./docs/operations/layout-snapshot-testing.md) |\n\n## Installation\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.demchaav\u003c/groupId\u003e\n    \u003cartifactId\u003egraph-compose\u003c/artifactId\u003e\n    \u003cversion\u003e1.6.6\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n```kotlin\ndependencies { implementation(\"io.github.demchaav:graph-compose:1.6.6\") }\n```\n\n\u003e **Distribution** \u0026mdash; Maven Central is the canonical channel from **v1.6.6** onwards\n\u003e (`io.github.demchaav:graph-compose:\u003cversion\u003e`). Hosted Javadocs auto-publish to\n\u003e [javadoc.io/doc/io.github.demchaav/graph-compose](https://javadoc.io/doc/io.github.demchaav/graph-compose)\n\u003e shortly after each Central release. The legacy JitPack URL\n\u003e (`com.github.DemchaAV:GraphCompose:v\u003cversion\u003e`) remains resolvable for callers\n\u003e pinned to v1.6.5 and earlier but is no longer the documented install option.\n\n\u003e **Upgrading from v1.5?** Core document authoring stays source-compatible \u0026mdash; engine, DSL, themes, and backend-neutral records carry v1.5 callers unchanged. **Templates v2** replaces the legacy CV / cover-letter template classes; legacy classes were **deleted**, not deprecated. Read the [migration guide](./docs/roadmaps/migration-v1-5-to-v1-6.md) before upgrading template-heavy code.\n\n## Hello world\n\n```java\nimport com.demcha.compose.GraphCompose;\nimport com.demcha.compose.document.api.DocumentPageSize;\nimport com.demcha.compose.document.api.DocumentSession;\nimport com.demcha.compose.document.theme.BusinessTheme;\n\nimport java.nio.file.Path;\n\nclass Hello {\n    public static void main(String[] args) throws Exception {\n        BusinessTheme theme = BusinessTheme.modern();\n\n        try (DocumentSession document = GraphCompose.document(Path.of(\"hello.pdf\"))\n                .pageSize(DocumentPageSize.A4)\n                .pageBackground(theme.pageBackground())\n                .margin(28, 28, 28, 28)\n                .create()) {\n\n            document.pageFlow(page -\u003e page\n                    .addSection(\"Hero\", section -\u003e section\n                            .softPanel(theme.palette().surfaceMuted(), 10, 14)\n                            .accentLeft(theme.palette().accent(), 4)\n                            .addParagraph(p -\u003e p.text(\"GraphCompose\").textStyle(theme.text().h1()))\n                            .addParagraph(p -\u003e p.text(\"A theme-driven hero, no manual coordinates.\")\n                                    .textStyle(theme.text().body()))));\n\n            document.buildPdf();\n        }\n    }\n}\n```\n\nFor a Spring Boot `@RestController` streaming the PDF straight to the response, see [`HttpStreamingExample`](./examples/src/main/java/com/demcha/examples/features/streaming/HttpStreamingExample.java).\n\n## What's in v1.6 \u0026mdash; \"expressive\"\n\n- **Layered templates** \u0026mdash; 14 CV and 14 paired cover-letter presets on the layered `cv.v2` / `coverletter.v2` architecture (data → theme → components → widgets → presets), one-liner `create()` factories over a typed `CvDocument` / `CoverLetterDocument`. Inline markdown, multi-column layouts. The going-forward standard for new template families. See [`docs/templates/v2-layered/README.md`](./docs/templates/v2-layered/README.md). (The earlier `BusinessTheme`-based preset surface is now deprecated.)\n- **Composed primitives** \u0026mdash; `ListBuilder.addItem(label, Consumer)` (nested lists), `DocumentTableCell.node(...)` (any node inside a cell), `CanvasLayerNode` (pixel-precise free-canvas placement).\n- **Architecture hardening** \u0026mdash; `@Internal` API stability marker, public `PdfFragmentRenderHandler` SPI, `DocumentRenderingException` on the convenience render path, documented thread-safety contract.\n\nFull notes in [`CHANGELOG.md`](./CHANGELOG.md). Upgrade guide: [`docs/roadmaps/migration-v1-5-to-v1-6.md`](./docs/roadmaps/migration-v1-5-to-v1-6.md).\n\n## v1.6 primitives in 30 lines\n\nThree snippets, one per new primitive. Full runnable versions live in the [examples gallery](./examples/README.md).\n\n**Nested list** \u0026mdash; builder-callback child scopes with a per-depth marker cascade.\n\n```java\ndocument.pageFlow().addList(list -\u003e list\n    .addItem(\"Backend platform\", row -\u003e row\n        .addItem(\"Java 21, Spring Boot, PostgreSQL\")\n        .addItem(\"REST APIs and event-driven services\"))\n    .addItem(\"Document generation\", row -\u003e row\n        .addItem(\"PDF rendering pipeline\")\n        .addItem(\"Layout snapshot tests\")));\n```\n\n**Composed table cell** \u0026mdash; any composable node inside a cell, two-pass row measurement.\n\n```java\nDocumentTableCell richSummary = DocumentTableCell.node(\n        new ParagraphNode(\"Summary\",\n                \"**Q3 results** were *strong* — revenue grew 18% YoY.\",\n                bodyStyle, TextAlign.LEFT, 1.0,\n                DocumentInsets.zero(), DocumentInsets.zero()));\n```\n\n**Canvas layer** \u0026mdash; pixel-precise `(x, y)` placement inside a fixed bounding box.\n\n```java\ndocument.pageFlow().addCanvas(523, 360, canvas -\u003e canvas\n        .clipPolicy(ClipPolicy.CLIP_BOUNDS)\n        .position(headline, 0, 60)\n        .position(rule(503, 1.4, accent), 10, 32));\n```\n\n## Documentation\n\n📚 **[Full docs index](./docs/README.md)** \u0026mdash; categorised map of every doc, ADR, and recipe. Start there to navigate the documentation.\n\n### Templates\n- 🆕 [**Templates — v2 layered architecture**](./docs/templates/v2-layered/README.md) \u0026mdash; the canonical going-forward pattern for new template families (CV v2 is the reference implementation). Personas: [quickstart](./docs/templates/v2-layered/quickstart.md) · [using templates](./docs/templates/v2-layered/using-templates.md) · [authoring presets](./docs/templates/v2-layered/authoring-presets.md) · [contributing a new family](./docs/templates/v2-layered/contributor-guide.md).\n- [Templates v1-classic landing](./docs/templates/v1-classic/README.md) \u0026mdash; the older `BusinessTheme` / `CvSpec` CV / cover-letter / invoice / proposal preset library (**deprecated** — CV + cover letter are superseded by [v2-layered](./docs/templates/v2-layered/README.md); invoice / proposal / schedule are not yet ported). Cheat sheet: [authoring](./docs/templates/v1-classic/authoring.md).\n\n### Architecture \u0026 operations\n- [Architecture overview](./docs/architecture/overview.md) · [Lifecycle](./docs/architecture/lifecycle.md) · [Production rendering](./docs/operations/production-rendering.md) · [Layout snapshot testing](./docs/operations/layout-snapshot-testing.md)\n\n### Recipes \u0026 examples\n- [Recipes index](./docs/recipes.md) \u0026mdash; [shape-as-container](./docs/recipes/shape-as-container.md) · [shapes](./docs/recipes/shapes.md) · [transforms](./docs/recipes/transforms.md) · [tables](./docs/recipes/tables.md) · [themes](./docs/recipes/themes.md) · [streaming](./docs/recipes/streaming.md) · [extending](./docs/recipes/extending.md)\n- [Examples gallery](./examples/README.md) \u0026mdash; every runnable example with PDF preview\n\n### Contributing \u0026 releases\n- [Contributing](./CONTRIBUTING.md) · [Code of conduct](./CODE_OF_CONDUCT.md) · [Security policy](./SECURITY.md) · [Release process](./docs/contributing/release-process.md)\n- [API stability policy](./docs/api-stability.md) · [Which template system?](./docs/templates/which-template-system.md) · [Migration v1.5 → v1.6](./docs/roadmaps/migration-v1-5-to-v1-6.md)\n\n## Companion projects\n\n- [**graphcompose-ai-flow**](https://github.com/DemchaAV/graphcompose-ai-flow) \u0026mdash; experimental sister project exploring an AI-assisted authoring flow on top of GraphCompose. Independent codebase, separate lifecycle \u0026mdash; nothing in this repo depends on it. Track it if you are interested in agentic document composition driven by the same semantic node model.\n\n## License\n\nMIT \u0026mdash; see [`LICENSE`](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdemchaav%2Fgraphcompose","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdemchaav%2Fgraphcompose","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdemchaav%2Fgraphcompose/lists"}