GraphCompose v2.4.0
v2.4.0 — 2026-09-14
2.4.0 leads with a much larger template line-up. Two
families join invoice, proposal, CV and cover letter: receipt, for payment
confirmations (ModernReceipt), and rota, a staff shift schedule (CobaltRota) on a
new templates.data.rota model that replaces the data.schedule records nothing rendered.
The invoice, proposal and CV families gain presets, and the structured invoice and proposal
models grow to carry what those designs print. Every CV preset is now either
ATS-friendly or design-first, a classification made by reading its showcase sample
with three resume parsers; the showcase marks the ATS-friendly ones.
The engine work under it is typographic. DocumentTextStyle carries real letter
spacing — PDF Tc, DrawingML spc, Word w:spacing — so spaced caps copy and search as
the word they are instead of letters padded with spaces, and the built-in CV and
cover-letter presets use it. A timeline's rail is one line resolved from where its markers
landed, and the timeline can put a column before its markers, size the marker column in
points and set the gap before a marker on its own. A list can hang its wrapped lines under
its text, style an item in pieces, and draw its markers in a colour of their own.
graph-compose-templates joins graph-compose-core under the binary-compatibility gate.
Public API
- A proposal block carries the paragraph that opens it.
- A proposal carries the header a one-page sales proposal has.
- An invoice line carries where it was delivered.
- A supplier carries the legal line it prints under its name.
- A billed party carries a printed registration.
- An invoice line carries a mark.
CvSkillcarries the level as the document words it.- The structured invoice model carries what a second sheet needs.
CvEntrycarries a link.CvEntrycarries a location and a mark, and gains a builder.CvIdentitycarries an optional portrait.- A structured invoice document model.
- A structured proposal document model.
- A rota document model, replacing
data.schedule. - One place turns a printed contact into a followable one:
core.identity.ContactUri. - Text style carries typographic tracking.
- The built-in CV and cover-letter presets now use real tracking, so their text is readable again.
- A list can hang its wrapped lines under its own text instead of under its marker.
- A list item can be styled in pieces.
- A list marker can be drawn, and can carry a colour of its own.
- A timeline's rail is one line, drawn from where its markers landed.
- A timeline's rail is one configuration.
- A timeline marker can be anything you can draw.
- A timeline's marker column can be given a width in points.
- A timeline can put a column before its markers — the
DATEofDATE | ● | CONTENT. - The gap before a timeline's marker is its own number.
- A timeline entry can fill its own content column.
- A vertical flow can pin its width and still grow with its content.
- A chip is sized like the text around it.
inlineStyledChip(text, textStyle, bg)styles a chip that is meant to differ from its paragraph.
Layout
- A resolved anchor on content that spans pages is now that page's slice of the box.
- A timeline's markers now report where they landed, and the marker column gains a level in the node tree.
- A built-in feature can now draw from geometry the layout has already resolved.
- A decorated root flow and its children can disagree under per-page margins.
- A composed table cell sits where its anchor says, and a spanning one stops falling to the foot of its span.
- A row child with a horizontal margin is measured and placed at the same width.
- A margin on composed table-cell content is honoured, and honoured by both passes.
Fixed
- The weekly-schedule board's foot is a footer.
- Five designs dialled a number they had not printed.
markerOnRail()no longer draws the rail through the entry's text.- A timeline marker is the box it declared.
- A timeline inside a card keeps its rail.
- A DOCX export no longer loses the content of a wrapper it cannot draw.
Templates
- Five CV presets name their sections with the headings resume parsers look for.
- Four sidebar CVs draw the name first, and the page looks the same.
- Professional Sidebar and Terracotta Rail carry a longer CV onto more pages.
- A stacked row's body now hangs under its name, not a couple of points to the left of it.
- A long degree title no longer draws over its own institution line on Professional Sidebar.
- Orange Ops' skills are a real list.
- Teal Pulse's dotted lines are a real list, so its one declared gap is the gap it draws.
- New
receiptfamily — payment confirmations. SvgGlyph.fromFile(Path). The classpath variant covers glyphs a template ships with; this covers the glyph a template is given — a receipt's issuer mark, a report's client logo — which arrives as a file beside the running application rather than repackaged into its jar.- The invoice presets set their page number in their own face.
- Seven CV presets make their telephone number dialable.
- A commerce invoice preset:
MerchantInvoice. - A dark invoice preset:
ObsidianInvoice. - A per-seat subscription invoice preset:
SubscriptionInvoice. - A region-billed platform invoice preset:
PlatformInvoice. - A metered-usage invoice preset:
MeteredInvoice. - A violet SaaS invoice preset:
WorkspaceInvoice. - A paginating invoice preset:
PaymentsInvoice. - A navy-plate CV preset:
MidnightNavy. - A two-column operations CV preset:
OrangeOps. - A banded single-column CV preset:
VioletGrid. - A masthead-and-rail CV preset:
SlateOrange. - A clinical CV preset in five bands:
TealPulse. - An architect's two-column CV preset:
TerracottaRail. - The first invoice preset that paginates what it ports:
LumaStudioInvoice. SerifHeadlinelinks its titles and lets its bands breathe.- A photographic CV preset:
CharcoalGold. - A two-column editorial CV preset:
SerifHeadline. - A portrait CV preset:
NavySidebar. - The first CV preset that owns its page:
ProfessionalSidebar. - A second structured proposal preset:
EditorialProposal. - A professional-services invoice preset:
ConsultingInvoice. - A second invoice preset:
ClassicInvoice. - The first structured proposal preset:
NorthlineProposal. - A one-page sales proposal preset:
IndigoProposal. - The first rota preset:
CobaltRota. - The rails seven CV presets drew by hand are timelines.
- Serif Headline's bullet gap is a measurement rather than a space.
- A Timeline Minimal marker that never drew is gone.
- The receipt and both structured proposals stop padding their spaced caps.
Tests
- Letter spacing carried in widths is held to the picture
Tcdraws. - The schedule fixtures no longer carry a real venue's staff.
- The CodeQL scope guard can no longer be emptied by rewriting a deploy command.
- The sidebar CV samples are held to the width of the column they are drawn in.
- Every promoted CV design is asked the same question about its telephone link.
- The timeline's finished visual model is pinned scene by scene.
- A timeline written before the rail moved is guarded against moving.
Deprecations
templates.data.schedule— every type.TextOrnaments.spacedUpper(String)is@Deprecated(since = "2.4.0", forRemoval = true).
Build
graph-compose-templatesis under the binary-compatibility gate.
Documentation
- The timeline recipe describes the finished model.
- Two engine seams are written down, and so is the difference between them.
- A row's width rule, and what
fill()does when there is no slot. - The stability document is guarded, and the pack records a beta package.
- Every CV preset is either ATS-friendly or design-first, and the showcase says which.
- The README leads with a first PDF, then routes by task, and every template family has a door.
Each entry above is the first line of its CHANGELOG entry. The full notes — what changed, why, and how it was verified — are too long for a GitHub Release body; read them in CHANGELOG.md at v2.4.0.