> For the complete documentation index, see [llms.txt](https://triton.pharos.ai/pharos-triton/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://triton.pharos.ai/pharos-triton/triton-best-practices/templates-and-builder-pattern.md).

# Templates & the Builder Pattern

## Why Templates Matter

* **Always prefer** `TritonBuilder` + **template cloning** over convenience helpers.
* **Why:** Templates standardize category, type, area, base details, and reduce copy/paste drift.

## Apex – Set & Reuse a Template

```apex
// Early in the transaction (e.g., controller entry, batch start)
Triton.instance.setTemplate(
    Triton.makeBuilder()
        .category(TritonTypes.Category.Apex)
        .level(TritonTypes.Level.DEBUG)
        .type(TritonTypes.Type.Backend)
        .area(TritonTypes.Area.OpportunityManagement) // agreed taxonomy
);

// Later: clone and specialize
Triton.instance.log(
    Triton.instance.fromTemplate()
        .level(TritonTypes.Level.INFO)
        .summary('Opportunity sync started')
        .details('seed=nightly, source=ERP')
);
```

## LWC – Component-Scoped Template

```js
import Triton, { LEVEL, TYPE, AREA } from 'c/triton';

const triton = new Triton().bindToComponent('c-opp-sync'); // scopes component details

triton.setTemplate(
  triton.makeBuilder()
    .type(TYPE.FRONTEND)
    .area(AREA.OPPORTUNITY_MANAGEMENT)
);

// Usage later:
triton.log(
  triton.fromTemplate()
    .summary('Button clicked')
    .details('action=sync-all')
);
```

## Real-World Example: Customer Service Portal

```js
// Customer service LWC component with comprehensive template
export default class CustomerServicePortal extends LightningElement {
    triton;
    
    connectedCallback() {
        this.triton = new Triton().bindToComponent('c-customer-service-portal');
        
        // Set comprehensive template for all customer service operations
        this.triton.setTemplate(
            this.triton.makeBuilder()
                .type(TYPE.FRONTEND)
                .area(AREA.COMMUNITY)
                .level(LEVEL.INFO)
                .relatedObjects([this.recordId])
        );
    }
    
    async handleCaseCreation() {
        try {
            const result = await createCase({ caseData: this.caseForm });
            
            // Uses template, adds specific details
            this.triton.log(
                this.triton.fromTemplate()
                    .summary('Case created successfully')
                    .details(JSON.stringify({ 
                        caseId: result.Id, 
                        priority: this.caseForm.priority,
                        category: this.caseForm.category 
                    }))
                    .relatedObjects([result.Id])
            );
            
        } catch (error) {
            // Template properties preserved in error logs
            this.triton.logNow(
                this.triton.fromTemplate()
                    .exception(error)
                    .summary('Case creation failed')
            );
        }
    }
}
```

## Template Benefits

### Consistency

* All logs in a method/component share the same base properties
* Reduces the risk of inconsistent categorization
* Ensures proper context across all log entries

### Maintainability

* Changes to common properties only need to be made in one place
* Reduces code duplication and drift
* Makes updates and refactoring easier

### Reduced Errors

* No risk of forgetting to set important properties
* Template ensures all required fields are populated
* Consistent structure across all logging calls

### Performance

* Template cloning is efficient
* Reduces object creation overhead
* Maintains singleton pattern benefits

## Template Override Pattern

Show how to override template properties when needed:

```apex
// Template sets common properties
Triton.instance.setTemplate(
    Triton.makeBuilder()
        .category(TritonTypes.Category.Apex)
        .type(TritonTypes.Type.Backend)
        .area(TritonTypes.Area.Accounts)
        .relatedObject(accountId)
);

// Override specific properties as needed
Triton.instance.log(
    Triton.instance.fromTemplate()
        .level(TritonTypes.Level.INFO)        // Override level
        .summary('Account processed')         // Add specific summary
        .details('status=completed')          // Add specific details
        .duration(processingTime)             // Add duration
        .relatedObjects(new Set<Id>{contactId}) // Override related objects
);
```

## Best Practices

### Do's

* ✅ Clone from `fromTemplate()` to get a pre-filled builder and add specifics
* ✅ Set templates early in methods/components
* ✅ Use templates for all logging calls within a scope
* ✅ Override only what's specific to each log entry

### Don'ts

* ❌ Call `addEvent/addDebug` directly in new code
* ❌ Use `makeBuilder()` for every log entry
* ❌ Forget to set templates in new methods
* ❌ Override template properties unnecessarily

## Template Scoping

### Method-Level Templates

```apex
public void processAccount(Id accountId) {
    // Set template for this method
    Triton.instance.setTemplate(
        Triton.makeBuilder()
            .category(TritonTypes.Category.Apex)
            .type(TritonTypes.Type.Backend)
            .area(TritonTypes.Area.Accounts)
            .relatedObject(accountId)
    );
    
    // All logs in this method use the template
    Triton.instance.log(Triton.instance.fromTemplate().summary('Processing started'));
    // ... processing logic ...
    Triton.instance.log(Triton.instance.fromTemplate().summary('Processing completed'));
}
```

### Component-Level Templates

```js
export default class AccountManager extends LightningElement {
    triton;
    
    connectedCallback() {
        this.triton = new Triton().bindToComponent('c-account-manager');
        
        // Set template for entire component
        this.triton.setTemplate(
            this.triton.makeBuilder()
                .type(TYPE.FRONTEND)
                .area(AREA.ACCOUNTS)
                .relatedObjects([this.recordId])
        );
    }
    
    // All methods in this component can use the template
    async handleSave() {
        this.triton.log(this.triton.fromTemplate().summary('Save initiated'));
        // ... save logic ...
    }
    
    async handleDelete() {
        this.triton.log(this.triton.fromTemplate().summary('Delete initiated'));
        // ... delete logic ...
    }
}
```

## Advanced Template Patterns

### Conditional Template Properties

```apex
// Set base template
Triton.instance.setTemplate(
    Triton.makeBuilder()
        .category(TritonTypes.Category.Apex)
        .type(TritonTypes.Type.Backend)
        .area(TritonTypes.Area.Accounts)
);

// Add conditional properties
if (isHighPriority) {
    Triton.instance.log(
        Triton.instance.fromTemplate()
            .level(TritonTypes.Level.WARNING)
            .summary('High priority account processed')
    );
} else {
    Triton.instance.log(
        Triton.instance.fromTemplate()
            .level(TritonTypes.Level.INFO)
            .summary('Standard account processed')
    );
}
```

### Template Inheritance

```apex
// Base template for all account operations
Triton.instance.setTemplate(
    Triton.makeBuilder()
        .category(TritonTypes.Category.Apex)
        .type(TritonTypes.Type.Backend)
        .area(TritonTypes.Area.Accounts)
);

// Specialize for specific operations
public void processHighValueAccount(Id accountId) {
    // Override template for this specific operation
    Triton.instance.setTemplate(
        Triton.instance.fromTemplate()
            .level(TritonTypes.Level.WARNING)
            .relatedObject(accountId)
    );
    
    // All logs in this method inherit the specialized template
    Triton.instance.log(Triton.instance.fromTemplate().summary('High value processing started'));
}
```

By mastering the template pattern, you'll create logging code that is consistent, maintainable, and efficient while providing rich context for all your log entries.
