How the Document Engine Works
A complete technical walkthrough of document generation, rendering, email delivery, agreement clauses, and invoice creation -- from Salesforce to PDF to inbox.
What Is the Document Engine?
The 30-second explanation
The Document Engine is a system for generating professional documents from Salesforce data. It supports three template types today: Invoices, Client Agreements, and Contractor Agreements. More templates can be added.
Invoice
Hours, line items, rates, totals, A/R
Client Agreement
8 clauses, terms, signature blocks
Contractor Agreement
8 clauses, scope, compensation, IP
Key concept: Frozen Snapshots
Each document is a frozen snapshot of data at generation time. Even if the underlying entity, work items, or rates change later, the document always reflects the state at the moment it was created. This is critical for legal and financial documents -- an invoice must never retroactively change.
Design philosophy: Try before generalizing
The current JSON metadata approach is deliberately simple. There is no separate Fields object or abstract template schema yet -- and that is intentional. The current approach of freezing all document data into a JSON snapshot works well for the three template types that exist today. The plan is to try this approach first with real production usage and generalize later only if the pattern proves it needs abstraction. Premature generalization would add complexity without proven benefit.
Key concept: Public Tokens
Every document gets a 64-character hex public token (e.g., a7f3e91b2c4d...). This token enables unauthenticated access to the document via a Salesforce Site. Anyone with the token can view the document -- no login required. Tokens are cryptographically random and practically unguessable.
Versioning, Approval Flow & PDF Hyperlinks
Production-grade document lifecycle
Documents in the real world go through revisions, need stakeholder sign-off, and must link back to source records. The Document Engine handles all three with versioning, an approval workflow, and clickable PDF hyperlinks.
Document Versioning
Regenerate an invoice or agreement and the engine creates a new version linked to the original document. Each version retains its own frozen JSON snapshot, so you can compare any two versions side by side. The latest version is always the active one, but prior versions remain accessible for reference and compliance.
Concrete example: Correcting an invoice
API: GET /v1/api/documents/:id/versions returns the full version chain with timestamps, snapshot diffs, and the user who triggered each regeneration.
Invoice Approval & Dispute Flow
Invoices go through a structured approval workflow before payment. Clients reviewing an invoice in the portal can approve it for payment or flag a dispute with specific comments attached to individual line items.
Invoice Status Flow
Concrete example: Disputing a line item
API: POST /v1/api/documents/:id/approve for approval, POST /v1/api/documents/:id/dispute with a JSON body containing the dispute reason and optional line item references.
PDF Hyperlink Improvements
Every line item in a PDF invoice is now a fully clickable hyperlink that opens the corresponding Salesforce record in a new tab. This means the person reviewing the PDF can jump directly to the work item or work log behind any charge.
How it works
The VF PDF controller detects at runtime whether it is running inside a managed package (namespacedelivery__) or unmanaged context. It builds the correct Salesforce URL for each line item accordingly.
Managed package: Links resolve to /lightning/r/delivery__WorkItem__c/RECORD_ID/view
Unmanaged: Links resolve to /lightning/r/WorkItem__c/RECORD_ID/view
Previously, hyperlinks only worked in unmanaged orgs because the namespace prefix was not injected. This fix ensures every Delivery Hub installation produces PDFs with working links regardless of packaging context.
How Documents Are Created
Step-by-step: from trigger to record
User triggers document generation
Click a button in the Salesforce LWC interface (e.g., “Generate Invoice”), or call the API programmatically. The trigger passes the entity ID, template type, and period.
DeliveryDocumentController.generateDocument() runs
The Apex controller method does the heavy lifting:
- -Builds a snapshot -- queries all relevant data: entity info (name, address, email), vendor info, work items in the period, work logs (hours), hourly rates, prior unpaid invoices
- -Freezes the snapshot as JSON in the
SnapshotTxt__cfield (LongTextArea). This is the immutable data source for all rendering. - -Creates the DeliveryDocument__c record with template type, period, status=Draft, and the snapshot JSON
- -Generates a 64-char hex public token for unauthenticated access via the Salesforce Site
Document record exists in Salesforce
The document is now a DeliveryDocument__c record with all its data frozen. It can be rendered, emailed, updated to Final status, or linked to DeliveryTransaction__c payment records.
{
// Entity (who the document is for)
"entityName": "Mobilization Funding",
"entityAddress": "123 Main St, Suite 400, Miami, FL",
"entityEmail": "jose@mobilizationfunding.com",
// Vendor (who created the document)
"vendorName": "Cloud Nimbus LLC",
"vendorAddress": "...",
"vendorEmail": "glen@cloudnimbusllc.com",
// Document metadata
"templateType": "Invoice",
"periodLabel": "March 2026",
"documentDate": "2026-03-31",
"dueDate": "2026-04-30",
// Line items (work logs)
"lineItems": [
{
"date": "2026-03-04",
"description": "Risk Rating implementation",
"hours": 3.5,
"rate": 90.00,
"amount": 315.00,
"workItemNumber": "WI-040"
},
// ... more items
],
// Totals
"totalHours": 30.0,
"hourlyRate": 90.00,
"subtotal": 2700.00,
"priorBalance": 0.00,
"amountDue": 2700.00,
// Unpaid invoices summary
"unpaidInvoices": [],
// Agreement clauses (for agreements only)
"clauses": [...]
}How Documents Are Rendered
Three rendering layers, explained
The Document Engine has three rendering layers. Each serves a different purpose, and they all read from the same frozen JSON snapshot. This means the data is always consistent across all views.
Layer 1: VF PDF
Server-side PDF generation
- - Visualforce + renderAs="pdf"
- - CSS 2.1 only (Flying Saucer)
- - Table-based layouts
- - Email attachment backbone
- - Scheduled job compatible
Layer 2: React Web View
Rich interactive web experience
- - React app in Static Resource
- - Loaded via VF shell on SF Site
- - Fetches data via public API + token
- - Modern CSS, full styling
- - Interactive (expand sections, etc.)
Layer 3: Client-Side PDF
Download PDF from web view
- - html2pdf.js library
- - Captures rendered HTML to PDF
- - Full modern CSS quality
- - User-triggered download
- - No server roundtrip
Server-Side PDF (Visualforce)
The VF page DeliveryDocumentPdf.page with renderAs="pdf" generates a server-side PDF. The controller DeliveryDocumentPdfController parses the JSON snapshot into typed Apex properties that the VF markup can reference.
Why CSS 2.1 only?
Salesforce uses Flying Saucer (an open-source Java library from 2008) to render VF pages to PDF. Flying Saucer only supports CSS 2.1 -- no flexbox, no grid, no modern CSS. This means all PDF layouts must use <table>-based layouts with inline styles. It's ugly to code but it works reliably.
This is the automation backbone. When you schedule monthly invoice runs, send document emails, or generate PDFs programmatically, this is the layer that runs. It does not require a browser.
INVOICE
Cloud Nimbus LLC
glen@cloudnimbusllc.com
Invoice #: INV-025
Date: March 31, 2026
Due: April 30, 2026
Terms: Net 30
Bill To
Mobilization Funding
123 Main St, Suite 400
Miami, FL 33130
| Date | Description | Hours | Rate | Amount |
|---|---|---|---|---|
| 03/04 | Risk Rating implementation | 3.5 | $90 | $315.00 |
| 03/07 | User Profile lockdown | 4.0 | $90 | $360.00 |
| 03/11 | Sync engine debugging | 6.0 | $90 | $540.00 |
| 03/14 | Portal convergence work | 8.0 | $90 | $720.00 |
| 03/18 | Document Engine build | 8.5 | $90 | $765.00 |
Generated by Cloud Nimbus Document Engine -- cloudnimbusllc.com
Rich Web View (React in Static Resource)
A React application bundled as a Salesforce Static Resource. It's loaded via a VF page shell hosted on a Salesforce Site (public, no login required). The React app fetches document data via the public API using the 64-char token.
This is the “real” experience for viewing documents. Modern CSS, beautiful formatting, responsive layout, interactive features (expand/collapse sections, print, etc.). The link in document emails points to this web view.
How the React app loads
VF page shell on SF Site loads the Static Resource JS bundle. The bundle parses the token from the URL, calls the @HttpGet API endpoint with the token, receives the snapshot JSON, and renders the document using React components with modern CSS.
Client-Side PDF (html2pdf.js)
The “Download PDF” button in the web view captures the rendered HTML and converts it to PDF entirely in the browser using html2pdf.js.
This produces a much higher quality PDF than Layer 1 because it renders with full modern CSS support. No server roundtrip required -- the PDF is generated client-side and downloaded directly.
How Email Delivery Works
From button click to inbox
User clicks “Send Email” in Salesforce
LWC button on the DeliveryDocument__c record page
DeliveryDocumentController.sendDocumentEmail() runs
Apex method that orchestrates the entire email
Generates VF PDF as a blob
Creates a PageReference to the VF page with renderAs=pdf, then calls getContentAsPDF() to get the binary blob. This is the Layer 1 rendering happening server-side.
Creates SingleEmailMessage
Salesforce email with:
- - To: recipient email (from entity record)
- - CC: glen@cloudnimbusllc.com (ALWAYS -- hard requirement from DeliverySettings)
- - Attachment: the VF PDF blob
- - Body: includes a link to the Layer 2 web view via public token
Email sent via Salesforce email service
Uses Salesforce's built-in email sending. No third-party email service needed.
Dear Jose,
Please find attached your invoice for March 2026.
You can also view this document online: View Invoice
Best regards,
Cloud Nimbus LLC
How Agreement Clauses Work
8 standard clauses with dynamic merge fields
Client Agreement and Contractor Agreement templates auto-inject 8 default clauses. These clauses are the standard legal sections for a consulting/contractor relationship. Each clause uses dynamic merge fields to inject client-specific data.
The 8 Default Clauses
Dynamic Merge Fields
Clause text contains placeholder tokens that get replaced with real data at generation time:
[Client Name]-->Mobilization Funding[rate]-->$90/hour[Vendor Name]-->Cloud Nimbus LLCCustom Clauses
Custom clauses can be passed via metadata override when generating the document. This allows client-specific terms without modifying the default clause set. Custom clauses appear after the 8 standard clauses.
Client Agreement -- Standard Clauses
1. Scope of Services
Cloud Nimbus LLC agrees to provide Salesforce development services to [Client Name] as described in...
2. Compensation
Client shall pay Vendor at a rate of $[rate]/hour. Invoices are due Net 30 from date of issue...
3. Term & Termination
This Agreement shall commence on the Effective Date and continue until terminated by either party...
4. Confidentiality
Each party agrees to hold in confidence all Confidential Information received from the other party...
5. Intellectual Property Rights
All work product created by Vendor shall be owned by Client upon full payment...
6. Limitation of Liability
In no event shall either party be liable for any indirect, incidental, or consequential damages...
7. Independent Contractor Status
Vendor is an independent contractor and not an employee, agent, or partner of Client...
8. Governing Law
This Agreement shall be governed by the laws of the State of [State]...
Client Signature
Date: ___________
Vendor Signature
Date: ___________
How Invoices Work
Hours x Rate = Money
The Invoice template is the most data-intensive document. It pulls together entity info, work items, work logs (hours), and hourly rates to produce a complete billing statement.
What the Invoice Pulls
Entity Info
- - Client name and address
- - Vendor name and address
- - Contact emails
Work Data
- - Work items active in the period
- - Work logs (each with date, hours, description)
- - Hourly rate from entity config
What the Invoice Calculates
Invoice Details
INVOICE
Cloud Nimbus LLC
glen@cloudnimbusllc.com
Invoice #: INV-025
Date: March 31, 2026
Due: April 30, 2026
Terms: Net 30
Bill To
Mobilization Funding
123 Main St, Suite 400
Miami, FL 33130
| Date | Description | Hours | Rate | Amount |
|---|---|---|---|---|
| 03/04 | Risk Rating implementation | 3.5 | $90 | $315.00 |
| 03/07 | User Profile lockdown | 4.0 | $90 | $360.00 |
| 03/11 | Sync engine debugging | 6.0 | $90 | $540.00 |
| 03/14 | Portal convergence work | 8.0 | $90 | $720.00 |
| 03/18 | Document Engine build | 8.5 | $90 | $765.00 |
Generated by Cloud Nimbus Document Engine -- cloudnimbusllc.com
How This Connects to the Marketplace
Document Engine is the financial backbone
The Document Engine is not a standalone feature -- it's the financial and legal infrastructure that makes the marketplace work. Here is how each document type maps to marketplace events:
Developer claims a bounty
Auto-generate Contractor Agreement with the developer's name, scope from the bounty, compensation terms (bounty amount minus rake), and all 8 standard clauses.
Work is accepted
Auto-generate Invoice with line items (work logs from the bounty period), total amount, rake deducted, and net payable to the developer.
Org posts a bounty
Can auto-generate Client Agreement with the organization to establish the terms of their relationship with the platform.
All document emails
Every email is CC'd to glen@cloudnimbusllc.com. This is a hard requirement -- Glen sees every invoice, every agreement, every financial communication.
Payment tracking: DeliveryTransaction__c records link to DeliveryDocument__c records to track payment status. This creates a full audit trail: document generated → email sent → payment received → transaction recorded.
Quick Reference
| Component | Type | Purpose |
|---|---|---|
| DeliveryDocumentController | Apex Controller | Generate documents, send emails, manage lifecycle |
| DeliveryDocumentPdfController | Apex Controller | Parse snapshot JSON for VF PDF rendering |
| DeliveryDocumentPdf.page | Visualforce Page | VF markup for PDF rendering (CSS 2.1 / table layouts) |
| DeliveryDocument__c | Custom Object | Stores document record + frozen JSON snapshot + public token |
| DeliveryTransaction__c | Custom Object | Payment tracking linked to documents |
| SnapshotTxt__c | LongTextArea Field | Frozen JSON blob with all document data |
| PublicTokenTxt__c | Text(64) Field | 64-char hex token for unauthenticated web access |
Feedback on the Document Engine
What's confusing? What needs more detail? What questions do you still have?