Integrations
Data Binding
Connect design elements to spreadsheet data for dynamic content. Create templates that automatically update when data changes.
How Data Binding Works
Connect elements to live data sources
┌─────────────────────────────────────────────────────────────────────┐ │ DATA BINDING FLOW │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ Sheets │ │ Binding │ │ Design Element │ │ │ │ Service │ ───▶ │ Engine │ ───▶ │ (Text, Image) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ │ │ │ │ │ │ │ ┌──────┴──────┐ │ │ │ Bindings │ │ │ │ Config │ │ │ └─────────────┘ │ │ │ │ Flow: │ │ 1. Create binding between element and cell/range │ │ 2. Engine fetches data from Sheets service │ │ 3. Element content updates automatically │ │ 4. Changes in Sheets propagate in real-time (via webhooks) │ │ │ └─────────────────────────────────────────────────────────────────────┘
Social Media Templates
Generate variants for different products or messages
Report Generation
Create charts and infographics from live data
Personalization
Customize designs with names, dates, or user data
Batch Export
Export multiple designs with different data
Connecting to Sheets
Access spreadsheet data from sheets.platphormnews.com
// List available sheets
// GET https://sheets.platphormnews.com/api/v1/sheets
const sheets = await fetch(
'https://sheets.platphormnews.com/api/v1/sheets',
{ headers: { 'X-PlatPhorm-API-Key': apiKey } }
).then(r => r.json())
// {
// sheets: [
// {
// id: "sheet_abc123",
// name: "Product Catalog",
// worksheets: ["Products", "Categories", "Prices"],
// lastModified: "2024-01-15T10:00:00Z"
// },
// {
// id: "sheet_def456",
// name: "Marketing Copy",
// worksheets: ["Headlines", "Descriptions", "CTAs"],
// lastModified: "2024-01-14T15:00:00Z"
// }
// ]
// }Creating Bindings
Link design elements to data cells
import { useDataBinding } from '@/hooks/use-data-binding'
function BindingPanel({ element }) {
const { createBinding, bindings } = useDataBinding()
const handleBind = async () => {
await createBinding({
elementId: element.id,
property: 'content', // Which property to bind
source: {
sheetId: 'sheet_abc123',
worksheet: 'Products',
cell: 'A2', // or range: 'A2:A10'
},
transform: (value) => value.toUpperCase(), // Optional
})
}
return (
<div>
<p>Bind "{element.content}" to sheet data</p>
<SheetSelector onSelect={handleBind} />
</div>
)
}
// Binding interface
interface DataBinding {
id: string
elementId: string
property: 'content' | 'src' | 'fill' | 'stroke'
source: {
sheetId: string
worksheet: string
cell: string
}
transform?: (value: any) => any
fallback?: any // Value if cell is empty
}Batch Generation
Generate multiple designs from rows of data
// Generate design variants from sheet data
import { useBatchGenerate } from '@/hooks/use-batch-generate'
function BatchGenerator({ design }) {
const { generate, isGenerating, progress } = useBatchGenerate()
const handleGenerate = async () => {
const results = await generate({
designId: design.id,
source: {
sheetId: 'sheet_abc123',
worksheet: 'Products',
range: 'A2:D100', // Each row becomes a variant
},
bindings: [
{ property: 'content', column: 'A', elementId: 'title_element' },
{ property: 'content', column: 'B', elementId: 'desc_element' },
{ property: 'content', column: 'C', elementId: 'price_element' },
{ property: 'src', column: 'D', elementId: 'image_element' },
],
export: {
format: 'png',
preset: 'og-image',
naming: 'row_{{A}}_og' // Filename template
}
})
// results: {
// total: 98,
// successful: 98,
// failed: 0,
// exports: [
// { rowIndex: 1, filename: 'row_Widget_Pro_og.png', url: '...' },
// { rowIndex: 2, filename: 'row_Widget_Mini_og.png', url: '...' },
// ...
// ],
// zipUrl: '...' // All files in a ZIP
// }
}
return (
<div>
<button onClick={handleGenerate} disabled={isGenerating}>
{isGenerating ? `Generating... ${progress}%` : 'Generate All'}
</button>
</div>
)
}Real-time Updates
Automatically update when data changes
// Subscribe to sheet changes
import { useSheetSubscription } from '@/hooks/use-sheet-subscription'
function LiveDesign({ design, bindings }) {
// Subscribe to changes in bound cells
useSheetSubscription({
sheetId: 'sheet_abc123',
cells: bindings.map(b => b.source.cell),
onUpdate: (updates) => {
// Updates: [{ cell: 'A2', oldValue: '...', newValue: '...' }]
for (const update of updates) {
const binding = bindings.find(b => b.source.cell === update.cell)
if (binding) {
updateElement(binding.elementId, {
[binding.property]: update.newValue
})
}
}
}
})
return <Canvas design={design} />
}
// Behind the scenes, this uses webhooks from the Sheets service
// Webhook event: sheets.cell.updated
// {
// type: "sheets.cell.updated",
// data: {
// sheetId: "sheet_abc123",
// worksheet: "Products",
// cell: "A2",
// oldValue: "Widget",
// newValue: "Widget Pro"
// }
// }Template Variables
Use Mustache-style syntax in text content
// Instead of binding entire elements, use template variables
// Text element content with variables
const textElement = {
id: 'text_001',
type: 'text',
content: 'Introducing {{product_name}} - {{tagline}}',
// ...
}
// Define variable sources
const variables = {
product_name: { sheetId, worksheet, cell: 'A2' },
tagline: { sheetId, worksheet, cell: 'B2' },
}
// Apply template
await applyTemplate(design.id, variables)
// Result: "Introducing Widget Pro - The best widget ever"
// Supported syntax:
// {{variable}} - Simple substitution
// {{variable|upper}} - With filter (upper, lower, title, etc.)
// {{variable|default:"N/A"}} - With default value
// {{price|currency}} - Format as currencyMCP Tools
AI agent access for data binding
// Available MCP tools for data binding
// Fetch data from sheet
await mcp.call('data_fetch', {
sheetId: 'sheet_abc123',
range: 'A1:D10'
})
// Create binding
await mcp.call('data_bind', {
designId: 'design_current',
elementId: 'text_001',
property: 'content',
sheetId: 'sheet_abc123',
cell: 'A2'
})
// Remove binding
await mcp.call('data_unbind', {
designId: 'design_current',
elementId: 'text_001',
property: 'content'
})
// Generate batch from sheet
await mcp.call('data_batch_generate', {
designId: 'design_current',
sheetId: 'sheet_abc123',
range: 'A2:D100',
exportFormat: 'png'
})Best Practices
Tips for effective data binding
Design for Variable Content
Account for text length variations. Use auto-sizing text boxes or design for the longest expected content.
Validate Data
Always provide fallback values for empty cells. Validate URLs before binding to image elements.
Cache Appropriately
Sheet data is cached for performance. Force refresh when you need the latest data immediately.
Use Named Ranges
Named ranges in sheets make bindings more maintainable than cell references like A2.
Related Documentation
- Learn about SVG Service
- Explore Export System
- See Webhooks for real-time updates