Kaptio Edge Platform

Edge Canvas

Dynamic Widgets for Salesforce Record Pages

Build beautiful, data-driven components with simple YAML configuration. No Apex. No custom LWC development. Just configure and deploy.

37+
Canvas Templates
2
Solution Bundles
YAML
Config Format
No Apex RequiredReal-time DataTenant IsolatedGit-based Config

Technical Overview | April 30, 2026

Kaptio Enablement Team

Overview

What is Edge Canvas?

Canvas is a configuration-driven system for building dynamic, data-rich widgets that render inside Salesforce Lightning record pages.

The Challenge

  • Building custom LWC components requires specialized developers
  • Apex governors limit complex queries and aggregations
  • Each customization needs deployment cycles
  • Standard reports don't embed well in record pages

The Canvas Solution

  • YAML configuration - no code required
  • Rendered server-side with unlimited query capabilities
  • Git-based deployment - change config, see results
  • Pre-built templates for common 360-view patterns

Canvas Widget Examples

VT
Virtuoso Travel
Consortium • Platinum Tier
127
Member Agencies
$4.2M
YTD Revenue
consortium-profile.canvas

Agency Performance

Bookings (YTD)
847+12%
Revenue
$1.2M+8%
Avg. Booking$1,418
Conversion34%
agent-scorecard.canvas

Quote Pipeline

12
Expiring in 7 days
8
Expiring in 3 days
4
Expired (last 7 days)
quote-options-pipeline.canvas

The Key Insight

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.

Architecture

How Canvas Works

A simple request-render cycle that delivers dynamic content to Salesforce

Request Flow

Salesforce
edgeCanvasRunner LWC
1. Request
/canvas/{tenant}/{canvasId}/render
Canvas API
Render Engine
2. Query
SOQL via REST API
SF Data
Account, Itinerary, etc.
3. Return
<div class="canvas-widget">...rendered HTML...</div>
1

LWC Loads

edgeCanvasRunner component initializes with canvasId and tenantId properties

2

Fetch Canvas

LWC calls Canvas API with tenant, canvas ID, and optional record context

3

Server Render

Canvas API loads YAML config, queries Salesforce, renders HTML

4

Display

LWC injects HTML into shadow DOM, user sees rendered canvas widget

System Components

ComponentLocationPurpose
edgeCanvasRunnerSalesforce Org (LWC)Thin shell component that fetches and displays canvas HTML
Canvas APIcanvas.edge.kaptioapis.comServer that reads YAML configs, queries SF, renders HTML
Canvas YAMLGitLab (edge-doc-engine-configs)Configuration files defining queries, templates, styling
FlexipageSalesforce Org (Metadata)Record page layout with edgeCanvasRunner components
Configuration

Canvas YAML Format

Each canvas is defined by a simple YAML configuration file. No code - just declarative configuration.

agent-scorecard.canvas.yaml
# 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;
    }
🔌

Connection

Defines how the Canvas API connects to Salesforce for this tenant.

tenant: Unique identifier for the org
auth: named-credential | oauth
📊

Data Queries

Define 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.
📄

Template

Handlebars template that renders the HTML using query results.

{{field}} - Output value
{{#if condition}} - Conditionals
{{#each list}} - Loops
{{currency val "USD"}} - Helpers
🎨

Styles

CSS rules scoped to this canvas. Rendered inline for isolation.

inline: true | false
css: Standard CSS rules
theme: Optional theme variables

Special Variables

:recordId

The Salesforce record ID passed from the LWC component

{{TENANT_ID}}

Placeholder replaced during deployment with actual tenant

:userId

The current Salesforce user ID for permissions

Pre-Built Solutions

Solution Bundles

Ready-to-deploy canvas collections with record types, flexipages, and pre-configured widgets.

B2B20 canvases

B2B Agent 360

Complete 360-degree views for B2B travel distribution: Consortium management, Agency performance tracking, and Advisor productivity.

Record Types
ConsortiumTravel_AgencyAdvisor
Record Pages
Consortium 360Agency 360Advisor 360
Sample Canvases
consortium-profileNetwork identity and tier
consortium-scorecardAggregate KPIs
member-agenciesMember agency list
agent-scorecardYoY performance metrics
quote-options-pipelineExpiring quotes urgency view
+15 more canvases...
B2C17 canvases

B2C Guest 360

Complete 360-degree views for B2C guest/customer management with lifecycle-aware tabs and predictive analytics.

Record Types
HouseholdGuest
Record Pages
Household 360Guest Contact 360
Sample Canvases
customer-profileGuest identity card
customer-valueLifetime value metrics
next-best-actionAI-powered recommendations
household-membersFamily/travel party
booking-journeyTrip history timeline
+12 more canvases...

What's in a Solution Bundle?

📋
Canvas YAML Files
Pre-configured canvas templates with placeholder tenant IDs
📄
Flexipage Metadata
Lightning record page layouts with canvas components placed
🔐
Permission Sets
Required permissions for viewing canvas data
🌐
Remote Site Settings
CSP and remote site configs for Canvas API access

manifest.json

Each 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.

Deployment

How to Deploy Canvases

From template to live widget in your Salesforce org

1

Select Solution Bundle

Choose from pre-built bundles (B2B Agent 360, B2C Guest 360) or create custom canvases.

  • Browse available solutions at /solutions
  • Review canvas components and record types
  • Check prerequisites (e.g., ACR enabled)
2

Create Record Types

Set up required record types for Account and Contact objects.

  • Use API to create record types automatically
  • Or create manually in Salesforce Setup
  • Assign to System Administrator profile
3

Clone Canvas Templates

Copy canvas YAML files from templates to your tenant folder.

  • Uses GitLab API to clone files
  • Replaces {{TENANT_ID}} with your tenant
  • Creates files in canvases/{tenantId}/
4

Deploy Salesforce Metadata

Push flexipages, LWC, and permission sets to your org.

  • Download metadata ZIP or use SFDX
  • Deploy edgeCanvasRunner LWC component
  • Deploy flexipage record page layouts
5

Assign Flexipages

Link record pages to record types via Lightning App Builder.

  • Open Lightning App Builder for each flexipage
  • Activate and assign to record type
  • Or use Salesforce API for bulk assignment
6

Test & Validate

Open a record and verify canvas widgets render correctly.

  • Navigate to Account/Contact record
  • Check canvas components load data
  • Verify styling and responsiveness

Ready to Deploy?

Use the Solution Deploy Wizard for a guided deployment experience. It handles record type creation, canvas cloning, and metadata deployment automatically.

Clone Canvases API

POST /api/solutions/clone-canvases
{
"tenantId": "your-tenant",
"templatePath": "canvases/_templates/b2b-agent-360",
"files": ["agent-scorecard.canvas.yaml", ...]
}

Create Record Types API

POST /api/solutions/create-record-types
{
"instanceUrl": "https://your-org.my.salesforce.com",
"accessToken": "...",
"recordTypes": [{...}]
}