Document Templates Guide
Last Updated: 2026-01-13 Status: Implemented (Enhanced) Plan References:
- 045-document-generation-templates.md
- 062-document-templates-enhancement.md
- 089-document-templates-improvement.md
Plan 089 Enhancements (2026-01-13):
- Template Marketplace for sharing and installing templates
- Template categories with
TemplateCategorymodel - Import/export templates as JSON
- WYSIWYG template editor component
TemplateExportServicefor bundling and importing
Overview
The Document Templates system allows administrators to create reusable document templates with variable placeholders. These templates can generate professional documents such as proposals, contracts, statements of work, and reports by merging with client, project, or invoice data.
Table of Contents
- Accessing Templates
- Features
- How to Use
- Template Marketplace
- Import/Export Templates
- Template Variables
- Template Components
- WYSIWYG Editor
- Template Validation
- Technical Architecture
- Related Features
Accessing Templates
Navigation
| Access Point | Location | URL | Role |
|---|---|---|---|
| Template Library | Admin sidebar | /admin/documents/templates | Admin |
| Create Template | Templates page | /admin/documents/templates/create | Admin |
| Edit Template | Template row | /admin/documents/templates/{id}/edit | Admin |
| Generate Document | Template/Project page | Modal action | Admin |
| Generated Documents | Documents section | /admin/documents | Admin |
Permissions
| Action | Admin | Client User |
|---|---|---|
| View templates | ✅ | ❌ |
| Create templates | ✅ | ❌ |
| Edit templates | ✅ | ❌ |
| Delete templates | ✅ | ❌ |
| Generate documents | ✅ | ❌ |
| View generated docs | ✅ | ✅ (shared) |
| Download documents | ✅ | ✅ (shared) |
Features
Template Management
- Create and edit templates
- Rich text editor (WYSIWYG)
- Template categories
- Template versioning
- Clone templates
Variable System
- Client variables
- Project variables
- Invoice variables
- User variables
- Custom variables
- Date/time variables
Document Generation
- Merge template with data
- PDF output
- Word document output
- HTML preview
- Batch generation
Document Library
- Store generated documents
- Version tracking
- Share with clients
- Digital signatures (optional)
How to Use
Creating a Template
- Navigate to Admin → Documents → Templates
- Click "Create Template"
- Fill in template details:
- Name: Template name (e.g., "Service Agreement")
- Category: Select or create category
- Description: Internal description
- Write template content in editor
- Insert variables using toolbar or
{{variable}}syntax - Click "Save Template"
Using Variables in Templates
Insert variables using double curly braces:
Dear {{client.contact_name}},
Thank you for choosing {{company.name}}. We are pleased to present
this proposal for {{project.name}}.
Project Start Date: {{project.start_date}}
Estimated Budget: {{project.budget | currency}}
Best regards,
{{user.name}}
{{company.name}}
Generating a Document
From Template:
- Navigate to Admin → Documents → Templates
- Click "Generate" on desired template
- Select data source:
- Client
- Project
- Invoice
- Preview generated document
- Click "Generate PDF" or "Generate Word"
- Document saved to library
From Project:
- Navigate to Admin → Projects → [Project]
- Click "Generate Document"
- Select template
- Review merged preview
- Generate and save
Editing a Template
- Navigate to Admin → Documents → Templates → [Template]
- Click "Edit"
- Modify content or variables
- Click "Save"
- Previous version saved automatically
Sharing Documents with Clients
- Navigate to Admin → Documents
- Find generated document
- Click "Share with Client"
- Document appears in client portal
- Client can view and download
Template Marketplace
The Template Marketplace allows admins to share templates publicly and install templates created by others.
Accessing Marketplace
| Access Point | Location | URL |
|---|---|---|
| Marketplace | Templates page | /admin/templates/marketplace |
| Share Template | Template actions | Share button |
| My Templates | Templates index | /admin/documents/templates |
Browsing Templates
- Navigate to Admin → Templates → Marketplace
- Filter by category (left sidebar)
- Search by name or description
- Sort by: Popular, Newest, or Name
- Click "Preview" to view details
- Click "Install" to add to your library
Sharing Templates
Share your templates with other admins:
- Navigate to Admin → Documents → Templates
- Select a template
- Click "Share to Marketplace"
- Template becomes public
- Track installs from marketplace
Unsharing Templates
- View your shared template
- Click "Remove from Marketplace"
- Template becomes private again
Template Categories
Categories organize marketplace templates:
| Category | Description |
|---|---|
| Proposals | Client proposals |
| Contracts | Service agreements |
| SOW | Statements of work |
| Reports | Project reports |
| Letters | Correspondence |
Import/Export Templates
Exporting Templates
Export a single template:
- View template in marketplace
- Click "Export JSON"
- Template downloads as
.jsonfile
Export format includes:
- Template name and description
- Content HTML
- Variables configuration
- Layout options
- Font configuration
- Category (by slug)
Importing Templates
Import a template file:
- Navigate to Admin → Templates → Marketplace
- Use "Import Template" form (left sidebar)
- Select
.jsonfile - Click "Import"
- Template added to your library
Export Bundle
Export multiple templates at once via API:
$service = app(TemplateExportService::class);
$json = $service->exportBundle([$id1, $id2, $id3]);
Import Bundle
$templates = $service->importBundle($jsonContent);
// Returns array of imported DocumentTemplate models
Export Format
{
"meta": {
"version": "1.0",
"exported_at": "2026-01-13T12:00:00Z",
"source": "Client Portal"
},
"template": {
"name": "Template Name",
"category": "proposal",
"category_slug": "proposals",
"description": "Template description",
"content": "<h1>Template Content</h1>",
"variables": {},
"layout_options": {},
"font_config": {}
}
}
WYSIWYG Editor
The visual template editor (<x-template-editor>) provides a rich editing experience.
Using the Component
<x-template-editor
:template="$template"
:variables="$availableVariables"
name="content"
/>
Editor Features
| Feature | Description |
|---|---|
| Text Formatting | Bold, italic, underline |
| Headings | H1, H2, H3, paragraph |
| Lists | Bullet and numbered lists |
| Alignment | Left, center, right |
| Insert Variable | Dropdown with all variables |
| Insert Table | 3x2 default table |
| Insert Link | URL with selected text |
| Insert Image | Image by URL |
| Undo/Redo | Edit history |
| View Toggle | Visual / HTML source |
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Ctrl+B | Bold |
| Ctrl+I | Italic |
| Ctrl+U | Underline |
| Ctrl+Z | Undo |
| Ctrl+Y | Redo |
Variable Insertion
Variables are grouped by category:
- Company: name, address, phone, email
- Client: company_name, contact_name, email
- Project: name, description, dates, budget
- Invoice: number, items, totals
- Date: today, year, month
Insert via dropdown or type {{variable.name}} directly.
Template Variables
Client Variables
| Variable | Description | Example |
|---|---|---|
{{client.company_name}} | Company name | Acme Corp |
{{client.contact_name}} | Contact name | John Smith |
{{client.email}} | Email address | john@acme.com |
{{client.phone}} | Phone number | 555-1234 |
{{client.address}} | Street address | 123 Main St |
{{client.city}} | City | New York |
{{client.state}} | State | NY |
{{client.zip}} | ZIP code | 10001 |
{{client.full_address}} | Complete address | Full formatted |
Project Variables
| Variable | Description | Example |
|---|---|---|
{{project.name}} | Project name | Website Redesign |
{{project.description}} | Description | Full description |
{{project.status}} | Current status | Active |
{{project.start_date}} | Start date | Jan 15, 2026 |
{{project.due_date}} | Due date | Mar 15, 2026 |
{{project.budget}} | Budget amount | 15000.00 |
| `{{project.budget | currency}}` | Formatted |
Invoice Variables
| Variable | Description | Example |
|---|---|---|
{{invoice.number}} | Invoice number | INV-2026-001 |
{{invoice.status}} | Status | Sent |
{{invoice.issue_date}} | Issue date | Jan 20, 2026 |
{{invoice.due_date}} | Due date | Feb 20, 2026 |
{{invoice.subtotal}} | Subtotal | $5,000.00 |
{{invoice.tax}} | Tax amount | $400.00 |
{{invoice.total}} | Total | $5,400.00 |
{{invoice.items}} | Line items table | Table HTML |
Company Variables
| Variable | Description |
|---|---|
{{company.name}} | Company name |
{{company.address}} | Company address |
{{company.phone}} | Company phone |
{{company.email}} | Company email |
{{company.website}} | Company website |
{{company.logo}} | Logo image tag |
User Variables
| Variable | Description |
|---|---|
{{user.name}} | Current user name |
{{user.email}} | Current user email |
{{user.title}} | User title/role |
Date Variables
| Variable | Description | Example |
|---|---|---|
{{date.today}} | Current date | Jan 25, 2026 |
{{date.now}} | Current datetime | Jan 25, 2026 2:30 PM |
{{date.year}} | Current year | 2026 |
{{date.month}} | Current month | January |
Variable Formatters
| Formatter | Usage | Result |
|---|---|---|
currency | `{{value | currency}}` |
date | `{{value | date}}` |
uppercase | `{{value | uppercase}}` |
lowercase | `{{value | lowercase}}` |
default | `{{value | default:'N/A'}}` |
Template Components
Template components are reusable building blocks that can be inserted into templates. They help maintain consistency across documents and reduce duplication.
Accessing Components
- Navigation: More > Template Components
- URL:
/admin/templates/components - Permissions: Admin only
Component Categories
| Category | Description |
|---|---|
| Header | Document headers, letterheads |
| Footer | Document footers, signature blocks |
| Table | Data tables, invoice items |
| Section | Content sections, dividers |
| Signature | Signature blocks |
| Divider | Visual separators |
Creating a Component
- Navigate to More > Template Components
- Click "Create Component"
- Fill in details:
- Name: Component name
- Category: Select category
- Description: Usage description
- Content: HTML with variables
- Click "Create Component"
Using Components in Templates
Insert components using the component library in the template editor:
- Open template editor
- Click "Insert Component"
- Select component from library
- Component HTML is inserted at cursor
Example Components
Company Letterhead:
<div class="letterhead">
<img src="{{company.logo_url}}" class="logo" />
<div class="company-info">
<h1>{{company.name}}</h1>
<p>{{company.address}}</p>
<p>{{company.phone}} | {{company.email}}</p>
</div>
</div>
Signature Block:
<div class="signature-block">
<div class="signature-line"></div>
<p>{{user.name}}</p>
<p>{{user.title}}</p>
<p>{{date.today}}</p>
</div>
Template Validation
Templates can be validated to check for errors before use.
Validation Checks
| Check | Description |
|---|---|
| Unknown variables | Variables not in registry |
| HTML validity | Valid HTML structure |
| Unclosed loops | Missing {{/each}} tags |
| Unclosed conditionals | Missing {{/if}} tags |
| Render errors | Template can be rendered |
Using Validation
- Open template editor
- Click "Validate" button
- View validation results:
- Errors (must fix)
- Warnings (review recommended)
Variable Registry
The system maintains a registry of all available variables with:
- Variable key and syntax
- Description
- Example value
- Formatter support
Access variables in editor via the Variable sidebar or search.
Technical Architecture
Models
DocumentTemplate Model: app/Models/DocumentTemplate.php
class DocumentTemplate extends Model
{
protected $fillable = [
'name',
'category_id',
'description',
'content',
'format',
'is_active',
'version',
];
protected $casts = [
'is_active' => 'boolean',
'version' => 'integer',
];
}
GeneratedDocument Model: app/Models/GeneratedDocument.php
class GeneratedDocument extends Model
{
protected $fillable = [
'template_id',
'documentable_type',
'documentable_id',
'filename',
'path',
'format',
'is_client_visible',
'generated_by',
];
}
Services
| Service | Location | Purpose |
|---|---|---|
VariableRegistry | app/Services/Templates/VariableRegistry.php | Manages available variables |
TemplateRenderer | app/Services/Templates/TemplateRenderer.php | Renders templates with data |
TemplatePreviewService | app/Services/Templates/TemplatePreviewService.php | Generates previews |
TemplateValidator | app/Services/Templates/TemplateValidator.php | Validates templates |
TemplateExportService | app/Services/Templates/TemplateExportService.php | Import/export templates |
TemplateExportService: Template import/export and bundling
$service = app(TemplateExportService::class);
// Export single template
$data = $service->export($template);
$json = $service->toJson($template);
// Import template
$template = $service->fromJson($jsonContent);
// Export/import bundles
$bundleJson = $service->exportBundle([$id1, $id2]);
$templates = $service->importBundle($bundleJson);
// Download response
return $service->downloadResponse($template);
VariableRegistry: Centralized variable management
$registry->register('company', [
'company.name' => [
'description' => 'Company name',
'example' => 'Acme Corp',
],
// ...
]);
// Get all variables
$variables = $registry->getAll();
// Search variables
$results = $registry->search('client');
TemplateRenderer: Variable replacement and template rendering
$renderer = app(TemplateRenderer::class);
$html = $renderer->render($template->content, $data);
TemplateValidator: Template validation
$validator = app(TemplateValidator::class);
$result = $validator->validate($content);
if (!$result->valid) {
foreach ($result->errors as $error) {
// Handle errors
}
}
Controller
Location: app/Http/Controllers/Admin/DocumentTemplateController.php
| Method | Route | Description |
|---|---|---|
index() | GET /admin/documents/templates | List templates |
create() | GET /admin/documents/templates/create | Create form |
store() | POST /admin/documents/templates | Save template |
show() | GET /admin/documents/templates/{template} | View template |
edit() | GET /admin/documents/templates/{template}/edit | Edit form |
update() | PUT /admin/documents/templates/{template} | Update template |
destroy() | DELETE /admin/documents/templates/{template} | Delete template |
preview() | GET /admin/documents/templates/{template}/preview | Preview merge |
duplicate() | POST /admin/documents/templates/{template}/duplicate | Clone template |
Routes
// Document Templates
Route::resource('documents/templates', DocumentTemplateController::class)->names('documents.templates');
Route::get('documents/templates/{template}/preview', [DocumentTemplateController::class, 'preview']);
Route::post('documents/templates/{template}/duplicate', [DocumentTemplateController::class, 'duplicate']);
Route::patch('documents/templates/{template}/toggle-active', [DocumentTemplateController::class, 'toggleActive']);
// Generated Documents
Route::resource('documents', GeneratedDocumentController::class);
Route::get('documents/{document}/pdf', [GeneratedDocumentController::class, 'streamPdf']);
Route::get('documents/{document}/pdf/download', [GeneratedDocumentController::class, 'downloadPdf']);
Route::post('documents/{document}/regenerate', [GeneratedDocumentController::class, 'regenerate']);
Database Tables
Table: document_templates
| Column | Type | Description |
|---|---|---|
id | bigint | Primary key |
name | string | Template name |
category_id | bigint | Category FK |
description | text | Description |
content | longtext | Template HTML |
format | string | Default format |
is_active | boolean | Active status |
version | integer | Version number |
created_at | timestamp | Created date |
updated_at | timestamp | Updated date |
Table: generated_documents
| Column | Type | Description |
|---|---|---|
id | bigint | Primary key |
template_id | bigint | Source template |
documentable_type | string | Polymorphic type |
documentable_id | bigint | Polymorphic ID |
filename | string | File name |
path | string | Storage path |
format | string | PDF/DOCX/HTML |
is_client_visible | boolean | Shared with client |
generated_by | bigint | User who generated |
created_at | timestamp | Generated date |
Template Examples
Service Proposal
<h1>Service Proposal</h1>
<p>Date: {{date.today}}</p>
<h2>Prepared For:</h2>
<p>
{{client.company_name}}<br>
{{client.contact_name}}<br>
{{client.full_address}}
</p>
<h2>Project Overview</h2>
<p>{{project.description}}</p>
<h2>Timeline</h2>
<p>Start Date: {{project.start_date | date}}</p>
<p>Completion: {{project.due_date | date}}</p>
<h2>Investment</h2>
<p>Total: {{project.budget | currency}}</p>
Invoice Template
<table>
{{invoice.items}}
</table>
<p>Total Due: {{invoice.total | currency}}</p>
Related Features
Dependencies
| Feature | Relationship |
|---|---|
| PDF Generation | PDF output |
| Client Management | Client data |
| Project Management | Project data |
| Invoicing | Invoice data |
Complementary Features
| Feature | Description |
|---|---|
| File Sharing | Document storage |
| Notifications | Send documents |
| Activity Logging | Track generation |
Best Practices
For Template Creation
- Use descriptive names for templates
- Test with sample data before production use
- Include default values for optional variables
- Keep formatting consistent
- Version templates before major changes
For Developers
- Cache template parsing for performance
- Validate variables before rendering
- Escape user content to prevent XSS
- Handle missing data gracefully
Troubleshooting
| Issue | Solution |
|---|---|
| Variable not replaced | Check variable syntax and data source |
| PDF rendering issues | Verify HTML is valid |
| Missing data | Ensure model relationships loaded |
| Slow generation | Enable caching, optimize queries |
See Also
- PDF Generation - PDF output
- Invoicing - Invoice documents
- File Sharing - Document storage