JavaScript Documentation
Complete setup, data, customization and API reference for Iza Product Designer.
Getting Started
Iza Product Designer is a responsive browser-based product editor built with modern JavaScript, Fabric.js and CSS. It supports multiple products and views, editable image/SVG/text/shape layers, artwork libraries, color editing, curved text, snapping, rulers, history, saved designs, preview downloads and print-ready production exports.
The editor is configured from JavaScript while products and reusable content are described with JSON. Product assets are loaded relative to the product JSON file, allowing every product to live in its own portable folder.
file:// will prevent JSON, fonts and image assets from loading because browsers restrict local fetch requests.
Requirements
- A modern browser with Canvas, Promises, Fetch and the FontFace API.
- An HTTP/HTTPS web server. For development, run
npm run dev. - Correct CORS headers when JSON, fonts or images are hosted on another domain.
- Optimized PNG, JPG and SVG assets. Use JPG for photos, PNG for transparency and SVG for scalable artwork. Keep files compressed but large enough for sharp production output; oversized images and complex SVGs increase memory usage and slow loading and exports.
Choosing the right image format
The best format depends on whether the asset needs editable colors, transparent areas, photographic detail or unlimited scaling. Selecting the appropriate format keeps the editor responsive and produces cleaner preview and production files.
| Format | Recommended use | Color customization |
|---|---|---|
| SVG | Logos, icons, shapes, line art and product sections that must remain sharp at every size. | Best option. The designer can expose a single fill or multiple detected fill groups for independent editing. |
| PNG | Transparent photographs, overlays, shadows, textures and raster artwork that cannot be represented accurately as vectors. | Supported through image tinting. Existing dark details and shading can be preserved, but results depend on the source pixels. A fully white PNG behaves like a clean color mask, so the selected color is reproduced accurately, similarly to recoloring a single-fill SVG. |
| JPG | Photographs and full rectangular background images that do not require transparency. | Not recommended. Because JPG has no transparent regions, applying a fill cannot isolate the visible subject reliably. |
SVG recommendations
- Use actual vector paths with explicit fill colors. Avoid embedding PNG or JPG files inside the SVG.
- Use
fillfor a single-color SVG andsvgFillwhen individual SVG fill groups need separate controls. - Simplify excessive path points and remove unused metadata before publishing the asset.
PNG and JPG recommendations
- Use PNG when transparent pixels or soft alpha edges are required; use JPG for opaque photographic content.
- Size raster files for the largest expected production output. Enlarging a small source cannot recreate missing image detail.
- Avoid unnecessarily large pixel dimensions. Large textures consume more browser memory and can slow loading, editing and export.
Prepare SVG and PNG Assets
Prepare product assets so their editable colors, photographic details and transparent areas work together correctly in Iza Product Designer. The video below demonstrates the complete SVG and PNG workflow, including creating a realistic shading overlay in Photoshop.
- SVG with shading: use SVG layers for editable product colors and place a transparent PNG shading overlay above them to preserve highlights, shadows, folds and texture.
- SVG without shading: use clean vector artwork when photographic texture and lighting are not required.
- Simple PNG: use a transparent raster image when the product does not require separate editable SVG regions.
Installation
Use the included start.html file as the integration reference. Copy the src, content and products folders next to your HTML file, preserving their internal structure and relative paths.
Include the global stylesheet first, followed by the compiled product designer script:
<head>
<link rel="stylesheet" href="content/global.css" type="text/css">
<script type="text/javascript" src="src/FWDIPD.js"></script>
</head>
Add the holder element where the designer should appear. Its ID must match the parent setting:
<body>
<div id="myDiv"></div>
</body>
Initialization
Initialize after the document is ready, as shown in start.html. The compiled script exposes the global FWDIPD class, so no module import is required.
if(document.readyState === 'complete'){
fwdipdInit();
}else{
document.addEventListener('DOMContentLoaded', function(){
fwdipdInit();
});
}
function fwdipdInit(){
new FWDIPD({
// Core: instance, product data, parent, main sizing.
id: 'fwdipd0',
product: ['./products/shirt/product.json', './products/cap/product.json'],
prodcutIndex: 0,
display: 'responsive',
parent: 'myDiv',
maxW: 1200,
resizeW: 1000,
maxH: 700,
minH: 600,
canvasW: 800, //600
canvasH: 650,
initVisible: false,
unit: 'mm', // px, mm, cm, inch. Fallback when product JSON does not define a root unit.
bleed: 3, // Default bleed in millimeters per edge. A view JSON value overrides it.
rulerPosition: 'canvas', // canvas, printingBox. Around Printing Box requires a printing box in the view.
rulerFixed: false, // If true, ruler starts visible and can still be hidden with the Ruler action.
autoScale: true,
currency: '$',
bg: '#f6f6f6',
toggleSnapToCenter: true,
snapColor: '#3858e9',
snapThreshold: 8,
// Bonding box for selected objects.
boundingBoxMode: ['clipping', 'Bounding Box'],
boundingBoxColor: '#FF0000',
showPrintingBox: true,
boundingBoxEditable: true,
boundingBoxInputs: true,
boundingBoxInputsBg: 'rgba(255, 255, 255, .94)',
boundingBoxInputsText: '#000000',
boundingBoxInputsFieldBg: '#f6f6f6',
boundingBoxInputsBorder: '#e2e2e2',
boundingBoxInputsBorderFocus: '#3858e9',
// Keyboard shortcuts.
addKeyboardSupport: true, // Enables keyboard shortcuts. Space + drag pans the zoomed canvas when the mouse is inside the viewer; Space + mouse wheel zooms when the ruler is visible.
keuboardMoveNudgeAmmount: 1, // Arrow keys: move the selected object by this amount in pixels.
keyboardMoveNudgeLargeAmmount: 10, // Shift + Arrow keys: move the selected object by this larger amount in pixels.
keyboardRotateAmmount: 1, // Alt + Left / Right: rotate the selected object by this amount in degrees.
keyboardRotateLargeAmmount: 15, // Shift + Alt + Left / Right: rotate the selected object by this larger amount in degrees.
keyboardScaleAmmount: 0.001, // Ctrl/Cmd + Arrow keys: scale the selected object by this amount.
keyboardScaleLargeAmmount: 0.1, // Ctrl/Cmd + Shift + Arrow keys: scale the selected object by this larger amount. Ctrl/Cmd + Z: undo. Ctrl/Cmd + Y or Ctrl/Cmd + Shift + Z: redo.
// Full-screen loader shown while product assets are prepared.
loader: {
text: 'Loading ',
bg: 'rgba(255, 255, 255, 0.6)',
iconBg: 'rgba(0, 88, 233, 0.2)',
icon: '#3858e9'
},
// Fonts available to text objects and text templates.
font: {
def: 'Roboto',
list: [
{label: 'Arial', family: 'Arial'},
{label: 'Times New Roman', family: 'Times New Roman'},
{label: 'Roboto', family: 'Roboto', url: 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap'},
{label: 'Montserrat', family: 'Montserrat', url: 'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;700&display=swap'},
{
label: 'MD Nichrome',
family: 'MDNichrome',
files: [
{url: './content/fonts/MD_Nichrome/MDNichrome-Regular.otf', weight: 400, style: 'normal'},
{url: './content/fonts/MD_Nichrome/MDNichrome-Bold.otf', weight: 700, style: 'normal'},
{url: './content/fonts/MD_Nichrome/MDNichrome-Black.otf', weight: 900, style: 'normal'}
]
}
]
},
// Shared modal window used for delete, reset, errors and info.
dialog: {
ok: 'Ok',
overlay: 'rgba(0, 0, 0, 0.6)',
bg: 'rgba(255, 255, 255, 1)',
text: 'rgba(0, 0, 0, .7)',
btn: {
bg: 'rgba(56, 88, 233, 1)',
bgOver: 'rgba(56, 88, 233, 0.7)',
text: '#FFFFFF',
textOver: '#FFFFFF'
},
close: {
icon: '#444444',
iconOver: '#3858e9'
},
del: {
show: true,
text: 'Are you sure you want to delete this element?',
btn: 'Delete'
},
reset: {
show: true,
text: 'Are you sure you want to reset this element?',
btn: 'Reset'
},
info: {
maxW: 560,
html: `
<div class="fwdipd-info-window-content">
<h3>Editor help</h3>
<p>
Use these shortcuts to move faster while designing. Select an element first, then use the keyboard to cointrol it.Any HTML/text can be added here!
</p>
<dl>
<dt>Arrow keys</dt><dd>Move 1px</dd>
<dt>Shift + Arrow keys</dt><dd>Move 10px</dd>
<dt>Alt + Left / Right</dt><dd>Rotate -1 / +1 degree</dd>
<dt>Shift + Alt + Left / Right</dt><dd>Rotate -15 / +15 degrees</dd>
<dt>Ctrl / Cmd + Up / Down</dt><dd>Scale up / down uniformly</dd>
<dt>Ctrl / Cmd + Left / Right</dt><dd>Scale X down / up</dd>
<dt>Ctrl / Cmd + Shift + Up / Down</dt><dd>Scale Y up / down</dd>
<dt>Delete / Backspace</dt><dd>Delete selected element</dd>
<dt>Ctrl / Cmd + D</dt><dd>Duplicate selected element</dd>
<dt>Ctrl / Cmd + Z</dt><dd>Undo</dd>
<dt>Ctrl / Cmd + Y</dt><dd>Redo</dd>
<dt>Ctrl / Cmd + Shift + Z</dt><dd>Redo</dd>
<dt>Hold Space + drag</dt><dd>Pan / scroll the canvas when the ruler is visible</dd>
<dt>Hold Space + mouse wheel</dt><dd>Zoom in / out when the ruler is visible</dd>
<dt>Escape</dt><dd>Close current edit / deselect object</dd>
</dl>
</div>
`
}
},
// Top action bar.
actionBar: {
leftlistLabel: 'File',
leftList: false,
leftListBg: '#ffffff',
leftListIcon: '#000000',
leftListIconOver: '#3858e9',
leftListBorder: '#e2e2e2',
rightList: false,
rightlistLabel: 'More',
rightListBg: '#ffffff',
rightListIcon: '#000000',
rightListIconOver: '#3858e9',
rightListBorder: '#e2e2e2',
bg: '#3858e9',
nav: [
[
{label: 'Save Design', button: 'savedDesign'},
{label: 'Saved Designs', button: 'savedDesigns'},
{label: 'Preview', button: 'preview'},
{label: 'Print', button: 'print'},
{label: 'Download Preview', button: 'download'},
{label: 'Doownload Production', button: 'productionExport'},
],
[
{label: 'Undo', button: 'undo'},
{label: 'Redo', button: 'redo'},
{label: 'Ruler', button: 'ruler'},
{label: 'Zoom', button: 'zoom'},
{label: 'Fullscreen', button: 'fullscreen'},
{label: 'Snap To Center', button: 'snapToCenter'},
// {label: 'Prev View', button: 'prevView'},
// {label: 'Next View', button: 'nextView'},
{label: 'Reset', button: 'reset'}
],
[
{label: 'Info', button: 'info'},
{label: 'Export', button: 'export'},
// {label: 'Total', button: 'done'},
]
],
icon: '#ffffff',
iconOver: '#dbe4ff',
iconDisabled: 'rgba(255, 255, 255, 0.3)',
toolTip: {
bg: '#000000',
text: '#ffffff'
}
},
// Download window.
download: {
title: 'Download',
text: 'Choose what you want to export.',
scope: 'all', // 'all' or 'current'
all: 'All views',
current: 'Current view',
maxW: 390,
bg: 'rgba(0, 0, 0, 0.02)',
bgOver: 'rgba(56, 88, 233, 1)',
formats: [
{label: 'PNG', button: 'png', description: 'Best for transparent images'},
{label: 'JPG', button: 'jpg', description: 'Flattened image file'},
{label: 'SVG', button: 'svg', description: 'Editable vector file'},
{label: 'PDF', button: 'pdf', description: 'One PDF with selected views'}
]
},
// Full-screen preview window.
preview: {
overlay: 'rgba(0, 0, 0, .8)',
title: '#ffffff',
itemBg: 'rgba(255, 255, 255, .96)',
itemText: '#000000',
close: '#ffffff',
closeOver: '#3858e9',
scrollbar: '#3858e9'
},
// View switcher and its thumbnail grid.
views: {
pos: 'bottomRight',
bg: '#ffffff',
border: '#e2e2e2',
icon: '#000000',
iconOver: '#3858e9',
nav: {
maxW: 210,
h: 42,
bottomGap: 12
},
grid: {
bg: '#FFFFFF',
itemBg: 'rgba(255, 255, 255, 1)',
itemBgOver: 'rgba(56, 88, 233, 0.7)'
}
},
// Left modules bar and the panel behind Layers/Text/Images.
modules: {
buttons: [
{label: 'Products', button: 'products'},
{label: 'Saved Designs', button: 'savedDesigns'},
{label: 'Layers', button: 'layers'},
{label: 'Text', button: 'text'},
{label: 'Images', button: 'images'},
{label: 'Shapes', button: 'shapes'},
{label: 'Artwork', button: 'artworkLibrary'}
],
pos: 'left', // 'left' or 'bottom'
allowToggle: true,
toggled: true,
bg: '#ffffff',
border: '#e2e2e2',
panelBg: '#ffffff',
icon: '#000000',
iconOver: '#3858e9',
btnBg: 'rgba(255, 255, 255, 0.1)',
btnBgOver: 'rgba(56, 88, 233, 0.1)'
},
// Products module previews.
products: {
priceColor: '#FFFFFF',
priceBg: 'rgba(0,0,0,.7)',
bg: '#ffffff',
btnBg: 'rgba(56, 88, 233, 1)',
btnBgOver: 'rgba(56, 88, 233, 0.7)',
btnText: '#FFFFFF',
btnTextOver: '#FFFFFF',
close: '#111111',
closeOver: '#3858e9',
itemBg: '#ffffff',
itemBgOver: 'rgba(56, 88, 233, 0.2)',
titleColor: '#FFFFFF',
titleBg: 'rgba(0,0,0,.7)',
titleSize: 14
},
// Saved Designs module.
savedDesigns: {
json: './content/saved-designs.json',
inputPlaceholder: 'Optional title',
btn: 'Save design',
bg: '#ffffff',
btnBg: 'rgba(56, 88, 233, 1)',
btnBgOver: 'rgba(56, 88, 233, 0.7)',
btnText: '#FFFFFF',
btnTextOver: '#FFFFFF',
removable: true,
close: '#111111',
closeOver: '#3858e9',
itemBg: '#ffffff',
itemBgOver: 'rgba(56, 88, 233, 0.2)',
titleColor: '#FFFFFF',
titleBg: 'rgba(0,0,0,.7)',
titleSize: 12,
inputBg: '#ffffff',
inputText: '#000000',
inputBorder: '#e2e2e2',
inputBorderFocus: '#3858e9',
canSave: true,
cooldownSeconds: 10,
loginText: 'Log in to save',
disabledText: 'Disabled for {seconds}'
},
// Layers list colors.
layers: {
bg: '#ffffff',
canEdit: true,
itemBg: 'rgba(56, 88, 233, 0)',
itemBgOver: 'rgba(56, 88, 233, 0.1)',
icon: '#333333',
iconOver: '#3858e9'
},
// Add Text module defaults and colors.
addText: {
json: './content/text.json',
btn: 'Add text',
price: 0,
removable: true,
canDuplicate: true,
colorPicker: true,
colors: ['#3858e9', '#B65A3C', '#D8A24A', '#C2413A', '#111111'],
canReset: true,
canMove: true,
canRotate: true,
canResize: true,
canDelete: true,
canReorder: true,
font: 'Roboto',
size: 30,
lineH: 1,
letter: 0,
curveType: 'normal',
radius: 0,
curve: 0,
offset: 0,
fill: '#ffffff',
stroke: null,
strokeW: 0,
bg: '#ffffff',
priceColor: '#FFFFFF',
priceBg: 'rgba(0,0,0,.7)',
btnBg: 'rgba(56, 88, 233, 1)',
btnBgOver: 'rgba(56, 88, 233, 0.7)',
btnText: '#FFFFFF',
btnTextOver: '#FFFFFF',
inputBg: '#ffffff',
inputText: '#000000',
inputBorder: '#d2d2d2'
},
// Add Images module defaults and colors.
addImg: {
json: './content/images.json',
btn: 'Add images',
price: 0,
removable: true,
colorPicker: true,
colors: ['#3858e9', '#B65A3C', '#D8A24A', '#C2413A', '#111111'],
canDuplicate: true,
canReset: true,
canMove: true,
canRotate: true,
canResize: true,
canDelete: true,
canReorder: true,
priceColor: '#FFFFFF',
priceBg: 'rgba(0,0,0,.7)',
bg: '#ffffff',
dropBg: '#f6f6f6',
dropBorder: '#d2d2d2',
dropText: 'Drop your images here',
dropColor: '#000000',
btnBg: 'rgba(56, 88, 233, 1)',
btnBgOver: 'rgba(56, 88, 233, 0.7)',
btnText: '#FFFFFF',
btnTextOver: '#FFFFFF',
close: '#111111',
closeOver: '#3858e9',
itemBg: '#ffffff',
itemBgOver: 'rgba(56, 88, 233, 0.2)'
},
// Add Shapes module. Uses built-in SVG shapes.
addShapes: {
json: './content/shapes.json',
price: 4,
priceColor: '#FFFFFF',
priceBg: 'rgba(0,0,0,.7)',
fill: '#000000',
colors: ['#3858e9', '#B65A3C', '#D8A24A', '#C2413A', '#000000'],
colorPicker: true,
removable: true,
canDuplicate: true,
canReset: true,
canMove: true,
canRotate: true,
canResize: true,
canDelete: true,
canReorder: true,
bg: '#ffffff',
close: '#111111',
closeOver: '#3858e9',
itemFill: '#000000',
itemBg: '#ffffff',
itemBgOver: 'rgba(56, 88, 233, 0.2)'
},
// Artwork Library module. Supports categories and search.
artworkLibrary: {
json: './content/artwork_library.json',
searchPlaceholder: 'Search artwork',
allCategoriesLabel: 'All',
price: 4,
removable: false,
colorPicker: true,
colors: ['#3858e9', '#B65A3C', '#D8A24A', '#C2413A', '#111111'],
canDuplicate: true,
canReset: true,
canMove: true,
canRotate: true,
canResize: true,
canDelete: true,
canReorder: true,
notFoundText: 'No artwork found',
bg: '#ffffff',
priceColor: '#FFFFFF',
priceBg: 'rgba(0,0,0,.7)',
close: '#111111',
closeOver: '#3858e9',
itemBg: '#ffffff',
itemBgOver: 'rgba(56, 88, 233, 0.2)',
searchBg: '#ffffff',
searchText: '#000000',
searchBorder: '#e2e2e2',
searchBorderFocus: '#3858e9',
catBg: 'rgba(0, 0, 0, 0.02)',
catBgOver: 'rgba(56, 88, 233, 0.1)',
catText: '#000000',
catTextOver: '#3858e9'
},
// Canvas background and object-control buttons.
canvas: {
showDimensions: true,
dimenstionsBg: 'rgba(0,0,0,.9)',
dimenstionsText: '#FFFFFF',
objBg: '#3858e9',
bg: '#FFFFFF',
icon: '#000000',
iconOver: '#ffffff',
iconBg: 'rgba(255, 255, 255, 1)',
iconBgOver: 'rgba(56, 88, 233, 1)',
zoomLevels: [1, 1.25, 1.5, 2],
zoomStep: 0.01,
rulerBg: 'rgba(255, 255, 255, 0.72)',
rulerText: 'rgba(0, 0, 0, 0.68)',
rulerTick: 'rgba(56, 88, 233, 1)',
rulerTickMajor: 'rgba(0, 0, 0, 0.65)',
rulerBorder: 'rgba(0, 0, 0, 0.2)',
toggleRuler: true,
},
// Floating object toolbar.
toolbar: {
buttons: [
{label: 'Color', button: 'color'},
{label: 'Transform', button: 'transform'},
{label: 'Text', button: 'textFormat'},
{label: 'Curved Text', button: 'curvedText'},
{label: 'Align', button: 'position'},
{label: 'Reset', button: 'reset'},
{label: 'Duplicate', button: 'duplicate'},
{label: 'Remove', button: 'delete'}
],
align: [
{label: 'Top', button: 'top'},
{label: 'Middle', button: 'middle'},
{label: 'Bottom', button: 'bottom'},
{label: 'Left', button: 'left'},
{label: 'Center', button: 'center'},
{label: 'Right', button: 'right'}
],
curve: [
{label: 'Normal Text', button: 'normal'},
{label: 'Curved Up', button: 'curvedUp'},
{label: 'Curved Down', button: 'curvedDown'},
{label: 'Oblique', button: 'oblique'},
{label: 'Bridge', button: 'bridge'},
{label: 'Radius', button: 'radius'},
{label: 'Font Size', button: 'fontSize'},
{label: 'Letter Spacing', button: 'letterSpacing'},
{label: 'Curve', button: 'curve'},
{label: 'Offset', button: 'offset'}
],
color: [
{label: 'Fill Color', button: 'fill'},
{label: 'Transparency', button: 'transparency'},
{label: 'Shadow', button: 'shadow'},
{label: 'Blur', button: 'blur'},
{label: 'Stroke Color', button: 'strokeColor'},
{label: 'Stroke Width', button: 'strokeWidth'},
{label: 'Font Family', button: 'fontFamily'},
{label: 'Font Size', button: 'fontSize'},
{label: 'Line Height', button: 'lineHeight'},
{label: 'Letter Spacing', button: 'letterSpacing'},
{label: 'Offset X', button: 'offsetX'},
{label: 'Offset Y', button: 'offsetY'},
],
transform: [
{label: 'Scale X', button: 'scaleX'},
{label: 'Scale Y', button: 'scaleY'},
{label: 'Rotate', button: 'rotate'},
{label: 'Skew X', button: 'skewX'},
{label: 'Skew Y', button: 'skewY'},
{label: 'Flip horizontal', button: 'flipHorizontal'},
{label: 'Flip vertical', button: 'flipVertical'}
],
objectToolbarMode: 'floating', // 'floating' or 'fixed'
toggled: false, // Auto-open the first available panel in fixed mode.
maxW: 393,
textMaxW: 460,
maxScale: 6,
maxSkew: 20,
defRadius: 40,
bg: 'rgba(255, 255, 255, 1)',
icon: '#000000',
iconOver: '#3858e9',
sliderBg: '#f6f6f6',
sliderBorder: '#e2e2e2',
sliderFill: '#3858e9',
sliderHandle: '#f6f6f6',
sliderInput: '#f6f6f6',
sliderHandleBorder: '#3858e9',
back: 'Back',
secBg: 'rgba(0, 0, 0, 0.02)',
secBgOver: 'rgba(56, 88, 233, 0.1)',
secIcon: '#000000',
secIconOver: '#3858e9',
secBorder: '#e2e2e2'
}
});
}
The id value also becomes the global API instance name. With id: 'fwdipd0', methods are available through window.fwdipd0 or directly as fwdipd0.
<button type="button" onclick="fwdipd0.export()">Export</button>
<button type="button" onclick="fwdipd0.destroy()">Destroy</button>
Multiple products
The product setting accepts one JSON path, one literal product object, or an array containing any combination of paths and objects. Only the selected product is rendered; the remaining entries are kept as product references for the Products module.
product: [
'./products/shirt/product.json',
'./products/cap/product.json',
literalProductObject
],
productIndex: 0 // Also accepts a product title.
Each product keeps its own canvas size, views, printing boxes, base price and initial state. Switching products reloads that product from its original data and resets zoom, view controls, selection, history and synchronized-view state.
Responsive layout
The editor measures its real parent container, not only the browser viewport. The module bar can be placed on the left or bottom. At compact widths the module content fills the available editor area and the object toolbar is attached to the bottom of the browser for reliable touch access.
maxW, resizeW, maxH and minH control the outer editor. Per-view canvas_width and canvas_height control the internal design stage.
Settings
Settings use short grouped names to keep initialization readable. Library JSON and product JSON can override the corresponding defaults at item or element level.
| are the accepted values or types. A CSS color can be any browser-supported color such as #3858e9, rgb(...), rgba(...), hsl(...), a named color or transparent.Core settings
Configure product sources, editor sizing, startup behavior, working units, pricing and the main appearance.
| Option | Type / values | Description |
|---|---|---|
id | Non-empty string (required) | Unique global instance name. instance is also accepted. |
product | JSON URL string | literal product object | array containing either | One product source or an ordered list of product sources. |
productIndex | Integer ≥ 0 | exact product-title string | Initial product index or title. The legacy alias prodcutIndex is accepted. |
basePrice | Number ≥ 0 | numeric string such as '10.00' | Fallback base price. Do not include a currency symbol; display currency comes from currency. A product JSON basePrice takes precedence. |
startAtView | Integer ≥ 0 | exact view-title string | Fallback initial view. A product JSON startAtView takes precedence. |
display | 'responsive' | 'afterparent' | 'lightbox' | Controls how the editor is displayed. Lightbox mode uses the dedicated lightbox settings below. displayType is an alias. |
parent | Non-empty element-ID string, without # | ID of the required editor holder. In lightbox mode it holds only the generated launch button. parentId is an alias. |
maxW, resizeW | Finite number > 0 (CSS pixels) | percentage string in lightbox mode | Maximum editor width and width at which automatic scaling starts. Lightbox values such as '90%' are relative to browser width. |
maxH, minH | Finite number > 0 (CSS pixels) | percentage string in lightbox mode | Maximum and minimum editor heights. Lightbox values such as '90%' are relative to browser height. |
canvasW, canvasH | Finite number > 0 (canvas pixels) | Fallback canvas size when a view does not define canvas_width/canvas_height. |
initVisible | true | false | When true, initialization waits until the editor enters the viewport. |
autoScale | true | false | Scales the editor height with its responsive width. |
unit | 'mm' | 'cm' | 'inch' | 'px' | Fallback working unit for measurements and production output metadata. A root unit in the active product JSON overrides it. The ruler temporarily uses pixels while boundingBoxEditable is enabled. |
bleed | Finite number ≥ 0, in millimeters | Global physical bleed per edge. A view JSON options.bleed overrides it; an explicit value of 0 disables bleed. |
rulerPosition | 'canvas' | 'printingBox' | Places ruler zero around the entire canvas or the active printing box. |
rulerFixed | true | false | Starts the ruler visible. The Ruler action can still hide it. |
currency | String, for example '$', '€' or 'USD' | Currency symbol or code used for base, layer and library prices. |
bg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Main editor background. |
dropShadow | Valid CSS box-shadow string | 'none' | Outer editor shadow. |
Lightbox
Configure the full-browser overlay, generated Customize button and close button used by display: 'lightbox'. Closing only hides the viewer, so reopening it preserves the current product, edits and history. When both maxW and maxH are '100%', the close button becomes the final button in the action bar's right section instead of overlapping it.
lightbox: {
label: 'Customize',
bg: 'rgba(0, 0, 0, .7)',
btnBg: '#3858e9',
btnBgOver: 'rgba(56, 88, 233, .7)',
btnText: '#FFFFFF',
btnTextOver: '#FFFFFF',
closeW: 34,
closeH: 34,
closeBg: '#3858e9',
closeBgOver: '#FFFFFF',
closeIcon: '#FFFFFF',
closeIconOver: '#3858e9'
}| Option | Type / values | Description |
|---|---|---|
label | Non-empty string | Text displayed in the generated launch button. Defaults to 'Customize'. |
bg | CSS color | Background covering the browser while the lightbox is open. |
btnBg, btnBgOver | CSS color | Customize button background in its normal and hover states. |
btnText, btnTextOver | CSS color | Customize button text in its normal and hover states. |
closeW, closeH | Finite number >= 24 (CSS pixels) | Close-button width and height. |
closeBg, closeBgOver | CSS color | Close-button background in its normal and hover states. |
closeIcon, closeIconOver | CSS color | Close icon in its normal and hover states. |
Bounds and snapping
Control object boundaries, clipping, editable printing boxes and center-snapping behavior.
| Option | Type / values | Description |
|---|---|---|
boundingBoxMode | 'none', 'inside', 'clipping', an object title such as 'Bounding Box', or an array of these values | Fallback bounds used when an item or module does not define its own mode. Use one value for all products, or an array in the same order as product, one value per product. An object title uses that view object as the mask. |
boundingBoxColor | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Printing-box guide and editable bounding-box color. |
showPrintingBox | true | false | Shows the dashed printing-box guide. Hiding it does not change clipping, stored geometry or production export. |
boundingBoxEditable | true | false | Controls whether the current view printing box can be selected, moved and resized. Its dimensions are normalized to the physical print ratio in both states. When enabled, the ruler is forced to pixels so it matches the X, Y, W and H inputs. |
boundingBoxInputs | true | false | Shows X, Y, width and height inputs while the editable box is selected. All four values use whole canvas pixels. |
boundingBoxInputsBg, boundingBoxInputsText | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Bounding-box input panel background and text. |
boundingBoxInputsFieldBg, boundingBoxInputsBorder, boundingBoxInputsBorderFocus | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Bounding-box field background, normal border and focused border. |
toggleSnapToCenter | true | false | Initial global center-snapping state. The action bar toggle can change it at runtime. |
snapColor | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Vertical and horizontal snap-guide color. |
snapThreshold | Finite number ≥ 0 (canvas pixels) | Distance from center at which objects and editable bounds snap. |
Supported boundingBoxMode values
| Value | Behavior |
|---|---|
none | No boundary restriction or clipping is applied. The object can be moved and rendered anywhere on the canvas. |
inside | Uses the current view's rectangular printing_box as a movement boundary and keeps the object's transformed bounds inside it. Content is not masked. |
clipping | Uses the current view's rectangular printing_box as a clipping area. Parts of the object extending outside the box are hidden. |
An element title, such as Bounding Box or Overlay | Finds that element in the active view and uses its visible SVG shape or PNG alpha as the clipping mask. Title matching is case-insensitive. If no matching element exists in a view, no element-based mask can be applied there. |
printing_box, the red dotted guide always represents that rectangle. An object-title mode can still use an SVG shape or PNG alpha as the actual clipping mask, but it does not replace the visual printing-box guide. Without a printing box, the guide falls back to the selected object's applicable bounds.
A single value applies to every configured product:
boundingBoxMode: 'clipping'For multiple products, array positions follow the order of the product setting. In this example the first product uses its printing box, while the second uses the visible shape of an element titled Bounding Box:
product: [
'./products/shirt/product.json',
'./products/cap/product.json'
],
boundingBoxMode: ['clipping', 'Bounding Box']clipping.
Keyboard settings
Enable keyboard controls and configure movement, rotation and scaling increments.
| Option | Type / values | Description |
|---|---|---|
addKeyboardSupport | true | false | Enables editor shortcuts. Transform shortcuts are ignored when no editable object is selected. |
keuboardMoveNudgeAmmount | Finite number ≥ 0 (pixels) | Arrow-key movement. The misspelled key is retained for compatibility. |
keyboardMoveNudgeLargeAmmount | Finite number ≥ 0 (pixels) | Shift + Arrow movement. |
keyboardRotateAmmount | Finite number ≥ 0 (degrees) | Alt + Left/Right rotation step. |
keyboardRotateLargeAmmount | Finite number ≥ 0 (degrees) | Shift + Alt + Left/Right rotation step. |
keyboardScaleAmmount | Finite number > 0, typically 0.001–0.1 | Normal keyboard scale increment. |
keyboardScaleLargeAmmount | Finite number > 0, typically 0.01–1 | Large keyboard scale increment. |
Loader and fonts
Customize the loading screen and define the system, web and custom fonts available for text.
| Group / option | Type / values | Description |
|---|---|---|
loader.text | String, including an empty string | Text shown while product assets and fonts load. |
loader.bg, loader.iconBg, loader.icon | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Loader overlay, icon background and icon color. |
font.def | Font-family string matching a configured or installed font | Default family for text when the JSON does not specify one. |
font.list | {label, family}[] | {label, family, url}[] | {label, family, files: [{url, weight, style}]}[] | Fonts shown in the text toolbar. Supports system fonts, CSS URLs and custom font files with multiple weights/styles. |
font: {
def: 'Roboto',
list: [
{label: 'Arial', family: 'Arial'},
{
label: 'Roboto',
family: 'Roboto',
url: 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'
},
{
label: 'MD Nichrome',
family: 'MDNichrome',
files: [
{url: './content/fonts/MDNichrome-Regular.otf', weight: 400, style: 'normal'},
{url: './content/fonts/MDNichrome-Bold.otf', weight: 700, style: 'normal'}
]
}
]
}
Dialog settings
Customize confirmation, error and information dialogs, including their content, colors and buttons.
| Option | Type / values | Description |
|---|---|---|
dialog.ok | Non-empty string | Default acknowledgement button label. |
dialog.overlay, dialog.bg, dialog.text | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Full overlay, dialog panel and content text colors. |
dialog.btn | {bg, bgOver, text, textOver}; each: #hex | rgb(a) | hsl(a) | named | transparent | Primary dialog button states. |
dialog.close | {icon, iconOver}; each: #hex | rgb(a) | hsl(a) | named | transparent | Close-icon states. |
dialog.del | {show: true | false, text: string, btn: string} | Delete confirmation visibility, message and button label. |
dialog.reset | {show: true | false, text: string, btn: string} | Object/product reset confirmation visibility, message and button label. |
dialog.info | {maxW: number > 0, html: HTML string} | Custom help/info window. HTML, links, images and structured shortcut lists are accepted. |
Action bar
The action bar is divided into equal left, center and right arrays. Button order is exactly the order in actionBar.nav. Remove an entry to hide that action.
| Option | Type / values | Description |
|---|---|---|
actionBar.nav | [leftButtons[], centerButtons[], rightButtons[]], each item {label: string, button: actionName} | Exactly three arrays. Supported action names are listed below this table. |
actionBar.bg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Action bar background. |
actionBar.icon, actionBar.iconOver, actionBar.iconDisabled | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Normal, hover and disabled button colors. |
actionBar.toolTip.bg, actionBar.toolTip.text | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Document-level tooltip colors. |
actionBar.leftList, actionBar.rightList | true | false | Forces a File/More dropdown. Even when false, a side automatically becomes a list if its buttons do not fit. |
actionBar.leftlistLabel, actionBar.rightlistLabel | String, including an empty string | Labels next to the left menu and right more icons. |
actionBar.leftListBg, actionBar.rightListBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Dropdown window backgrounds. |
actionBar.leftListIcon, actionBar.leftListIconOver, actionBar.rightListIcon, actionBar.rightListIconOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Dropdown trigger and item colors. |
actionBar.leftListBorder, actionBar.rightListBorder | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Dropdown borders. |
Supported actionBar.nav[].button values: 'savedDesign', 'savedDesigns', 'preview', 'print', 'download', 'productionExport', 'undo', 'redo', 'ruler', 'zoom', 'fullscreen', 'snapToCenter', 'prevView', 'nextView', 'reset', 'info', 'export' and 'done'. Fullscreen expands the complete designer to the browser viewport and automatically returns to its configured size when the browser exits fullscreen.
Download and preview
Configure how customers preview the product and download the current view or all available views.
| Group / option | Type / values | Description |
|---|---|---|
download.title, download.text | Strings, including an empty string | Download dialog title and introduction. |
download.scope | 'all' | 'current' | Initially selected view scope. |
download.all, download.current | Non-empty strings | Scope button labels. |
download.maxW | Finite number > 0 (CSS pixels) | Maximum download dialog width. |
download.bg, download.bgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Format/scope button normal and hover backgrounds. |
download.formats | {label: string, button: 'png' | 'jpg' | 'svg' | 'pdf', description: string}[] | Ordered download-format definitions. Remove an entry to hide that format. |
preview.overlay | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Full-browser preview overlay. |
preview.title, preview.itemText | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Preview title and view label colors. |
preview.itemBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | View preview card background. |
preview.close, preview.closeOver, preview.scrollbar | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Close icon and responsive scrollbar colors. |
Views
Configure the navigation used to switch between product views, including its position, colors and thumbnail grid.
| Option | Type / values | Description |
|---|---|---|
views.pos | 'topLeft' | 'topCenter' | 'topRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight' | View navigation position. |
views.bg, views.border | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Navigation background and button border. |
views.icon, views.iconOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Normal and hover icon colors. |
views.nav.maxW, views.nav.h | Finite number > 0 (CSS pixels) | Navigation maximum width and height. |
views.nav.bottomGap, topGap, sideGap | Finite number ≥ 0 (CSS pixels) | Navigation offsets. |
views.grid.bg, itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Full view-grid window and thumbnail colors. |
The view navigation is automatically hidden when the selected product contains only one view.
Modules
Configure the module bar, its position and the tools customers can open while customizing a product.
| Option | Type / values | Description |
|---|---|---|
modules.buttons | {label: string, button: 'products' | 'savedDesigns' | 'layers' | 'text' | 'images' | 'shapes' | 'artworkLibrary'}[] | Ordered module definitions. Remove an entry to hide that module. |
modules.pos | 'left' | 'bottom' | Desktop module-bar position. |
modules.allowToggle | true | false | Allows the active module button to show/hide its content window. |
modules.toggled | true | false | Initial module content visibility. |
modules.bg, modules.border, modules.panelBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Bar, shared border and content panel backgrounds. |
modules.icon, modules.iconOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Module icon and label normal/hover colors. |
modules.btnBg, modules.btnBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Module button normal/hover backgrounds. |
Products and saved designs
Configure product selection and saved-design management, including thumbnails, titles and removal controls.
Saved designs can be loaded from savedDesigns.json: './content/saved-designs.json'.
| Group / option | Type / values | Description |
|---|---|---|
products.bg, itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Products window and preview-card colors. |
products.titleColor, titleBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Product title text and strip background. |
products.titleSize | Finite number > 0 (CSS pixels) | Product-title font size. |
products.priceColor, priceBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Optional price badge colors. |
products.btnBg, btnBgOver, btnText, btnTextOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Shared product action button states. |
products.close, closeOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Optional item close button states. |
savedDesigns.json | JSON URL string | JSON source string | literal saved-designs object | Initial saved-design collection. Runtime saves stay in memory and are dispatched for server persistence. |
savedDesigns.inputPlaceholder, btn | Strings, including an empty placeholder | Optional title placeholder and Save Design label. |
savedDesigns.canSave | true | false | Set this from your authentication state. When false, saving is disabled and loginText is shown. |
savedDesigns.cooldownSeconds | Integer ≥ 0 | Seconds before another design can be saved. The default is 10. |
savedDesigns.loginText, disabledText | Strings | Disabled button labels. Use {seconds} in the cooldown label. |
savedDesigns.removable | true | false | Global fallback for close/delete buttons; individual JSON entries can override it. |
savedDesigns.bg, itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Window and thumbnail states. |
savedDesigns.btnBg, btnBgOver, btnText, btnTextOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Save button states. |
savedDesigns.close, closeOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Delete icon states. |
savedDesigns.titleColor, titleBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Multiline title/date overlay colors. |
savedDesigns.titleSize | Finite number > 0 (CSS pixels) | Saved-design title/date font size. |
savedDesigns.inputBg, inputText, inputBorder, inputBorderFocus | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Saved-design title input states. |
Layers
Configure the layers panel, layer editing and the visual states of layer items and controls.
| Option | Type / values | Description |
|---|---|---|
layers.bg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Layers window and text-editor background. |
layers.canEdit | true | false | Allows layer names to be edited on double click. Text-layer content remains synchronized with canvas text. |
layers.itemBg, layers.itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Layer normal and selected/hover backgrounds. |
layers.icon, layers.iconOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Layer action normal and hover colors. |
Add Text
Configure text templates, default typography, object permissions, pricing and module appearance.
The demo text-template library is loaded from addText.json: './content/text.json'.
| Option | Type / values | Description |
|---|---|---|
addText.json | JSON URL string | JSON source string | literal text-library object | Text-template library. |
btn | Non-empty string | Add Text button label. |
price | Number ≥ 0 | currency-free numeric string | Default price assigned to newly added text. When provided, the text template JSON price overrides this value. |
removable | true | false | Default removal permission for text templates. |
colorPicker | true | false | Allows the custom color picker. When false, preset swatches remain available. |
colors | Array of #hex, rgb(a), hsl(a), named or transparent values | empty array | Default fill swatches for newly added text. A template-level colors array overrides this palette. |
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorder | Each value: true | false | Default permissions for text created from the module. |
font | Font-family string matching font.list or an installed system font | Default text family. |
fontWeight | 'normal' | 'bold' | numeric weight such as 400, 700, 900 | Text template font weight. For custom fonts, the value should match one of the weights registered in font.list. |
size | Finite number > 0 | Default font size. |
lineH | Finite number > 0 | Default line-height multiplier, for example 1.2. |
letter | Finite number | Default Fabric character spacing; negative, zero and positive values are accepted. |
curveType | 'normal' | 'curvedUp' | 'curvedDown' | 'oblique' | 'bridge' | Default text geometry. |
radius | Number from 0 to 300 | Default curved-up/down radius. |
curve | Number from -100 to 100 | Default oblique/bridge deformation. |
offset | Number from 0 to 100 | Default internal oblique/bridge offset. |
fill | #hex | rgb(a) | hsl(a) | named | transparent | empty string | Default text fill; an empty string requests no fill. |
stroke | #hex | rgb(a) | hsl(a) | named | transparent | null | empty string | Default text stroke. |
strokeW | Finite number ≥ 0 | Default stroke width; 0 disables the stroke. |
bg, priceColor, priceBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Window and price badge. |
btnBg, btnBgOver, btnText, btnTextOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Add Text button states. |
inputBg, inputText, inputBorder | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Live text-area styling. |
close, closeOver, itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Template close icon and thumbnail states. |
Add Images
Configure the image library and upload area, including defaults, permissions, pricing and visual states.
The demo image library is loaded from addImg.json: './content/images.json'.
| Option | Type / values | Description |
|---|---|---|
addImg.json | JSON URL string | JSON source string | literal image-library object | Initial image/SVG library. |
btn | Non-empty string | Browse button label. |
price | Number ≥ 0 | currency-free numeric string | Default price assigned to newly added media. When provided, the image library JSON price overrides this value. |
removable | true | false | Default removal permission for image-library entries. |
colorPicker | true | false | Allows the custom color picker. When false, preset swatches remain available. |
colors | Array of #hex, rgb(a), hsl(a), named or transparent values | empty array | Default tint/fill swatches for added PNG, JPG and SVG media. An image-level colors array overrides this palette. |
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorder | Each value: true | false | Default permissions for added media. |
bg, dropBg, dropBorder, dropColor | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Window, drop-area background, border and text colors. |
dropText | String, including an empty string | Text displayed inside the fixed drag/drop area. |
priceColor, priceBg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Price badge. |
btnBg, btnBgOver, btnText, btnTextOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Browse button states. |
close, closeOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Removable library-item close icon. |
itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Thumbnail holder and animated overlay. |
Add Shapes
Configure the shape library, default colors, permissions, pricing and thumbnail appearance.
The demo shapes library is loaded from addShapes.json: './content/shapes.json'.
| Option | Type / values | Description |
|---|---|---|
addShapes.json | JSON URL string | JSON source string | literal shape-library object | Shape library. Item order in JSON is display order. |
price | Number ≥ 0 | currency-free numeric string | Global fallback price for shapes. A positive per-shape price overrides it; 0 or an omitted value inherits it. |
removable | true | false | Default removal permission for shape-library entries. |
colorPicker | true | false | Allows the custom color picker. When false, preset swatches remain available. |
fill | #hex | rgb(a) | hsl(a) | named | transparent | empty string | Default canvas shape fill. |
colors | Array of #hex, rgb(a), hsl(a), named or transparent values | empty array | Default fill swatches for added shapes. A shape-level colors array overrides this palette. |
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorder | Each value: true | false | Default shape permissions. |
bg, itemFill, itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Window, preview-shape fill and thumbnail states. |
priceColor, priceBg, close, closeOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Price and removable button states. |
Artwork Library
Configure categorized artwork, search behavior, object defaults, pricing and library appearance.
The demo artwork library is loaded from artworkLibrary.json: './content/artwork_library.json'.
| Option | Type / values | Description |
|---|---|---|
artworkLibrary.json | JSON URL string | JSON source string | literal artwork-library object | Categories and artwork library. |
searchPlaceholder, allCategoriesLabel, notFoundText | Strings, including empty strings | Search and category UI labels. |
price | Number ≥ 0 | currency-free numeric string | Default price assigned to newly added artwork. When provided, the artwork JSON price overrides this value. |
removable | true | false | Default removal permission for artwork entries. |
colorPicker | true | false | Allows the custom color picker. When false, preset swatches remain available. |
colors | Array of #hex, rgb(a), hsl(a), named or transparent values | empty array | Default tint/fill swatches for added artwork. An artwork-level colors array overrides this palette. |
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorder | Each value: true | false | Default artwork permissions. |
bg, itemBg, itemBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Window and artwork-card colors. |
priceColor, priceBg, close, closeOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Price and removal button states. |
searchBg, searchText, searchBorder, searchBorderFocus | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Category search field. |
catBg, catBgOver, catText, catTextOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Category buttons. |
Canvas
Configure the canvas appearance, object controls, dimensions, zoom behavior and ruler styling.
| Option | Type / values | Description |
|---|---|---|
canvas.showDimensions | true | false | Shows rounded selected-object dimensions without covering canvas controls. |
dimenstionsBg, dimenstionsText | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Dimension badge colors. The historical spelling is supported. |
objBg, bg | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Selected-object control accent and canvas background. |
icon, iconOver, iconBg, iconBgOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Canvas move/rotate/resize/delete control states. |
zoomLevels | Array of finite numbers > 0, for example [1, 1.25, 1.5, 2] | Reference zoom levels; 1 is automatically included. |
zoomStep | Finite number > 0, typically 0.01–0.25 | Zoom slider and Space + wheel increment. |
toggleRuler | true | false | Shows the rulers when the designer starts. The Ruler action can still toggle them. |
rulerBg, rulerText, rulerTick, rulerTickMajor, rulerBorder | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Ruler panel, labels, minor/major ticks and border colors. |
Object toolbar
Configure the actions and editing panels shown for selected objects, including colors, transforms and text tools.
| Option | Type / values | Description |
|---|---|---|
toolbar.buttons | {label: string, button: 'color' | 'transform' | 'textFormat' | 'curvedText' | 'position' | 'reset' | 'duplicate' | 'delete'}[] | Main object actions and display order. |
toolbar.align | {label: string, button: 'top' | 'middle' | 'bottom' | 'left' | 'center' | 'right'}[] | Alignment actions and display order. |
toolbar.curve | {label: string, button: 'normal' | 'curvedUp' | 'curvedDown' | 'oblique' | 'bridge' | 'radius' | 'fontSize' | 'letterSpacing' | 'curve' | 'offset'}[] | Curved-text modes and slider labels. |
toolbar.color | {label: string, button: 'fill' | 'transparency' | 'shadow' | 'blur' | 'strokeColor' | 'strokeWidth' | 'fontFamily' | 'fontSize' | 'lineHeight' | 'letterSpacing' | 'offsetX' | 'offsetY'}[] | Color, shadow, text typography and stroke controls. |
toolbar.transform | {label: string, button: 'scaleX' | 'scaleY' | 'rotate' | 'skewX' | 'skewY' | 'flipHorizontal' | 'flipVertical'}[] | Transform controls and display order. |
objectToolbarMode | 'floating' | 'fixed' | Floating toolbar near the selected object or fixed toolbar integrated into the modules panel. toolbar.mode is also accepted. |
toggled | true | false | In fixed mode, automatically opens the first available editing panel when an object is selected. The order in toolbar.buttons determines which compatible panel opens first. |
maxW, textMaxW | Finite number > 0 (CSS pixels) | Normal and text-object toolbar maximum widths. |
maxScale | Finite number > 0 | Maximum scale value available in the toolbar. |
maxSkew | Finite number from 0 to 89 (degrees) | Positive and negative skew limit. |
defRadius | Number from 0 to 300 | Default curved-text radius. |
bg, icon, iconOver | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Toolbar window and primary icon colors. |
sliderBg, sliderBorder, sliderFill, sliderHandle, sliderInput, sliderHandleBorder | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | All object-toolbar sliders and inputs. |
back | String, including an empty string | Back button label in floating subwindows. |
secBg, secBgOver, secIcon, secIconOver, secBorder | #hex | rgb() | rgba() | hsl() | hsla() | named | transparent | Align, format, flip and other secondary button states. |
canResize: false hides scale controls, and canRotate: false hides rotation.Working with Colors
Colors are configured independently for the interface, product layers and module content. Every color option accepts browser-supported CSS colors such as hex, RGB, RGBA, HSL, HSLA, named colors and transparent. Use RGBA or transparent when opacity is required.
Interface theme
Theme each interface area through its own settings group. Update normal, hover and selected states together so the accent remains consistent across the action bar, modules, object toolbar, canvas controls, rulers and dialogs.
new FWDIPD({
actionBar: {
bg: ''#d62828'',
icon: ''#ffffff'',
iconOver: ''#ffe0e0''
},
modules: {
iconOver: ''#d62828'',
btnBgOver: ''rgba(214, 40, 40, .1)''
},
toolbar: {
iconOver: ''#d62828'',
sliderFill: ''#d62828'',
sliderHandleBorder: ''#d62828''
},
canvas: {
objBg: ''#d62828'',
rulerTick: ''#d62828''
}
});Only the properties you define are replaced. Unspecified color properties keep their defaults.
Content palettes
Text, Images, Shapes and Artwork can expose preset swatches through colors. Enable colorPicker when customers may also choose colors outside the preset palette.
addShapes: {
fill: ''#000000'',
colorPicker: true,
colors: [''#d62828'', ''#2f5f8f'', ''#111111'']
}A palette provides selectable choices. Its first color is not applied automatically. Individual templates and library items can define their own palette, which takes precedence over the module defaults for that item.
SVG and image colors
- SVG: editable fills remain sharp at every size. Multi-path SVG files can preserve their original colors while exposing configured choices.
- White PNG: works as an accurate tint mask and displays the selected color cleanly.
- Shaded PNG: tinting can preserve dark shading and texture, but the result depends on the source pixels.
- JPG: use mainly for photographs because recoloring affects the complete rectangular image.
Color changes are stored with the design element and reproduced in previews, saved designs and exports. The original source asset is not modified.
Color precedence
- The color saved on the current view element.
- The individual template or library-item color.
- The module default fill, tint or palette.
- The product or constructor fallback.
When color synchronization is enabled, matching product elements can share a customer color choice across views. Unrelated elements retain their own saved colors.
Editable Printing Box
The editable printing box is a product-setup tool for positioning and sizing the real customizable area directly on the canvas. Enable it when preparing a product, then export the product JSON after the box is correct.
options.printing_box. Its position and size use whole canvas pixels. print_width_mm and print_height_mm define the real production size and lock the box to the correct physical aspect ratio.
1. Define the physical print area
"options": {
"canvas_width": "922",
"canvas_height": "749",
"print_width_mm": "95",
"print_height_mm": "117",
"dpi": 300,
"bleed": 3,
"printing_box": {
"left": 179,
"top": 62,
"width": 518,
"height": 638
}
}The canvas values and printing_box geometry are editor pixels. The print_width_mm and print_height_mm values are the authoritative physical print size. The designer preserves their ratio when the box is loaded or resized.
2. Enable visual editing
Add these options to the main FWDIPD configuration:
boundingBoxEditable: true,
boundingBoxInputs: true,
boundingBoxColor: '#FF0000'boundingBoxEditable enables canvas selection and transform handles. boundingBoxInputs adds the floating X, Y, W and H fields. The ruler automatically displays canvas pixels while this setup mode is enabled.
3. Adjust and export
- Select: click the red dashed printing box. Its translucent fill and resize controls appear only while selected.
- Move: drag the selected box, use its X/Y inputs, or press an Arrow key. Shift + Arrow uses the configured large movement step.
- Resize: drag a resize control, change W/H, or use Ctrl/Cmd + Arrow. Add Shift for the large resize step.
- Center: when Snap To Center is active, the box snaps to the horizontal and vertical canvas center and displays the configured guides.
- Finish: click outside the canvas to deselect it, then use Product Export to save the updated printing-box values.
print_width_mm / print_height_mm. If the initial JSON ratio is incorrect, the designer retains the configured width and corrects the height.
boundingBoxMode and boundingBoxEditable have different jobs. The mode controls how added objects are constrained or clipped; the editable option controls whether the product administrator can modify the view's rectangular printing box.
Production Export and Unit Conversion
Production Export creates a print-ready file from the customizable area of a product. It crops the design to the printing box, adds bleed when required, and generates the final file at the configured physical size and DPI.
printing_box defines where the design is placed in the editor, while print_width_mm and print_height_mm define its real printed size. The designer handles the conversion automatically.
Setting up a print area
Start by asking the printer or product manufacturer for the real size of the area that can receive artwork.
- Enter the real print size. Set
print_width_mmandprint_height_mmin millimeters. - Position the printing box. Place it over the customizable area of the product image. Its X, Y, width and height use canvas pixels. Width and height are automatically constrained to the ratio defined by
print_width_mmandprint_height_mm. - Position the product artwork. Align the base image, SVG colors, shading and overlays around the printing box.
- Set DPI and bleed. A DPI above 0 controls physical raster resolution. DPI 0 keeps the printing box at its editor-pixel resolution. Bleed adds extra millimeters around every edge.
- Test the result. Run Production Export and confirm the crop and final file size before publishing the product.
Example: if the printer specifies a 95 × 117 mm printable area, enter those values and place a similarly shaped printing box over the product preview. You do not need to calculate the pixel-to-millimeter conversion yourself.
The root unit only controls how measurements are displayed in the editor. Normally keep unitScale: 1. Change it only when the complete product requires an additional measurement multiplier.
Setting the printing-box width and height
The physical print dimensions determine the shape of the printing box. The printing box itself is positioned and sized in whole canvas pixels, so its pixel width can be chosen to fit the product preview. Its pixel height must then be calculated from the physical ratio.
95 × 117 mm print area does not require a 95 × 117 px box. It only requires the same width-to-height ratio. The pixel box can be much larger to provide a comfortable editing area.
When choosing the pixel width
Choose a printing_box.width that visually covers the customizable area, then calculate its height:
printing_box.height = Math.round(
printing_box.width * print_height_mm / print_width_mm
);
When choosing the pixel height
If the height is easier to determine from the product preview, calculate the width instead:
printing_box.width = Math.round(
printing_box.height * print_width_mm / print_height_mm
);
| Physical print size | Chosen pixel dimension | Calculated pixel box |
|---|---|---|
180 × 100 mm | Width 580 px | 580 × 322 px |
95 × 117 mm | Width 518 px | 518 × 638 px |
100 × 100 mm | Width 400 px | 400 × 400 px |
"options": {
"canvas_width": "922",
"canvas_height": "749",
"print_width_mm": "95",
"print_height_mm": "117",
"printing_box": {
"left": 179,
"top": 62,
"width": 518,
"height": 638
}
}
- Width and height: control the printing-box size in canvas pixels.
- Left and top: position the finished box over the customizable part of the product.
- If the box does not fit: reduce the chosen pixel width or height and recalculate the other dimension. Do not distort one dimension independently.
- Whole-pixel rounding: a tiny ratio difference after rounding is normal and does not change the configured physical print size.
- Automatic correction: when JSON dimensions do not match, the designer keeps
printing_box.widthand recalculatesprinting_box.heighton load. - Editable box: canvas handles, keyboard resizing and W/H inputs preserve the same ratio automatically. While
boundingBoxEditable: true, both the ruler and bounds inputs display canvas pixels.
Canvas pixels and physical output size
| Value | Unit | Purpose |
|---|---|---|
canvas_width, canvas_height | Canvas pixels | Size of the complete editable stage for a view. |
printing_box.left, top | Canvas pixels | Position of the printable crop area inside the stage. |
printing_box.width, height | Canvas pixels | Size of the printable crop area inside the editor. |
Root unitScale | Positive multiplier | Optional product-wide multiplier applied after per-view calibration. Missing or invalid values fall back to 1. |
print_width_mm, print_height_mm | Millimeters | Authoritative physical size represented by the view's printing box. |
bleed | Millimeters per edge | Extra physical area added to every side. The view value falls back to the global constructor bleed setting when omitted. |
dpi | Pixels per inch or 0 | Controls raster resolution. Set 0 to export using the printing-box pixel dimensions without DPI scaling. |
Effective unit | mm, cm, inch, or px | The active product root value, falling back to the constructor setting. It controls measurement presentation and converted output metadata; production dimensions remain stored in millimeters. During editable printing-box setup, only the ruler is temporarily forced to pixels. |
print_width_mm / print_height_mm. When an existing JSON box has a different ratio, its width is retained and its height is corrected when the view loads. For example, 180 × 100 mm produces a 1.8 ratio, so a 580 px box width produces a rounded 322 px height. With boundingBoxEditable: true, dragging or editing W/H keeps the same ratio. With false, users cannot edit the box, but the ratio normalization still applies.
The printing box determines which part of the canvas is rendered. Its pixel dimensions and configured physical output establish the scale independently for each axis:
mmPerPixelX = print_width_mm / printing_box.width * unitScale;
mmPerPixelY = print_height_mm / printing_box.height * unitScale;
canvasWidthMm = canvas_width * mmPerPixelX;
canvasHeightMm = canvas_height * mmPerPixelY;
For example, the mug uses a 518 × 638 px printing box for a 95 × 117 mm print size. This produces approximately 0.183 mm/px on both axes. Setting unitScale: 2 doubles those physical measurements; unitScale: 1 leaves them unchanged.
Physical-size conversion formulas
There are exactly 25.4 millimeters in one inch. The renderer first converts all production values to millimeters and then calculates the final raster dimensions:
trimWidthPx = Math.round(outputWidthMm * dpi / 25.4);
trimHeightPx = Math.round(outputHeightMm * dpi / 25.4);
finalWidthPx = Math.round((outputWidthMm + bleedMm * 2) * dpi / 25.4);
finalHeightPx = Math.round((outputHeightMm + bleedMm * 2) * dpi / 25.4);
The selected display unit does not change the resulting pixel count. It only changes how the same physical measurement is presented:
centimeters = millimeters / 10;
inches = millimeters / 25.4;
// All three values describe the same physical width.
240 mm = 24 cm = 9.449 in;
PDF page dimensions are calculated in points after rasterization:
pdfWidthPoints = finalWidthPx / dpi * 72;
pdfHeightPoints = finalHeightPx / dpi * 72;
Printing-box crop and bleed
Bleed uses the same physical scale as the configured print output. Because this project stores production sizes in print_width_mm and print_height_mm, bleed is also measured in millimeters. Resolution order is runtime API, view JSON, global constructor, then 0. The renderer maps the physical bleed proportionally into each printing-box axis:
bleedCanvasX = bleedMm / print_width_mm * printing_box.width;
bleedCanvasY = bleedMm / print_height_mm * printing_box.height;
cropLeft = printing_box.left - bleedCanvasX;
cropTop = printing_box.top - bleedCanvasY;
cropWidth = printing_box.width + bleedCanvasX * 2;
cropHeight = printing_box.height + bleedCanvasY * 2;
Every exported object is cloned, moved relative to the expanded crop origin, and scaled into the final raster canvas. Object clip paths are transformed by the same values. excludeFromExport: true removes a layer from every download, while excludeFromProductionExport: true removes it only from print-ready production files.
false.
For objects using rectangular clipping, production export expands the clip to the bleed crop so available artwork can reach the exported image edges. Normal editor and preview rendering continue to use the printing-box trim boundary. Image-based bounding masks retain their original shape and include every source pixel whose alpha is greater than zero.
printing_box.width / printing_box.height aligned with print_width_mm / print_height_mm. Runtime outputWidth/outputHeight overrides should still use that same ratio.
Worked 300-DPI example
The included mug JSON uses a ratio-corrected 518 × 638 px box representing 95 × 117 mm, with no bleed:
{
"unit": "cm",
"unitScale": 1,
"views": [{
"options": {
"canvas_width": "922",
"canvas_height": "749",
"print_width_mm": "95",
"print_height_mm": "117",
"dpi": 300,
"bleed": 0,
"printing_box": {
"left": 179,
"top": 62,
"width": 518,
"height": 638
}
}
}]
}
The physical output is 95 × 117 mm. At 300 DPI, the generated raster dimensions are:
bleedCanvasX = 0 / 95 * 518; // 0 canvas px per edge
bleedCanvasY = 0 / 117 * 638; // 0 canvas px per edge
width = Math.round(95 * 300 / 25.4); // 1122 px
height = Math.round(117 * 300 / 25.4); // 1382 px
With zero bleed, the source crop remains exactly left: 179, top: 62, 518 × 638 px. The root display unit is cm, but the authoritative production values remain in millimeters.
API, overrides, and generated files
The production API accepts PNG, JPG, or PDF. By default it exports every view. Use currentViewOnly, viewIndex, or viewIndexes to select specific views.
// Export every view using its product JSON production settings.
await fwdipd0.productionExport('png');
// Export only the active view.
await fwdipd0.productionExport('jpg', {
currentViewOnly: true,
quality: 0.92,
fileName: 'shirt-front-production.jpg'
});
// Deliberately override the configured physical size for this export only.
// Keep the override ratio aligned with the printing box.
await fwdipd0.productionExport('pdf', {
viewIndex: 0,
outputWidth: 240, // millimeters
outputHeight: 400, // millimeters
bleed: 3, // millimeters per edge
dpi: 300,
outputUnit: 'cm'
});
- A single PNG or JPG view downloads as one image.
- Multiple PNG or JPG views are packaged into one ZIP file.
- PDF combines the rendered production views into one PDF document.
jpegis normalized tojpg.- Production SVG is not supported because production output is rasterized at the configured DPI.
- Without API overrides, production uses the view's configured
print_width_mmandprint_height_mm, calibrated against its printing box and multiplied byunitScale. - Runtime
outputWidth,outputHeight, andbleedare interpreted as canonical millimeters. Runtime bleed overrides view JSON, which overrides the global fallback.unit/outputUnitcontrols converted presentation metadata.
Production validation checklist
- Define
canvas_widthandcanvas_heightin pixels for every view. - Define an accurate
printing_boxinside the canvas. - Set the real printing size in
print_width_mmandprint_height_mm. - Keep the output aspect ratio equal to the printing-box aspect ratio.
- Set one positive root
unitScaleonly when an additional multiplier is needed; omitted values default to1. - Product export preserves the configured physical output values instead of replacing them with printing-box pixels.
- If API size overrides are used, keep their aspect ratio equal to the printing-box ratio.
- Use a suitable DPI, typically 300 for high-quality print output.
- Confirm with the print provider whether bleed is required and how many millimeters to use.
- Use sufficiently large source images; increasing DPI cannot restore detail missing from a low-resolution asset.
- Run a production export and inspect its pixel dimensions before delivering the product configuration.
productionExport() renders print-ready PNG, JPG, or PDF files. export() creates an editable ZIP containing product.json and referenced product assets.
Product JSON
A product is portable data: product metadata, one or more views, elements and per-view production geometry. Asset paths are resolved relative to the JSON file that declares the product.
Product root
{
"title": "Men Standard",
"thumbnail": "preview-front.png",
"basePrice": 20,
"startAtView": 0,
"unit": "mm",
"unitScale": 1,
"views": [
{
"title": "Front",
"thumbnail": "preview-front.png",
"elements": [],
"options": {}
}
]
}
| Property | Type / values | Description |
|---|---|---|
title | Non-empty string | Product title shown in Products and used for filenames. |
thumbnail | Relative or absolute image-URL string | Product-module preview, resolved relative to this JSON. |
basePrice | Number ≥ 0 | currency-free numeric string | Global product base price. Do not include the currency symbol. Defaults to 0. |
startAtView | Integer ≥ 0 | exact view-title string | Initial view. Defaults to the first view. |
unit | 'mm' | 'cm' | 'inch' | 'px' | Product working unit used by measurements and output metadata. When omitted, the constructor unit setting is used. The ruler displays pixels whenever boundingBoxEditable is enabled. |
unitScale | Finite number > 0 | Optional product-wide multiplier applied after each view derives its scale from output size and printing-box pixels. Defaults to 1. |
views | Array of {title, thumbnail, elements, options} objects | Ordered product sides/views. |
View and production options
"options": {
"canvas_width": "600",
"canvas_height": "650",
"print_width_mm": "240",
"print_height_mm": "400",
"dpi": 300,
"bleed": 3,
"printing_box": {
"left": 178,
"top": 139,
"width": 240,
"height": 400
}
}
| Property | Type / supported values | Description |
|---|---|---|
canvas_width, canvas_height | Number > 0 | positive numeric string, in editor pixels | Actual design-stage size for this view. |
printing_box.left, printing_box.top | Finite number | numeric string, in editor pixels | Printing-box position inside the canvas. |
printing_box.width, printing_box.height | Number > 0 | positive numeric string, in whole editor pixels | Printing-box crop dimensions. Their ratio is automatically normalized to print_width_mm / print_height_mm. |
print_width_mm, print_height_mm | Number > 0 | positive numeric string, in millimeters | Authoritative physical production size represented by the printing box. Legacy output_width/output_height values are still accepted when loading. |
dpi | Finite number ≥ 0 | Production raster density. A value of 0 uses the printing-box pixel dimensions. |
bleed | Finite number ≥ 0, in millimeters | Per-view physical bleed override. When omitted, the global constructor bleed value is used. |
unitScale. This lets a large editor canvas represent a much smaller real product accurately.
Element schema
{
"title": "Logo",
"source": "logo.svg",
"type": "image",
"parameters": {
"left": 300,
"top": 325,
"originX": "center",
"originY": "center",
"fill": "#3858e9",
"colors": ["#3858e9", "#B65A3C", "#D8A24A"],
"colorPicker": true,
"showInLayers": true,
"canDuplicate": true,
"canReset": true,
"canMove": true,
"canRotate": true,
"canResize": true,
"canDelete": true,
"canReorder": true,
"scaleX": 1,
"scaleY": 1,
"minScaleLimit": 0.04,
"lockUniScaling": true,
"angle": 0,
"price": 0,
"boundingBoxMode": "clipping",
"opacity": 1,
"locked": false,
"alwaysOnTop": false,
"excludeFromExport": false,
"excludeFromProductionExport": true,
"visible": true
}
}
| Parameter group | Properties and supported values | Behavior |
|---|---|---|
| Position/origin | left, top: finite numbers; originX: 'left' | 'center' | 'right'; originY: 'top' | 'center' | 'bottom'; autoCenter: true | false | Canvas position and transform origin. Center origins are recommended. |
| Transform | scaleX, scaleY, minScaleLimit: numbers > 0; angle, skewX, skewY: finite degree values; lockUniScaling, flipX, flipY: true | false | Initial transform and limits. |
| Permissions | canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorder: each true | false | Controls both behavior and visible UI actions. |
| Layer state | showInLayers, locked, visible, alwaysOnTop, autoSelect: each true | false | Layer-list visibility, editing lock, canvas visibility, permanent visual top order and initial selection. |
| Appearance | fill: #hex | rgb(a) | hsl(a) | named | transparent | empty string; colors, svgFill: arrays of those color values; colorPicker: true | false; opacity: 0–1; filter: filter name/object or array; shadow: {color, blur, offsetX, offsetY} | Color, transparency, filters and shadow. |
| Product behavior | price: number ≥ 0 | currency-free numeric string; syncInAllViews, excludeFromExport, excludeFromProductionExport: true | false; boundingBoxMode: 'none' | 'inside' | 'clipping' | object-title string | Price, cross-view synchronization, bounds, all-export exclusion and production-only exclusion. |
| Loading/rendering | scaleMode: 'fit' | 'cover' | 'stretch'; mimeType: MIME string such as 'image/svg+xml' | Media fitting and metadata used by module-added content. |
shadow accepts {color, blur, offsetX, offsetY}. Blur 0 removes the visible shadow and disables offsets while preserving the chosen shadow color for later use.
filter accepts one filter or a list. Supported important filters include grayscale, sepia, invert, brightness, contrast, saturation, vibrance, blur, pixelate and noise.
can* property set to false can still be selected when locked is false. Set locked: true only when selection and editing must be blocked.Color palettes and SVG fills
fillis the initial single fill/tint.- Module-level
colorsdefine the default swatches for Text, Images, Shapes or Artwork. - Item-level
colors, either directly on the item or insideparameters, replace the module palette for that item. - An explicit empty
colors: []removes preset swatches from that item. svgFillstores one color per detected SVG fill group for multi-fill SVG editing.colorPicker: falsekeeps the Color section and swatches but prevents opening the custom picker.- An empty
fillwith an emptycolorsarray leaves a PNG/SVG in its original appearance. - The transparent/reset swatch restores original image pixels or original SVG fill colors.
"fill": "",
"colors": ["#3858e9", "#B65A3C", "#D8A24A"],
"svgFill": ["#3c33e0", "#818cf8", "#0d277a", "#120e69"],
"colorPicker": true
Text parameters
Text uses source as its editable content. This keeps the element schema consistent and avoids a separate top-level text property.
{
"title": "Personalized name",
"source": "YOUR TEXT",
"type": "text",
"parameters": {
"fontFamily": "Roboto",
"fontSize": 42,
"fontWeight": 700,
"fontStyle": "normal",
"underline": false,
"textAlign": "center",
"fill": "#3858e9",
"strokeColor": "#000000",
"strokeWidth": 0,
"lineHeight": 1.2,
"letterSpacing": 0,
"curvable": true,
"curvedType": "normal",
"curveRadius": 80,
"curve": 0,
"curveOffset": 0,
"maxLines": 0,
"minFontSize": 1,
"maxFontSize": 1000,
"textTransform": "none",
"widthFontSize": false
}
}
| Property | Values | Description |
|---|---|---|
curvedType | 'normal' | 'curvedUp' | 'curvedDown' | 'oblique' | 'bridge' | Text geometry mode. |
curveRadius | Number from 0 to 300 | Arc radius for curved up/down. Smaller values create a stronger curve. |
curve | Number from -100 to 100 | Oblique/bridge deformation strength. |
curveOffset | Number from 0 to 100 | Internal vertical deformation offset without changing object position. |
letterSpacing | Finite number; negative, zero or positive | Fabric character spacing, synchronized between Format Text and Curved Text. |
maxLines | Integer ≥ 0 | 0 means unlimited lines; otherwise limits multiline input. |
textTransform | 'none' | 'uppercase' | 'lowercase' | Rendered character transform while preserving editable source text. |
widthFontSize | true | false | finite number > 0 | When enabled, font size is automatically constrained to the stored target width. |
Bounding modes
none: no clipping or inside constraint.inside: keep the object's transformed bounds inside the current view printing box without masking it.clipping: clip the object to the current view printing box.- An element title such as
Overlay: use that view element's visible SVG shape or PNG alpha as a clipping mask.
SVG targets use their vector alpha. Transparent PNG targets use image alpha; transparent areas clip while partially/fully opaque pixels preserve the edited object at full visual opacity.
When printing_box exists, the red dotted guide always displays its exact rectangle. Object-title modes affect the clipping target only.
Library JSON
parameters override the module defaults. Values omitted from the item inherit the corresponding addText, addImg, addShapes or artworkLibrary setting.Image, text, shape, artwork and artwork-category entries can define an optional itemBg CSS color. It changes only that entry's thumbnail background; it does not affect the canvas object, overlay, price badge or close button.
Images JSON
{
"removable": true,
"images": [
{
"type": "svg",
"name": "Mushroom",
"src": "./content/svg/mushroom.svg",
"itemBg": "#e2e2e2",
"price": 9.99,
"removable": false,
"parameters": {
"canMove": true,
"canDelete": true,
"colors": ["#3858e9", "#B65A3C"]
}
}
]
}
The browser upload list is also maintained in memory. Duplicate detection uses src; no separate key is required. Set an item's optional itemBg CSS color to override the global thumbnail background, which is useful for displaying white artwork.
Text templates JSON
{
"removable": true,
"texts": [
{
"text": "YOUR\nTEXT",
"parameters": {
"fontFamily": "MDNichrome",
"fontSize": 42,
"fontWeight": 700,
"fill": "#3858e9",
"colors": ["#3858e9", "#B65A3C", "#D8A24A"],
"textAlign": "center",
"curvedType": "bridge",
"curve": 45,
"curveOffset": 50,
"price": 10
}
}
]
}
Template thumbnails are rendered from the same text parameters used by the canvas, including custom fonts, multiple lines, curved up/down, oblique and bridge modes.
Shapes JSON
{
"removable": true,
"shapes": [
{
"label": "Circle",
"button": "circle",
"svg": "<svg viewBox='0 0 100 100'><circle cx='50' cy='50' r='38' fill='currentColor'/></svg>",
"price": 4,
"parameters": {
"fill": "#3858e9",
"colors": ["#3858e9", "#B65A3C", "#D8A24A"]
}
}
]
}
Use inline svg or a source URL. Inline paths should use currentColor so the configured shape fill and color toolbar can update them.
Each shape can define a currency-free, non-negative price directly on the shape or inside parameters. A value greater than 0 is used for that shape. A missing value or 0 inherits addShapes.price. The global currency, addShapes.priceColor and addShapes.priceBg control its thumbnail badge.
Artwork Library JSON
{
"search": true,
"categories": [
{
"label": "Animals",
"button": "animals",
"removable": false,
"search": ["animals", "wildlife", "pets"]
}
],
"artworks": [
{
"label": "Panda",
"button": "animals_panda",
"category": "animals",
"src": "./artwork_library/animals/panda.svg",
"price": 0,
"search": ["panda", "animal", "bear"],
"parameters": {
"colors": ["#3858e9", "#B65A3C", "#D8A24A"]
}
}
]
}
The main window shows category thumbnails first. Opening a category reveals its artwork, back button and search field. Category removable controls removal for artwork in that category unless an item overrides it.
Saved designs JSON
{
"removable": true,
"designs": []
}
Each runtime design contains id, title, createdAt, productIndex, productTitle, productBasePath, currentViewIndex, thumbnail and a complete productData snapshot.
Important Workflows
Preview download
download() renders the current visual product. It supports PNG, JPG, SVG and PDF and can include the current view or all views. This is intended for customer previews and normal downloads.
Product ZIP export
export() synchronizes the editable printing box, serializes the live product state, removes deprecated/internal properties, respects excludeFromExport, gathers only assets referenced by product elements, and downloads one ZIP containing product.json plus those assets.
Module library JSON and unused Add Images media are not included. Product root basePrice and startAtView are always exported with safe defaults.
Saved designs
Saving creates an in-memory snapshot and dispatches an event containing everything required for database persistence. No localStorage is used. Reloading the page starts from the configured saved-design JSON unless your application supplies saved records again.
Keyboard Shortcuts
| Shortcut | Requirement | Action |
|---|---|---|
| Arrow keys | Movable object selected | Move by keuboardMoveNudgeAmmount. |
| Shift + Arrow keys | Movable object selected | Large movement. |
| Arrow keys | Editable printing box selected | Move the printing box in whole-pixel steps. |
| Ctrl/Cmd + Arrow keys | Editable printing box selected | Resize by the configured normal movement step while preserving the physical print ratio. Up/Right enlarge; Down/Left shrink. |
| Ctrl/Cmd + Shift + Arrow keys | Editable printing box selected | Ratio-locked resize using the configured large movement step. |
| Alt + Left / Right | Rotatable object selected | Rotate by the normal configured step. |
| Shift + Alt + Left / Right | Rotatable object selected | Large rotation step. |
| Ctrl/Cmd + Up / Down | Resizable object selected | Uniform scale up/down. |
| Ctrl/Cmd + Left / Right | Resizable object selected | Scale X down/up. |
| Ctrl/Cmd + Shift + Up / Down | Resizable object selected | Scale Y up/down. |
| Delete / Backspace | Deletable object selected | Request object deletion. |
| Ctrl/Cmd + D | Duplicable object selected | Duplicate object. |
| Ctrl/Cmd + Z | History available | Undo. |
| Ctrl/Cmd + Y | Redo available | Redo. |
| Ctrl/Cmd + Shift + Z | Redo available | Redo. |
| Escape | Any editor mode | Close picker/toolbar mode and deselect the object. |
| Shift while rotating | Canvas rotate handle | Snap rotation in 90-degree increments. |
| Space + drag | Pointer inside editor and ruler visible | Temporarily disable object interaction and pan the zoomed canvas. |
| Space + mouse wheel | Pointer inside editor and ruler visible | Zoom the canvas. |
Methods
Every instance is available under its configured ID, for example window.designer0.
download
await designer0.download(format = 'png', options = {})
Downloads normal rendered views. Formats: png, jpg/jpeg, svg, pdf.
await designer0.download('png', {currentViewOnly: true});
await designer0.download('pdf', {currentViewOnly: false, fileName: 'customer-design.pdf'});productionExport
await designer0.productionExport(format = 'png', options = {})
Downloads print-ready cropped output. Formats: PNG, JPG and PDF. Options can include currentViewOnly, viewIndex, fileName, dpi, bleed, outputWidth, outputHeight and unit/outputUnit. Runtime bleed is in millimeters and overrides both the view JSON and global fallback.
await designer0.productionExport('png', {
currentViewOnly: true,
dpi: 300,
bleed: 3,
unit: 'mm'
});await designer0.print(options = {})
Renders product previews into an isolated print document and opens the browser's normal print dialog. The current view is printed by default; pass {currentViewOnly: false} for all views.
export
await designer0.export(options = {})
Downloads the editable product JSON and referenced assets as a ZIP. Options: fileName for the ZIP and productFileName for the JSON inside it. Resolves to {productData, assets, blob} or null on error.
saveDesign
designer0.saveDesign(title = '')
Creates an in-memory saved-design snapshot, refreshes all saved-design windows and dispatches FWDIPD.SAVED_DESIGN_CREATED.
Product and view methods
| Method | Returns | Description |
|---|---|---|
await loadProductByIndex(index, forceReload) | Promise | Loads a product by numeric index. With forceReload, restores original product data. |
await loadProductView(index) | Promise | Loads a specific view and resets view history. |
await goToNextView() | Promise | Moves to the next available view. |
await goToPrevView() | Promise | Moves to the previous available view. |
await resetCurrentProduct() | Promise | Restores the current product's initial state directly. |
await requestResetCurrentProduct() | Promise | Uses the configured reset confirmation before resetting. |
await showPreviewWindow() | Promise | Renders and opens the full-browser all-view preview. |
showSavedDesignsLightbox() | void | Opens the independent full-browser saved-design window. |
showLightbox() | void | Opens an instance configured with display: 'lightbox'. The first call initializes it; later calls reuse its existing products, edits and history. |
hideLightbox() | void | Hides a lightbox instance without destroying or reinitializing the editor. |
showInfoWindow(text) | void | Shows a message in the shared dialog window. |
undo / redo
await designer0.undo() / await designer0.redo()
Moves through the current view's history. Slider and color-picker drags commit one history entry when released rather than one entry for every pointer movement.
getCurrentPrintingBoxInfo
designer0.getCurrentPrintingBoxInfo(viewIndex?)
Returns debugging/integration data for a view:
{
viewIndex: 0,
viewTitle: 'Front',
unitScale: 1,
millimetersPerPixel: {x: 1, y: 1},
canvasPx: {width: 600, height: 650},
printingBoxPx: {left: 178, top: 139, width: 240, height: 400},
output: {unit: 'mm', width: 240, height: 400},
sourceOutput: {unit: 'mm', width: 240, height: 400}
}destroy
designer0.destroy()
Removes listeners, timers, dialogs, responsive windows, color pickers, Fabric canvas resources, component references, the global instance and all generated DOM. In normal embedded modes it also removes the configured parent holder; in lightbox mode it removes the generated launch button and overlay.
Events
Register events on the instance with addEventListener. Event constants are available on the global FWDIPD class after initialization.
designer0.addEventListener(FWDIPD.SAVED_DESIGN_CREATED, function(event){
console.log(event.design);
// Send event.design to your database/API.
});
designer0.addEventListener(FWDIPD.MODULE_ITEM_REMOVED, function(event){
console.log(event.section, event.type, event.item || event.media);
});
designer0.addEventListener(FWDIPD.PRICE_CHANGED, function(event){
console.log(event.total);
});
designer0.addEventListener(FWDIPD.DONE, function(event){
console.log(event.total);
});FWDIPD.SAVED_DESIGN_CREATED
'savedDesignCreated'
Dispatched after a design snapshot is created. Payload: design, savedDesign, id, title, createdAt, productIndex, productTitle, productBasePath, currentViewIndex, thumbnail and productData.
FWDIPD.MODULE_ITEM_REMOVED
'moduleItemRemoved'
Dispatched when a removable Text, Image, Shape or Artwork Library item/category is deleted. Payload always includes section and type, plus the relevant item/media/category data.
FWDIPD.PRICE_CHANGED
'priceChanged'
Dispatched when the product total changes. The total payload contains the current base price plus all priced design elements.
FWDIPD.DONE
'done'
Dispatched when the Done action is clicked. The total payload contains the current product total and can be used by storefront integrations.