Products & Views
ChamevoJS organizes customizable products using a three-level hierarchy: Product -> Views -> Elements.
Data Model
interface CVProduct {
id?: string; // Auto-generated from title if omitted
title?: string;
thumbnail?: string;
views: CVView[];
options?: Partial<ChamevoOptions>; // Product-level option overrides
namesNumbers?: NamesNumbersEntry[]; // Names & Numbers roster — shared across all views
}
interface CVView {
id?: string; // Auto-generated from title if omitted
title: string;
thumbnail?: string;
elements: CVElementData[];
printAreas?: CVPrintAreaConfig[];
options?: Partial<ChamevoViewOptions>; // View-level option overrides
locked?: boolean; // Optional view (user must unlock)
}
interface CVElementData {
id?: string;
type: ElementType; // 'text' | 'image' | 'textbox' | 'curved-text' | 'neon-text' | 'engraved-text'
title: string;
source: string; // Text content for text types, URL for images
parameters: ElementParameters;
}
Loading Products
// New format (recommended)
await chamevo.loadProduct({
title: 'Hoodie',
thumbnail: '/images/hoodie-thumb.jpg',
views: [
{ title: 'Front', elements: [...] },
{ title: 'Back', elements: [...] },
],
});
// Legacy format (flat array — auto-normalized)
await chamevo.loadProduct([
{ title: 'Front', productTitle: 'Hoodie', elements: [...] },
{ title: 'Back', elements: [...] },
]);
When loading a legacy CVView[] array, ChamevoJS extracts productTitle and productThumbnail from the first view to build the CVProduct wrapper.
Auto-Generated IDs
When id is omitted, ChamevoJS generates a URL-friendly slug from the title via generateSlugId():
"Front View" → "front-view"
"T-Shirt Back" → "t-shirt-back"
Switching Views
ChamevoJS uses a single canvas architecture. Only one view is rendered at a time:
// Switch to view by index
await chamevo.selectView(1); // Switch to "Back"
// Current state
console.log(chamevo.currentViewIndex); // 1
console.log(chamevo.currentView.title); // "Back"
console.log(chamevo.views.length); // 2
When switching views:
- Current view state is saved (element positions, transforms, etc.)
- Canvas is cleared
- New view elements are rendered
Getting Product Data
// Get the full product with all current customizations
const product = chamevo.getProduct();
// Get order data (product + metadata)
const order = chamevo.getOrder();
// { product: CVProduct, usedFonts: FontInfo[], usedColors: ColorInfo[] }
// Get elements from a specific view
const frontElements = chamevo.getElements(0); // All elements in view 0
const textElements = chamevo.getElements(0, 'text'); // Only text elements
Per-View Options
Each view can override a subset of options. These are the 21 view-scoped keys:
const product = {
title: 'Mug',
views: [
{
title: 'Front',
elements: [...],
options: {
stageWidth: 600, // Override canvas dimensions
stageHeight: 400,
maxPrice: 50, // Different price limit
customTextParameters: {
maxLength: 20, // Shorter text limit for this view
},
},
},
{
title: 'Back',
elements: [...],
// Uses global defaults (no overrides)
},
],
};
View-scoped keys include: stageWidth, stageHeight, elementParameters, textParameters, imageParameters, customTextParameters, customImageParameters, maxPrice, pricingRules, layouts, optionalView, customTextAsTextbox, maxColorableSVGPaths, disabledModules, industry, dynamicViewsOptions, printingBox, usePrintingBoxAsBounding, modulesConfig.
Color Sync Across Views (colorLinkGroup)
Elements with the same colorLinkGroup value synchronize their color across all views:
const product = {
views: [
{
title: 'Front',
elements: [
{
type: 'image',
source: '/images/shirt-front.svg',
title: 'Shirt Front',
parameters: {
colorLinkGroup: 'shirt-color',
fill: '#ffffff',
},
},
],
},
{
title: 'Back',
elements: [
{
type: 'image',
source: '/images/shirt-back.svg',
title: 'Shirt Back',
parameters: {
colorLinkGroup: 'shirt-color', // Same group
fill: '#ffffff',
},
},
],
},
],
};
// When user changes the front shirt color to red,
// the back shirt automatically updates to red too.
Optional Views
Views can be locked by default, requiring the user to explicitly unlock them:
{
title: 'Inside Flap',
elements: [...],
locked: true, // or set optionalView: true in view options
}
Next Steps
- Elements Guide — Element types and parameters
- Print Areas Guide — Defining printable regions
- Options Cascade — How options merge