Build beautiful, data-driven components with simple YAML configuration. No Apex. No custom LWC development. Just configure and deploy.
Technical Overview | April 30, 2026
Kaptio Enablement Team
Canvas is a configuration-driven system for building dynamic, data-rich widgets that render inside Salesforce Lightning record pages.
Canvas moves the rendering logic outside of Salesforce. The LWC component is just a thin shell that fetches pre-rendered HTML from the Canvas API. This means complex queries, aggregations, and visualizations happen server-side without any Apex governors or LWC limitations.
A simple request-render cycle that delivers dynamic content to Salesforce
/canvas/{tenant}/{canvasId}/renderSOQL via REST API<div class="canvas-widget">...rendered HTML...</div>edgeCanvasRunner component initializes with canvasId and tenantId properties
LWC calls Canvas API with tenant, canvas ID, and optional record context
Canvas API loads YAML config, queries Salesforce, renders HTML
LWC injects HTML into shadow DOM, user sees rendered canvas widget
| Component | Location | Purpose |
|---|---|---|
edgeCanvasRunner | Salesforce Org (LWC) | Thin shell component that fetches and displays canvas HTML |
Canvas API | canvas.edge.kaptioapis.com | Server that reads YAML configs, queries SF, renders HTML |
Canvas YAML | GitLab (edge-doc-engine-configs) | Configuration files defining queries, templates, styling |
Flexipage | Salesforce Org (Metadata) | Record page layout with edgeCanvasRunner components |
Each canvas is defined by a simple YAML configuration file. No code - just declarative configuration.
# agent-scorecard.canvas.yaml
# KPI scorecard for Travel Agency 360 view
canvas:
id: agent-scorecard
name: Agency Scorecard
description: Year-over-year performance metrics
connection:
tenant: {{TENANT_ID}}
auth: named-credential
data:
# Primary data source - the agency account
account:
object: Account
fields:
- Id
- Name
- KaptioTravel__TotalRevenue__c
- KaptioTravel__BookingsYTD__c
filter: "Id = :recordId"
# Aggregate query for YoY comparison
bookings_ytd:
type: aggregate
object: KaptioTravel__Itinerary__c
filter: |
KaptioTravel__Account__c = :recordId
AND CreatedDate = THIS_YEAR
aggregate:
- field: Id
function: COUNT
alias: total_bookings
- field: KaptioTravel__TotalPrice__c
function: SUM
alias: total_revenue
bookings_last_year:
type: aggregate
object: KaptioTravel__Itinerary__c
filter: |
KaptioTravel__Account__c = :recordId
AND CreatedDate = LAST_YEAR
aggregate:
- field: Id
function: COUNT
alias: total_bookings
- field: KaptioTravel__TotalPrice__c
function: SUM
alias: total_revenue
template:
type: handlebars
content: |
<div class="scorecard-grid">
<div class="kpi-card">
<div class="kpi-label">Bookings (YTD)</div>
<div class="kpi-value">{{bookings_ytd.total_bookings}}</div>
{{#if (gt bookings_ytd.total_bookings bookings_last_year.total_bookings)}}
<div class="kpi-trend up">
+{{percent_change bookings_ytd.total_bookings bookings_last_year.total_bookings}}%
</div>
{{/if}}
</div>
<div class="kpi-card">
<div class="kpi-label">Revenue</div>
<div class="kpi-value">{{currency bookings_ytd.total_revenue "USD"}}</div>
</div>
</div>
styles:
inline: true
css: |
.scorecard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
}
.kpi-card {
background: #f8fafc;
border-radius: 0.5rem;
padding: 1rem;
text-align: center;
}
.kpi-label {
font-size: 0.75rem;
color: #64748b;
text-transform: uppercase;
}
.kpi-value {
font-size: 1.5rem;
font-weight: 600;
color: #1e293b;
}
.kpi-trend.up {
color: #22c55e;
font-size: 0.875rem;
}Defines how the Canvas API connects to Salesforce for this tenant.
tenant: Unique identifier for the org
auth: named-credential | oauthDefine one or more data sources. Supports standard queries and aggregates.
object: Salesforce object API name
fields: Fields to retrieve
filter: WHERE clause (supports :recordId)
aggregate: COUNT, SUM, AVG, etc.Handlebars template that renders the HTML using query results.
{{field}} - Output value
{{#if condition}} - Conditionals
{{#each list}} - Loops
{{currency val "USD"}} - HelpersCSS rules scoped to this canvas. Rendered inline for isolation.
inline: true | false
css: Standard CSS rules
theme: Optional theme variables:recordIdThe Salesforce record ID passed from the LWC component
{{TENANT_ID}}Placeholder replaced during deployment with actual tenant
:userIdThe current Salesforce user ID for permissions
Ready-to-deploy canvas collections with record types, flexipages, and pre-configured widgets.
Complete 360-degree views for B2B travel distribution: Consortium management, Agency performance tracking, and Advisor productivity.
consortium-profileNetwork identity and tierconsortium-scorecardAggregate KPIsmember-agenciesMember agency listagent-scorecardYoY performance metricsquote-options-pipelineExpiring quotes urgency viewComplete 360-degree views for B2C guest/customer management with lifecycle-aware tabs and predictive analytics.
customer-profileGuest identity cardcustomer-valueLifetime value metricsnext-best-actionAI-powered recommendationshousehold-membersFamily/travel partybooking-journeyTrip history timelineEach solution bundle includes a manifest.json file that defines requirements (record types, objects, permissions), canvas collection (source repo, files to clone), metadata (flexipages, LWC, permission sets), and deployment instructions. The manifest follows a standardized schema for automated deployment.
From template to live widget in your Salesforce org
Choose from pre-built bundles (B2B Agent 360, B2C Guest 360) or create custom canvases.
Set up required record types for Account and Contact objects.
Copy canvas YAML files from templates to your tenant folder.
Push flexipages, LWC, and permission sets to your org.
Link record pages to record types via Lightning App Builder.
Open a record and verify canvas widgets render correctly.
Use the Solution Deploy Wizard for a guided deployment experience. It handles record type creation, canvas cloning, and metadata deployment automatically.
POST /api/solutions/clone-canvases
{
"tenantId": "your-tenant",
"templatePath": "canvases/_templates/b2b-agent-360",
"files": ["agent-scorecard.canvas.yaml", ...]
}POST /api/solutions/create-record-types
{
"instanceUrl": "https://your-org.my.salesforce.com",
"accessToken": "...",
"recordTypes": [{...}]
}