diff --git a/benchmarks/src/main/java/com/demcha/compose/AllocationRateProbe.java b/benchmarks/src/main/java/com/demcha/compose/AllocationRateProbe.java index e81c2af92..1d4ad6ac3 100644 --- a/benchmarks/src/main/java/com/demcha/compose/AllocationRateProbe.java +++ b/benchmarks/src/main/java/com/demcha/compose/AllocationRateProbe.java @@ -2,10 +2,11 @@ import com.demcha.compose.document.api.DocumentPageSize; import com.demcha.compose.document.api.DocumentSession; -import com.demcha.compose.document.templates.builtins.InvoiceTemplateV1; -import com.demcha.compose.document.templates.builtins.ProposalTemplateV1; +import com.demcha.compose.document.templates.api.DocumentTemplate; import com.demcha.compose.document.templates.data.invoice.InvoiceDocumentSpec; import com.demcha.compose.document.templates.data.proposal.ProposalDocumentSpec; +import com.demcha.compose.document.templates.invoice.v2.presets.ModernInvoice; +import com.demcha.compose.document.templates.proposal.v2.presets.ModernProposal; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; @@ -46,9 +47,9 @@ public static void main(String[] args) throws Exception { enableAllocationMeasurement(); InvoiceDocumentSpec invoice = CanonicalBenchmarkSupport.canonicalInvoice(); - InvoiceTemplateV1 invoiceTemplate = new InvoiceTemplateV1(); + DocumentTemplate invoiceTemplate = ModernInvoice.create(); ProposalDocumentSpec proposal = CanonicalBenchmarkSupport.canonicalProposal(); - ProposalTemplateV1 proposalTemplate = new ProposalTemplateV1(); + DocumentTemplate proposalTemplate = ModernProposal.create(); System.out.println("GraphCompose allocation-rate / GC-pressure probe (" + MEASURE + " warm renders each)"); System.out.printf("%-12s | %14s | %10s | %12s | %12s%n", diff --git a/benchmarks/src/main/java/com/demcha/compose/CurrentSpeedBenchmark.java b/benchmarks/src/main/java/com/demcha/compose/CurrentSpeedBenchmark.java index 46706038a..499800b8f 100644 --- a/benchmarks/src/main/java/com/demcha/compose/CurrentSpeedBenchmark.java +++ b/benchmarks/src/main/java/com/demcha/compose/CurrentSpeedBenchmark.java @@ -13,12 +13,12 @@ import com.demcha.compose.document.style.DocumentTextStyle; import com.demcha.compose.document.svg.SvgIcon; import com.demcha.compose.document.templates.api.DocumentTemplate; -import com.demcha.compose.document.templates.builtins.InvoiceTemplateV1; -import com.demcha.compose.document.templates.builtins.ProposalTemplateV1; import com.demcha.compose.document.templates.cv.presets.ModernProfessional; import com.demcha.compose.document.templates.cv.spec.CvSpec; import com.demcha.compose.document.templates.data.invoice.InvoiceDocumentSpec; import com.demcha.compose.document.templates.data.proposal.ProposalDocumentSpec; +import com.demcha.compose.document.templates.invoice.v2.presets.ModernInvoice; +import com.demcha.compose.document.templates.proposal.v2.presets.ModernProposal; import com.demcha.compose.document.theme.BusinessTheme; import com.demcha.compose.engine.components.style.Margin; import org.apache.pdfbox.pdmodel.common.PDRectangle; @@ -85,9 +85,9 @@ public final class CurrentSpeedBenchmark { .color(DocumentColor.of(new Color(58, 69, 84))) .build(); - private final InvoiceTemplateV1 invoiceTemplate = new InvoiceTemplateV1(); + private final DocumentTemplate invoiceTemplate = ModernInvoice.create(); private final DocumentTemplate cvTemplate = ModernProfessional.create(BusinessTheme.modern()); - private final ProposalTemplateV1 proposalTemplate = new ProposalTemplateV1(); + private final DocumentTemplate proposalTemplate = ModernProposal.create(); private final InvoiceDocumentSpec invoice = CanonicalBenchmarkSupport.canonicalInvoice(); private final ProposalDocumentSpec proposal = CanonicalBenchmarkSupport.canonicalProposal(); private final CvSpec cv = CanonicalBenchmarkSupport.canonicalCv(); diff --git a/benchmarks/src/main/java/com/demcha/compose/jmh/ColdStartJmhBenchmark.java b/benchmarks/src/main/java/com/demcha/compose/jmh/ColdStartJmhBenchmark.java index a21e3ddbc..6504c8a6f 100644 --- a/benchmarks/src/main/java/com/demcha/compose/jmh/ColdStartJmhBenchmark.java +++ b/benchmarks/src/main/java/com/demcha/compose/jmh/ColdStartJmhBenchmark.java @@ -5,10 +5,10 @@ import com.demcha.compose.document.api.DocumentPageSize; import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.style.DocumentInsets; -import com.demcha.compose.document.templates.builtins.InvoiceTemplateV1; import com.demcha.compose.document.templates.cv.presets.ModernProfessional; import com.demcha.compose.document.templates.cv.spec.CvSpec; import com.demcha.compose.document.templates.data.invoice.InvoiceDocumentSpec; +import com.demcha.compose.document.templates.invoice.v2.presets.ModernInvoice; import com.demcha.compose.document.theme.BusinessTheme; import com.demcha.compose.document.templates.api.DocumentTemplate; import org.openjdk.jmh.annotations.Benchmark; @@ -37,7 +37,7 @@ * reported number is a distribution of cold first-renders, not one lucky start. * The spec/template objects are built in {@link #setUp()} so the measured shot is * the cold render path, not fixture assembly. Same workloads as the warm benches - * ({@code engine-simple} inline, {@code InvoiceTemplateV1}, {@code ModernProfessional}) + * ({@code engine-simple} inline, {@code ModernInvoice}, {@code ModernProfessional}) * so cold and warm numbers are directly comparable.

* *
@@ -56,7 +56,7 @@
 public class ColdStartJmhBenchmark {
 
     private InvoiceDocumentSpec invoice;
-    private InvoiceTemplateV1 invoiceTemplate;
+    private DocumentTemplate invoiceTemplate;
     private CvSpec cv;
     private DocumentTemplate cvTemplate;
 
@@ -64,7 +64,7 @@ public class ColdStartJmhBenchmark {
     @Setup
     public void setUp() {
         invoice = CanonicalBenchmarkSupport.canonicalInvoice();
-        invoiceTemplate = new InvoiceTemplateV1();
+        invoiceTemplate = ModernInvoice.create();
         cv = CanonicalBenchmarkSupport.canonicalCv();
         cvTemplate = ModernProfessional.create(BusinessTheme.modern());
     }
@@ -96,7 +96,7 @@ public byte[] coldEngineSimple() throws Exception {
     }
 
     /**
-     * Cold first render of the canonical invoice through {@code InvoiceTemplateV1}.
+     * Cold first render of the canonical invoice through {@code ModernInvoice}.
      *
      * @return the rendered PDF bytes (consumed by JMH)
      * @throws Exception if rendering fails
diff --git a/examples/README.md b/examples/README.md
index e87e62dbf..ef5a56285 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -127,10 +127,8 @@ are with the canonical DSL, then jump to its detailed section below.
 
 | Example | What it shows | Preview · Source |
 |---|---|---|
-| [Invoice (V1)](#invoice-v1) | `InvoiceTemplateV1` driven from `InvoiceDocumentSpec` — pre-rebuild surface, supported only | [PDF](../assets/readme/examples/invoice.pdf) · [Source](src/main/java/com/demcha/examples/templates/invoice/InvoiceFileExample.java) |
-| [Proposal (V1)](#proposal-v1) | `ProposalTemplateV1` driven from `ProposalDocumentSpec` — pre-rebuild surface, supported only | [PDF](../assets/readme/examples/proposal.pdf) · [Source](src/main/java/com/demcha/examples/templates/proposal/ProposalFileExample.java) |
 | [Handcrafted Proposal](#handcrafted-proposal) | v1.4-style cinematic proposal composed by hand — pre-template authoring; kept for parity reference | [PDF](../assets/readme/examples/project-proposal-cinematic.pdf) · [Source](src/main/java/com/demcha/examples/templates/proposal/CinematicProposalFileExample.java) |
-| [Weekly schedule](#weekly-schedule) | Bar / restaurant shift schedule via `WeeklyScheduleRenderer` (`WeeklyScheduleTemplateV1` — no V2 yet; will be re-shaped before 2.0) | [PDF](../assets/readme/examples/weekly-schedule.pdf) · [Source](src/main/java/com/demcha/examples/templates/schedule/WeeklyScheduleFileExample.java) |
+| [Weekly schedule](#weekly-schedule) | Bar / restaurant shift schedule via `WeeklyScheduleRenderer` | [PDF](../assets/readme/examples/weekly-schedule.pdf) · [Source](src/main/java/com/demcha/examples/templates/schedule/WeeklyScheduleFileExample.java) |
 
 ---
 
@@ -177,45 +175,6 @@ try (DocumentSession document = GraphCompose.document(outputFile)
 [📄 View PDF](../assets/readme/examples/cover-letter.pdf) ·
 [📜 Full source](src/main/java/com/demcha/examples/templates/coverletter/CoverLetterFileExample.java)
 
-### Invoice (V1)
-
-`InvoiceTemplateV1.compose(document, spec)` handles the full layout —
-header band, parties row, line-items table, totals row, payment-terms
-footer — driven from a `InvoiceDocumentSpec`. Use this when you want
-the legacy hard-coded theme; for V2 cinematic, see below.
-
-```java
-InvoiceDocumentSpec spec = InvoiceDocumentSpec.builder()
-        .invoiceNumber("GC-2026-041")
-        .issueDate("02 Apr 2026")
-        .dueDate("16 Apr 2026")
-        .fromParty(p -> p.name("GraphCompose Studio"))
-        .billToParty(p -> p.name("Northwind Systems"))
-        .lineItem("Template architecture", "Reusable invoice flow", "2", "GBP 980", "GBP 1,960")
-        .totalRow("Total", "GBP 1,960")
-        .build();
-
-try (DocumentSession document = GraphCompose.document(outputFile)
-        .pageSize(DocumentPageSize.A4)
-        .margin(28, 28, 28, 28)
-        .create()) {
-    new InvoiceTemplateV1().compose(document, spec);
-    document.buildPdf();
-}
-```
-
-[📄 View PDF](../assets/readme/examples/invoice.pdf) ·
-[📜 Full source](src/main/java/com/demcha/examples/templates/invoice/InvoiceFileExample.java)
-
-### Proposal (V1)
-
-`ProposalTemplateV1` rendered against a `ProposalDocumentSpec` —
-sections, scope items, deliverables, sign-off. Pairs naturally with
-`InvoiceTemplateV1` for consistent "spec → PDF" pipelines.
-
-[📄 View PDF](../assets/readme/examples/proposal.pdf) ·
-[📜 Full source](src/main/java/com/demcha/examples/templates/proposal/ProposalFileExample.java)
-
 ### Module-first profile
 
 Authoring against `DocumentSession.pageFlow().module(...)` — no
diff --git a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
index e566e387a..32b9a2aa5 100644
--- a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
+++ b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
@@ -80,12 +80,10 @@
 import com.demcha.examples.templates.cv.v2.CvSidebarPortraitExample;
 import com.demcha.examples.templates.cv.v2.CvTimelineMinimalExample;
 import com.demcha.examples.templates.invoice.InvoiceCinematicFileExample;
-import com.demcha.examples.templates.invoice.InvoiceFileExample;
 import com.demcha.examples.templates.invoice.v2.ModernInvoiceV2Example;
 import com.demcha.examples.templates.proposal.CinematicProposalFileExample;
 import com.demcha.examples.templates.proposal.ProposalCinematicFileExample;
 import com.demcha.examples.templates.proposal.v2.ModernProposalV2Example;
-import com.demcha.examples.templates.proposal.ProposalFileExample;
 import com.demcha.examples.templates.schedule.WeeklyScheduleFileExample;
 
 /**
@@ -138,12 +136,10 @@ public static void main(String[] args) throws Exception {
         System.out.println("Generated: " + CvTimelineMinimalLetterV2Example.generate());
 
         // Invoices
-        System.out.println("Generated: " + InvoiceFileExample.generate());
         System.out.println("Generated: " + InvoiceCinematicFileExample.generate());
         System.out.println("Generated: " + ModernInvoiceV2Example.generate());
 
         // Proposals
-        System.out.println("Generated: " + ProposalFileExample.generate());
         System.out.println("Generated: " + ProposalCinematicFileExample.generate());
         System.out.println("Generated: " + ModernProposalV2Example.generate());
         System.out.println("Generated: " + CinematicProposalFileExample.generate());
diff --git a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
index 0eb173e60..c7649b02c 100644
--- a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
+++ b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
@@ -78,11 +78,9 @@ record Entry(String title, String description, List tags, String codeUrl
         letter("cover-letter-mint-editorial-v2", "CvMintEditorialLetterV2Example", "Mint Editorial letter", "Letter paired with Mint Editorial CV — magazine-style mint accent.");
 
         // ===== Templates / Invoice =====
-        invoice("invoice", "Invoice (canonical)", "Single-page invoice with line items, totals, and structured chrome — InvoiceTemplateV1.", "invoice");
         invoice("invoice-cinematic", "Cinematic Invoice", "Polished V2 invoice template with theme-driven layout, advanced tables, and totals.", "invoice", "cinematic");
 
         // ===== Templates / Proposal =====
-        proposal("proposal", "Proposal (canonical)", "Multi-section proposal with cover, scope, deliverables, and pricing — ProposalTemplateV1.", "proposal");
         proposal("proposal-cinematic", "Cinematic Proposal", "Cinematic V2 proposal layout with cover panel, hero spread, and rich typography.", "proposal", "cinematic");
         proposal("project-proposal-cinematic", "Project Proposal (cinematic)", "End-to-end project proposal with mountain hero, scope panels, and pricing summary.", "proposal", "cinematic");
 
@@ -183,16 +181,13 @@ private static void letter(String id, String exampleClass, String title, String
     }
 
     private static void invoice(String id, String title, String desc, String... tags) {
-        String file = id.contains("cinematic") ? "InvoiceCinematicFileExample" : "InvoiceFileExample";
         ENTRIES.put(id, entry(title, desc, withCategory("invoice", tags),
-                EX_BASE + "/templates/invoice/" + file + ".java"));
+                EX_BASE + "/templates/invoice/InvoiceCinematicFileExample.java"));
     }
 
     private static void proposal(String id, String title, String desc, String... tags) {
-        String file;
-        if (id.equals("project-proposal-cinematic")) file = "CinematicProposalFileExample";
-        else if (id.contains("cinematic")) file = "ProposalCinematicFileExample";
-        else file = "ProposalFileExample";
+        String file = id.equals("project-proposal-cinematic")
+                ? "CinematicProposalFileExample" : "ProposalCinematicFileExample";
         ENTRIES.put(id, entry(title, desc, withCategory("proposal", tags),
                 EX_BASE + "/templates/proposal/" + file + ".java"));
     }
diff --git a/examples/src/main/java/com/demcha/examples/templates/invoice/InvoiceFileExample.java b/examples/src/main/java/com/demcha/examples/templates/invoice/InvoiceFileExample.java
deleted file mode 100644
index 6035e5e9e..000000000
--- a/examples/src/main/java/com/demcha/examples/templates/invoice/InvoiceFileExample.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.demcha.examples.templates.invoice;
-
-import com.demcha.compose.GraphCompose;
-import com.demcha.compose.document.api.DocumentPageSize;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.templates.builtins.InvoiceTemplateV1;
-import com.demcha.examples.support.ExampleDataFactory;
-import com.demcha.examples.support.ExampleOutputPaths;
-
-import java.nio.file.Path;
-
-public final class InvoiceFileExample {
-
-    private InvoiceFileExample() {
-    }
-
-    public static Path generate() throws Exception {
-        Path outputFile = ExampleOutputPaths.prepare("templates/invoice", "invoice.pdf");
-        InvoiceTemplateV1 template = new InvoiceTemplateV1();
-
-        try (DocumentSession document = GraphCompose.document(outputFile)
-                .pageSize(DocumentPageSize.A4)
-                .margin(22, 22, 22, 22)
-                .create()) {
-            template.compose(document, ExampleDataFactory.sampleInvoice());
-            document.buildPdf();
-        }
-
-        return outputFile;
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.out.println("Generated: " + generate());
-    }
-}
diff --git a/examples/src/main/java/com/demcha/examples/templates/proposal/ProposalFileExample.java b/examples/src/main/java/com/demcha/examples/templates/proposal/ProposalFileExample.java
deleted file mode 100644
index a4708830b..000000000
--- a/examples/src/main/java/com/demcha/examples/templates/proposal/ProposalFileExample.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.demcha.examples.templates.proposal;
-
-import com.demcha.compose.GraphCompose;
-import com.demcha.compose.document.api.DocumentPageSize;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.templates.builtins.ProposalTemplateV1;
-import com.demcha.examples.support.ExampleDataFactory;
-import com.demcha.examples.support.ExampleOutputPaths;
-
-import java.nio.file.Path;
-
-public final class ProposalFileExample {
-
-    private ProposalFileExample() {
-    }
-
-    public static Path generate() throws Exception {
-        Path outputFile = ExampleOutputPaths.prepare("templates/proposal", "proposal.pdf");
-        ProposalTemplateV1 template = new ProposalTemplateV1();
-
-        try (DocumentSession document = GraphCompose.document(outputFile)
-                .pageSize(DocumentPageSize.A4)
-                .margin(22, 22, 22, 22)
-                .create()) {
-            template.compose(document, ExampleDataFactory.sampleProposal());
-            document.buildPdf();
-        }
-
-        return outputFile;
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.out.println("Generated: " + generate());
-    }
-}
diff --git a/src/main/java/com/demcha/compose/document/templates/api/InvoiceTemplate.java b/src/main/java/com/demcha/compose/document/templates/api/InvoiceTemplate.java
index 3ec59a3fb..2ea737906 100644
--- a/src/main/java/com/demcha/compose/document/templates/api/InvoiceTemplate.java
+++ b/src/main/java/com/demcha/compose/document/templates/api/InvoiceTemplate.java
@@ -11,7 +11,7 @@
  * {@link DocumentSession}.

* *
{@code
- * InvoiceTemplate template = new InvoiceTemplateV1();
+ * InvoiceTemplate template = new InvoiceTemplateV2();
  * InvoiceDocumentSpec invoice = InvoiceDocumentSpec.builder()
  *         .invoiceNumber("GC-2026-041")
  *         .fromParty(party -> party.name("GraphCompose Studio"))
diff --git a/src/main/java/com/demcha/compose/document/templates/api/ProposalTemplate.java b/src/main/java/com/demcha/compose/document/templates/api/ProposalTemplate.java
index 44e45a514..92d153c5a 100644
--- a/src/main/java/com/demcha/compose/document/templates/api/ProposalTemplate.java
+++ b/src/main/java/com/demcha/compose/document/templates/api/ProposalTemplate.java
@@ -11,7 +11,7 @@
  * {@link DocumentSession}.

* *
{@code
- * ProposalTemplate template = new ProposalTemplateV1();
+ * ProposalTemplate template = new ProposalTemplateV2();
  * ProposalDocumentSpec proposal = ProposalDocumentSpec.builder()
  *         .projectTitle("GraphCompose rollout")
  *         .section("Scope", "Introduce reusable invoice and proposal templates.")
diff --git a/src/main/java/com/demcha/compose/document/templates/builtins/InvoiceTemplateV1.java b/src/main/java/com/demcha/compose/document/templates/builtins/InvoiceTemplateV1.java
deleted file mode 100644
index 2f399cfd9..000000000
--- a/src/main/java/com/demcha/compose/document/templates/builtins/InvoiceTemplateV1.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.demcha.compose.document.templates.builtins;
-
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.templates.api.InvoiceTemplate;
-import com.demcha.compose.document.templates.data.invoice.InvoiceDocumentSpec;
-import com.demcha.compose.document.templates.support.business.BusinessDocumentSceneStyles;
-import com.demcha.compose.document.templates.support.business.InvoiceTemplateComposer;
-import com.demcha.compose.document.templates.support.common.SessionTemplateComposeTarget;
-import com.demcha.compose.document.templates.support.common.TemplateLifecycleLog;
-
-/**
- * Canonical implementation of the invoice template.
- */
-public final class InvoiceTemplateV1 implements InvoiceTemplate {
-    private final InvoiceTemplateComposer composer = new InvoiceTemplateComposer(new BusinessDocumentSceneStyles());
-
-    /**
-     * Creates the canonical invoice template.
-     */
-    public InvoiceTemplateV1() {
-    }
-
-    @Override
-    public String getTemplateId() {
-        return "invoice-v1";
-    }
-
-    @Override
-    public String getTemplateName() {
-        return "Invoice V1";
-    }
-
-    @Override
-    public String getDescription() {
-        return "A light business invoice template with metadata, billing parties, line items, and totals.";
-    }
-
-    @Override
-    public void compose(DocumentSession document, InvoiceDocumentSpec spec) {
-        long startNanos = TemplateLifecycleLog.start(getTemplateId(), spec);
-        try {
-            composer.compose(new SessionTemplateComposeTarget(document), spec);
-            TemplateLifecycleLog.success(getTemplateId(), spec, startNanos);
-        } catch (RuntimeException | Error ex) {
-            TemplateLifecycleLog.failure(getTemplateId(), spec, startNanos, ex);
-            throw ex;
-        }
-    }
-}
diff --git a/src/main/java/com/demcha/compose/document/templates/builtins/ProposalTemplateV1.java b/src/main/java/com/demcha/compose/document/templates/builtins/ProposalTemplateV1.java
deleted file mode 100644
index 9190bbb45..000000000
--- a/src/main/java/com/demcha/compose/document/templates/builtins/ProposalTemplateV1.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.demcha.compose.document.templates.builtins;
-
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.templates.api.ProposalTemplate;
-import com.demcha.compose.document.templates.data.proposal.ProposalDocumentSpec;
-import com.demcha.compose.document.templates.support.business.BusinessDocumentSceneStyles;
-import com.demcha.compose.document.templates.support.business.ProposalTemplateComposer;
-import com.demcha.compose.document.templates.support.common.SessionTemplateComposeTarget;
-import com.demcha.compose.document.templates.support.common.TemplateLifecycleLog;
-
-/**
- * Canonical implementation of the proposal template.
- */
-public final class ProposalTemplateV1 implements ProposalTemplate {
-    private final ProposalTemplateComposer composer = new ProposalTemplateComposer(new BusinessDocumentSceneStyles());
-
-    /**
-     * Creates the canonical proposal template.
-     */
-    public ProposalTemplateV1() {
-    }
-
-    @Override
-    public String getTemplateId() {
-        return "proposal-v1";
-    }
-
-    @Override
-    public String getTemplateName() {
-        return "Proposal V1";
-    }
-
-    @Override
-    public String getDescription() {
-        return "A light business proposal template with executive summary, scope, timeline, pricing, and acceptance terms.";
-    }
-
-    @Override
-    public void compose(DocumentSession document, ProposalDocumentSpec spec) {
-        long startNanos = TemplateLifecycleLog.start(getTemplateId(), spec);
-        try {
-            composer.compose(new SessionTemplateComposeTarget(document), spec);
-            TemplateLifecycleLog.success(getTemplateId(), spec, startNanos);
-        } catch (RuntimeException | Error ex) {
-            TemplateLifecycleLog.failure(getTemplateId(), spec, startNanos, ex);
-            throw ex;
-        }
-    }
-}
diff --git a/src/test/java/com/demcha/documentation/DocumentationExamplesTest.java b/src/test/java/com/demcha/documentation/DocumentationExamplesTest.java
index cd130f84d..14e8c749f 100644
--- a/src/test/java/com/demcha/documentation/DocumentationExamplesTest.java
+++ b/src/test/java/com/demcha/documentation/DocumentationExamplesTest.java
@@ -4,9 +4,9 @@
 import com.demcha.compose.document.api.DocumentPageSize;
 import com.demcha.compose.document.api.DocumentSession;
 import com.demcha.compose.document.image.DocumentImageFitMode;
-import com.demcha.compose.document.templates.api.InvoiceTemplate;
-import com.demcha.compose.document.templates.builtins.InvoiceTemplateV1;
+import com.demcha.compose.document.templates.api.DocumentTemplate;
 import com.demcha.compose.document.templates.data.invoice.InvoiceDocumentSpec;
+import com.demcha.compose.document.templates.invoice.v2.presets.ModernInvoice;
 import com.demcha.compose.document.style.DocumentColor;
 import com.demcha.compose.document.style.DocumentInsets;
 import com.demcha.compose.document.style.DocumentStroke;
@@ -163,7 +163,7 @@ void shouldRenderModuleFirstDslExampleToFile() throws Exception {
     @Test
     void shouldRenderComposeFirstBuiltInTemplateExampleToFile() throws Exception {
         Path outputFile = VisualTestOutputs.preparePdf("compose-first-invoice-template", "clean", "documentation");
-        InvoiceTemplate template = new InvoiceTemplateV1();
+        DocumentTemplate template = ModernInvoice.create();
 
         try (DocumentSession document = GraphCompose.document(outputFile)
                 .pageSize(DocumentPageSize.A4)
diff --git a/src/test/java/com/demcha/mock/ProposalDataFixtures.java b/src/test/java/com/demcha/mock/ProposalDataFixtures.java
index 0e8d06b3d..458dd3331 100644
--- a/src/test/java/com/demcha/mock/ProposalDataFixtures.java
+++ b/src/test/java/com/demcha/mock/ProposalDataFixtures.java
@@ -47,14 +47,14 @@ public static ProposalData longProposal() {
                                 repeatSentence("Weekly checkpoints will focus on visual deltas, example ergonomics, and whether the generated outputs are understandable for both library consumers and internal maintainers.", 4),
                                 repeatSentence("Each milestone includes a review of template polish, code readability, and whether the generated examples are strong enough to support README and demo usage.", 4)))),
                 List.of(
-                        new ProposalTimelineItem("Week 1", "5 days", "API alignment, DTO modeling, invoice template implementation, and review-ready render tests."),
-                        new ProposalTimelineItem("Week 2", "5 days", "Proposal template implementation, long-content pagination verification, and examples module setup."),
-                        new ProposalTimelineItem("Week 3", "3 days", "README refresh, final PDF review, and delivery handoff package.")),
+                        new ProposalTimelineItem("Week 1", "5 days", "API alignment, DTO modeling, render tests."),
+                        new ProposalTimelineItem("Week 2", "5 days", "Proposal template + pagination checks."),
+                        new ProposalTimelineItem("Week 3", "3 days", "README refresh, final review, handoff.")),
                 List.of(
-                        new ProposalPricingRow("Foundation", "Public template APIs, DTOs, and cleanup of devtool production scope.", "GBP 3,200", false),
-                        new ProposalPricingRow("Template delivery", "Invoice and proposal layouts with render tests and polished defaults.", "GBP 4,450", false),
-                        new ProposalPricingRow("Examples package", "Runnable examples module, sample data, and usage documentation.", "GBP 1,850", false),
-                        new ProposalPricingRow("Total investment", "Fixed-price delivery for the agreed scope.", "GBP 9,500", true)),
+                        new ProposalPricingRow("Foundation", "Public template APIs and cleanup.", "GBP 3,200", false),
+                        new ProposalPricingRow("Template delivery", "Invoice and proposal layouts + tests.", "GBP 4,450", false),
+                        new ProposalPricingRow("Examples package", "Runnable examples module + docs.", "GBP 1,850", false),
+                        new ProposalPricingRow("Total investment", "Fixed-price delivery, agreed scope.", "GBP 9,500", true)),
                 List.of(
                         "Proposal pricing is valid until the stated expiration date.",
                         "Any additional template families beyond the agreed four examples are scoped separately.",