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.

Important: run the project through an HTTP or HTTPS server. Loading the page with 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 fill for a single-color SVG and svgFill when 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.
Practical rule: choose SVG for artwork whose colors customers can change, PNG for transparent raster content, and JPG for ordinary photographs. Always test the final asset with the intended color and production-export settings.

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>
Keep the folder structure intact: product JSON, thumbnails, product assets, library JSON and fonts are loaded through relative URLs. If a folder is moved, update the corresponding paths in the settings and JSON files.

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.

Value notation: alternatives separated with | 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.

OptionType / valuesDescription
idNon-empty string (required)Unique global instance name. instance is also accepted.
productJSON URL string | literal product object | array containing eitherOne product source or an ordered list of product sources.
productIndexInteger ≥ 0 | exact product-title stringInitial product index or title. The legacy alias prodcutIndex is accepted.
basePriceNumber ≥ 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.
startAtViewInteger ≥ 0 | exact view-title stringFallback 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.
parentNon-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, resizeWFinite number > 0 (CSS pixels) | percentage string in lightbox modeMaximum editor width and width at which automatic scaling starts. Lightbox values such as '90%' are relative to browser width.
maxH, minHFinite number > 0 (CSS pixels) | percentage string in lightbox modeMaximum and minimum editor heights. Lightbox values such as '90%' are relative to browser height.
canvasW, canvasHFinite number > 0 (canvas pixels)Fallback canvas size when a view does not define canvas_width/canvas_height.
initVisibletrue | falseWhen true, initialization waits until the editor enters the viewport.
autoScaletrue | falseScales 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.
bleedFinite number ≥ 0, in millimetersGlobal 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.
rulerFixedtrue | falseStarts the ruler visible. The Ruler action can still hide it.
currencyString, for example '$', '€' or 'USD'Currency symbol or code used for base, layer and library prices.
bg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentMain editor background.
dropShadowValid CSS box-shadow string | 'none'Outer editor shadow.

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'
}
OptionType / valuesDescription
labelNon-empty stringText displayed in the generated launch button. Defaults to 'Customize'.
bgCSS colorBackground covering the browser while the lightbox is open.
btnBg, btnBgOverCSS colorCustomize button background in its normal and hover states.
btnText, btnTextOverCSS colorCustomize button text in its normal and hover states.
closeW, closeHFinite number >= 24 (CSS pixels)Close-button width and height.
closeBg, closeBgOverCSS colorClose-button background in its normal and hover states.
closeIcon, closeIconOverCSS colorClose icon in its normal and hover states.

Bounds and snapping

Control object boundaries, clipping, editable printing boxes and center-snapping behavior.

OptionType / valuesDescription
boundingBoxMode'none', 'inside', 'clipping', an object title such as 'Bounding Box', or an array of these valuesFallback 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 | transparentPrinting-box guide and editable bounding-box color.
showPrintingBoxtrue | falseShows the dashed printing-box guide. Hiding it does not change clipping, stored geometry or production export.
boundingBoxEditabletrue | falseControls 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.
boundingBoxInputstrue | falseShows 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 | transparentBounding-box input panel background and text.
boundingBoxInputsFieldBg, boundingBoxInputsBorder, boundingBoxInputsBorderFocus#hex | rgb() | rgba() | hsl() | hsla() | named | transparentBounding-box field background, normal border and focused border.
toggleSnapToCentertrue | falseInitial global center-snapping state. The action bar toggle can change it at runtime.
snapColor#hex | rgb() | rgba() | hsl() | hsla() | named | transparentVertical and horizontal snap-guide color.
snapThresholdFinite number ≥ 0 (canvas pixels)Distance from center at which objects and editable bounds snap.

Supported boundingBoxMode values

ValueBehavior
noneNo boundary restriction or clipping is applied. The object can be moved and rendered anywhere on the canvas.
insideUses the current view's rectangular printing_box as a movement boundary and keeps the object's transformed bounds inside it. Content is not masked.
clippingUses 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 OverlayFinds 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.
Guide precedence: when the active view defines 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']
Fallback: if the current product has no corresponding non-empty array entry, the first non-empty mode in the array is used. If no usable mode is supplied, the default is clipping.

Keyboard settings

Enable keyboard controls and configure movement, rotation and scaling increments.

OptionType / valuesDescription
addKeyboardSupporttrue | falseEnables editor shortcuts. Transform shortcuts are ignored when no editable object is selected.
keuboardMoveNudgeAmmountFinite number ≥ 0 (pixels)Arrow-key movement. The misspelled key is retained for compatibility.
keyboardMoveNudgeLargeAmmountFinite number ≥ 0 (pixels)Shift + Arrow movement.
keyboardRotateAmmountFinite number ≥ 0 (degrees)Alt + Left/Right rotation step.
keyboardRotateLargeAmmountFinite number ≥ 0 (degrees)Shift + Alt + Left/Right rotation step.
keyboardScaleAmmountFinite number > 0, typically 0.001–0.1Normal keyboard scale increment.
keyboardScaleLargeAmmountFinite number > 0, typically 0.01–1Large keyboard scale increment.

Loader and fonts

Customize the loading screen and define the system, web and custom fonts available for text.

Group / optionType / valuesDescription
loader.textString, including an empty stringText shown while product assets and fonts load.
loader.bg, loader.iconBg, loader.icon#hex | rgb() | rgba() | hsl() | hsla() | named | transparentLoader overlay, icon background and icon color.
font.defFont-family string matching a configured or installed fontDefault 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'}
            ]
        }
    ]
}
Font loading: configured web and custom fonts are prepared before editing so each dropdown item can be previewed in its actual family. Keep the list intentional; hundreds of remote fonts will increase startup time.

Dialog settings

Customize confirmation, error and information dialogs, including their content, colors and buttons.

OptionType / valuesDescription
dialog.okNon-empty stringDefault acknowledgement button label.
dialog.overlay, dialog.bg, dialog.text#hex | rgb() | rgba() | hsl() | hsla() | named | transparentFull overlay, dialog panel and content text colors.
dialog.btn{bg, bgOver, text, textOver}; each: #hex | rgb(a) | hsl(a) | named | transparentPrimary dialog button states.
dialog.close{icon, iconOver}; each: #hex | rgb(a) | hsl(a) | named | transparentClose-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.

OptionType / valuesDescription
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 | transparentAction bar background.
actionBar.icon, actionBar.iconOver, actionBar.iconDisabled#hex | rgb() | rgba() | hsl() | hsla() | named | transparentNormal, hover and disabled button colors.
actionBar.toolTip.bg, actionBar.toolTip.text#hex | rgb() | rgba() | hsl() | hsla() | named | transparentDocument-level tooltip colors.
actionBar.leftList, actionBar.rightListtrue | falseForces a File/More dropdown. Even when false, a side automatically becomes a list if its buttons do not fit.
actionBar.leftlistLabel, actionBar.rightlistLabelString, including an empty stringLabels next to the left menu and right more icons.
actionBar.leftListBg, actionBar.rightListBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentDropdown window backgrounds.
actionBar.leftListIcon, actionBar.leftListIconOver, actionBar.rightListIcon, actionBar.rightListIconOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentDropdown trigger and item colors.
actionBar.leftListBorder, actionBar.rightListBorder#hex | rgb() | rgba() | hsl() | hsla() | named | transparentDropdown 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 / optionType / valuesDescription
download.title, download.textStrings, including an empty stringDownload dialog title and introduction.
download.scope'all' | 'current'Initially selected view scope.
download.all, download.currentNon-empty stringsScope button labels.
download.maxWFinite number > 0 (CSS pixels)Maximum download dialog width.
download.bg, download.bgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentFormat/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 | transparentFull-browser preview overlay.
preview.title, preview.itemText#hex | rgb() | rgba() | hsl() | hsla() | named | transparentPreview title and view label colors.
preview.itemBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentView preview card background.
preview.close, preview.closeOver, preview.scrollbar#hex | rgb() | rgba() | hsl() | hsla() | named | transparentClose icon and responsive scrollbar colors.

Views

Configure the navigation used to switch between product views, including its position, colors and thumbnail grid.

OptionType / valuesDescription
views.pos'topLeft' | 'topCenter' | 'topRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight'View navigation position.
views.bg, views.border#hex | rgb() | rgba() | hsl() | hsla() | named | transparentNavigation background and button border.
views.icon, views.iconOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentNormal and hover icon colors.
views.nav.maxW, views.nav.hFinite number > 0 (CSS pixels)Navigation maximum width and height.
views.nav.bottomGap, topGap, sideGapFinite number ≥ 0 (CSS pixels)Navigation offsets.
views.grid.bg, itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentFull 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.

OptionType / valuesDescription
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.allowToggletrue | falseAllows the active module button to show/hide its content window.
modules.toggledtrue | falseInitial module content visibility.
modules.bg, modules.border, modules.panelBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentBar, shared border and content panel backgrounds.
modules.icon, modules.iconOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentModule icon and label normal/hover colors.
modules.btnBg, modules.btnBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentModule 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 / optionType / valuesDescription
products.bg, itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentProducts window and preview-card colors.
products.titleColor, titleBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentProduct title text and strip background.
products.titleSizeFinite number > 0 (CSS pixels)Product-title font size.
products.priceColor, priceBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentOptional price badge colors.
products.btnBg, btnBgOver, btnText, btnTextOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentShared product action button states.
products.close, closeOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentOptional item close button states.
savedDesigns.jsonJSON URL string | JSON source string | literal saved-designs objectInitial saved-design collection. Runtime saves stay in memory and are dispatched for server persistence.
savedDesigns.inputPlaceholder, btnStrings, including an empty placeholderOptional title placeholder and Save Design label.
savedDesigns.canSavetrue | falseSet this from your authentication state. When false, saving is disabled and loginText is shown.
savedDesigns.cooldownSecondsInteger ≥ 0Seconds before another design can be saved. The default is 10.
savedDesigns.loginText, disabledTextStringsDisabled button labels. Use {seconds} in the cooldown label.
savedDesigns.removabletrue | falseGlobal fallback for close/delete buttons; individual JSON entries can override it.
savedDesigns.bg, itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentWindow and thumbnail states.
savedDesigns.btnBg, btnBgOver, btnText, btnTextOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentSave button states.
savedDesigns.close, closeOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentDelete icon states.
savedDesigns.titleColor, titleBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentMultiline title/date overlay colors.
savedDesigns.titleSizeFinite number > 0 (CSS pixels)Saved-design title/date font size.
savedDesigns.inputBg, inputText, inputBorder, inputBorderFocus#hex | rgb() | rgba() | hsl() | hsla() | named | transparentSaved-design title input states.

Layers

Configure the layers panel, layer editing and the visual states of layer items and controls.

OptionType / valuesDescription
layers.bg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentLayers window and text-editor background.
layers.canEdittrue | falseAllows 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 | transparentLayer normal and selected/hover backgrounds.
layers.icon, layers.iconOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentLayer 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'.

OptionType / valuesDescription
addText.jsonJSON URL string | JSON source string | literal text-library objectText-template library.
btnNon-empty stringAdd Text button label.
priceNumber ≥ 0 | currency-free numeric stringDefault price assigned to newly added text. When provided, the text template JSON price overrides this value.
removabletrue | falseDefault removal permission for text templates.
colorPickertrue | falseAllows the custom color picker. When false, preset swatches remain available.
colorsArray of #hex, rgb(a), hsl(a), named or transparent values | empty arrayDefault fill swatches for newly added text. A template-level colors array overrides this palette.
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorderEach value: true | falseDefault permissions for text created from the module.
fontFont-family string matching font.list or an installed system fontDefault text family.
fontWeight'normal' | 'bold' | numeric weight such as 400, 700, 900Text template font weight. For custom fonts, the value should match one of the weights registered in font.list.
sizeFinite number > 0Default font size.
lineHFinite number > 0Default line-height multiplier, for example 1.2.
letterFinite numberDefault Fabric character spacing; negative, zero and positive values are accepted.
curveType'normal' | 'curvedUp' | 'curvedDown' | 'oblique' | 'bridge'Default text geometry.
radiusNumber from 0 to 300Default curved-up/down radius.
curveNumber from -100 to 100Default oblique/bridge deformation.
offsetNumber from 0 to 100Default internal oblique/bridge offset.
fill#hex | rgb(a) | hsl(a) | named | transparent | empty stringDefault text fill; an empty string requests no fill.
stroke#hex | rgb(a) | hsl(a) | named | transparent | null | empty stringDefault text stroke.
strokeWFinite number ≥ 0Default stroke width; 0 disables the stroke.
bg, priceColor, priceBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentWindow and price badge.
btnBg, btnBgOver, btnText, btnTextOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentAdd Text button states.
inputBg, inputText, inputBorder#hex | rgb() | rgba() | hsl() | hsla() | named | transparentLive text-area styling.
close, closeOver, itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentTemplate 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'.

OptionType / valuesDescription
addImg.jsonJSON URL string | JSON source string | literal image-library objectInitial image/SVG library.
btnNon-empty stringBrowse button label.
priceNumber ≥ 0 | currency-free numeric stringDefault price assigned to newly added media. When provided, the image library JSON price overrides this value.
removabletrue | falseDefault removal permission for image-library entries.
colorPickertrue | falseAllows the custom color picker. When false, preset swatches remain available.
colorsArray of #hex, rgb(a), hsl(a), named or transparent values | empty arrayDefault tint/fill swatches for added PNG, JPG and SVG media. An image-level colors array overrides this palette.
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorderEach value: true | falseDefault permissions for added media.
bg, dropBg, dropBorder, dropColor#hex | rgb() | rgba() | hsl() | hsla() | named | transparentWindow, drop-area background, border and text colors.
dropTextString, including an empty stringText displayed inside the fixed drag/drop area.
priceColor, priceBg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentPrice badge.
btnBg, btnBgOver, btnText, btnTextOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentBrowse button states.
close, closeOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentRemovable library-item close icon.
itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentThumbnail 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'.

OptionType / valuesDescription
addShapes.jsonJSON URL string | JSON source string | literal shape-library objectShape library. Item order in JSON is display order.
priceNumber ≥ 0 | currency-free numeric stringGlobal fallback price for shapes. A positive per-shape price overrides it; 0 or an omitted value inherits it.
removabletrue | falseDefault removal permission for shape-library entries.
colorPickertrue | falseAllows the custom color picker. When false, preset swatches remain available.
fill#hex | rgb(a) | hsl(a) | named | transparent | empty stringDefault canvas shape fill.
colorsArray of #hex, rgb(a), hsl(a), named or transparent values | empty arrayDefault fill swatches for added shapes. A shape-level colors array overrides this palette.
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorderEach value: true | falseDefault shape permissions.
bg, itemFill, itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentWindow, preview-shape fill and thumbnail states.
priceColor, priceBg, close, closeOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentPrice 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'.

OptionType / valuesDescription
artworkLibrary.jsonJSON URL string | JSON source string | literal artwork-library objectCategories and artwork library.
searchPlaceholder, allCategoriesLabel, notFoundTextStrings, including empty stringsSearch and category UI labels.
priceNumber ≥ 0 | currency-free numeric stringDefault price assigned to newly added artwork. When provided, the artwork JSON price overrides this value.
removabletrue | falseDefault removal permission for artwork entries.
colorPickertrue | falseAllows the custom color picker. When false, preset swatches remain available.
colorsArray of #hex, rgb(a), hsl(a), named or transparent values | empty arrayDefault tint/fill swatches for added artwork. An artwork-level colors array overrides this palette.
canDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorderEach value: true | falseDefault artwork permissions.
bg, itemBg, itemBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentWindow and artwork-card colors.
priceColor, priceBg, close, closeOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentPrice and removal button states.
searchBg, searchText, searchBorder, searchBorderFocus#hex | rgb() | rgba() | hsl() | hsla() | named | transparentCategory search field.
catBg, catBgOver, catText, catTextOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentCategory buttons.

Canvas

Configure the canvas appearance, object controls, dimensions, zoom behavior and ruler styling.

OptionType / valuesDescription
canvas.showDimensionstrue | falseShows rounded selected-object dimensions without covering canvas controls.
dimenstionsBg, dimenstionsText#hex | rgb() | rgba() | hsl() | hsla() | named | transparentDimension badge colors. The historical spelling is supported.
objBg, bg#hex | rgb() | rgba() | hsl() | hsla() | named | transparentSelected-object control accent and canvas background.
icon, iconOver, iconBg, iconBgOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentCanvas move/rotate/resize/delete control states.
zoomLevelsArray of finite numbers > 0, for example [1, 1.25, 1.5, 2]Reference zoom levels; 1 is automatically included.
zoomStepFinite number > 0, typically 0.01–0.25Zoom slider and Space + wheel increment.
toggleRulertrue | falseShows the rulers when the designer starts. The Ruler action can still toggle them.
rulerBg, rulerText, rulerTick, rulerTickMajor, rulerBorder#hex | rgb() | rgba() | hsl() | hsla() | named | transparentRuler 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.

OptionType / valuesDescription
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.
toggledtrue | falseIn 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, textMaxWFinite number > 0 (CSS pixels)Normal and text-object toolbar maximum widths.
maxScaleFinite number > 0Maximum scale value available in the toolbar.
maxSkewFinite number from 0 to 89 (degrees)Positive and negative skew limit.
defRadiusNumber from 0 to 300Default curved-text radius.
bg, icon, iconOver#hex | rgb() | rgba() | hsl() | hsla() | named | transparentToolbar window and primary icon colors.
sliderBg, sliderBorder, sliderFill, sliderHandle, sliderInput, sliderHandleBorder#hex | rgb() | rgba() | hsl() | hsla() | named | transparentAll object-toolbar sliders and inputs.
backString, including an empty stringBack button label in floating subwindows.
secBg, secBgOver, secIcon, secIconOver, secBorder#hex | rgb() | rgba() | hsl() | hsla() | named | transparentAlign, format, flip and other secondary button states.
Permission-driven UI: toolbar buttons and canvas controls are automatically hidden when the selected element does not allow the related action. For example, 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

  1. The color saved on the current view element.
  2. The individual template or library-item color.
  3. The module default fill, tint or palette.
  4. 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.

Required view data: every editable view needs an 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

  1. Select: click the red dashed printing box. Its translucent fill and resize controls appear only while selected.
  2. Move: drag the selected box, use its X/Y inputs, or press an Arrow key. Shift + Arrow uses the configured large movement step.
  3. Resize: drag a resize control, change W/H, or use Ctrl/Cmd + Arrow. Add Shift for the large resize step.
  4. Center: when Snap To Center is active, the box snaps to the horizontal and vertical canvas center and displays the configured guides.
  5. Finish: click outside the canvas to deselect it, then use Product Export to save the updated printing-box values.
Ratio lock: resizing never freely distorts the box. Its width and height remain proportional to 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.

Simple rule: 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.

Use the printable area, not the complete product size. For a mug, do not include the handle. Enter only the surface where artwork can actually be printed.
  1. Enter the real print size. Set print_width_mm and print_height_mm in millimeters.
  2. 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_mm and print_height_mm.
  3. Position the product artwork. Align the base image, SVG colors, shading and overlays around the printing box.
  4. 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.
  5. 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.

Do not copy millimeters directly into the pixel box. A 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 sizeChosen pixel dimensionCalculated pixel box
180 × 100 mmWidth 580 px580 × 322 px
95 × 117 mmWidth 518 px518 × 638 px
100 × 100 mmWidth 400 px400 × 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.width and recalculates printing_box.height on 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

ValueUnitPurpose
canvas_width, canvas_heightCanvas pixelsSize of the complete editable stage for a view.
printing_box.left, topCanvas pixelsPosition of the printable crop area inside the stage.
printing_box.width, heightCanvas pixelsSize of the printable crop area inside the editor.
Root unitScalePositive multiplierOptional product-wide multiplier applied after per-view calibration. Missing or invalid values fall back to 1.
print_width_mm, print_height_mmMillimetersAuthoritative physical size represented by the view's printing box.
bleedMillimeters per edgeExtra physical area added to every side. The view value falls back to the global constructor bleed setting when omitted.
dpiPixels per inch or 0Controls raster resolution. Set 0 to export using the printing-box pixel dimensions without DPI scaling.
Effective unitmm, cm, inch, or pxThe 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.
Automatic ratio lock: the printing box always uses whole canvas pixels and preserves 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.

Product silhouette and background: the printing box defines a rectangular crop, but it does not paint that rectangle. Production PNG keeps transparent pixels outside rounded or irregular product shapes, preventing the editor background from appearing around products such as phone cases. JPG and PDF use white because they do not preserve the same transparent-canvas workflow. To print a solid color, add an explicit rectangle, SVG or PNG layer and leave both export-exclusion options set to 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.

Ratio safety: the editor automatically keeps 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.
  • jpeg is normalized to jpg.
  • 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_mm and print_height_mm, calibrated against its printing box and multiplied by unitScale.
  • Runtime outputWidth, outputHeight, and bleed are interpreted as canonical millimeters. Runtime bleed overrides view JSON, which overrides the global fallback. unit/outputUnit controls converted presentation metadata.

Production validation checklist

  • Define canvas_width and canvas_height in pixels for every view.
  • Define an accurate printing_box inside the canvas.
  • Set the real printing size in print_width_mm and print_height_mm.
  • Keep the output aspect ratio equal to the printing-box aspect ratio.
  • Set one positive root unitScale only when an additional multiplier is needed; omitted values default to 1.
  • 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.
Production export is different from product export: 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": {}
        }
    ]
}
PropertyType / valuesDescription
titleNon-empty stringProduct title shown in Products and used for filenames.
thumbnailRelative or absolute image-URL stringProduct-module preview, resolved relative to this JSON.
basePriceNumber ≥ 0 | currency-free numeric stringGlobal product base price. Do not include the currency symbol. Defaults to 0.
startAtViewInteger ≥ 0 | exact view-title stringInitial 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.
unitScaleFinite number > 0Optional product-wide multiplier applied after each view derives its scale from output size and printing-box pixels. Defaults to 1.
viewsArray of {title, thumbnail, elements, options} objectsOrdered 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
    }
}
PropertyType / supported valuesDescription
canvas_width, canvas_heightNumber > 0 | positive numeric string, in editor pixelsActual design-stage size for this view.
printing_box.left, printing_box.topFinite number | numeric string, in editor pixelsPrinting-box position inside the canvas.
printing_box.width, printing_box.heightNumber > 0 | positive numeric string, in whole editor pixelsPrinting-box crop dimensions. Their ratio is automatically normalized to print_width_mm / print_height_mm.
print_width_mm, print_height_mmNumber > 0 | positive numeric string, in millimetersAuthoritative physical production size represented by the printing box. Legacy output_width/output_height values are still accepted when loading.
dpiFinite number ≥ 0Production raster density. A value of 0 uses the printing-box pixel dimensions.
bleedFinite number ≥ 0, in millimetersPer-view physical bleed override. When omitted, the global constructor bleed value is used.
Product conversion: millimeters per pixel are calculated per axis from physical output divided by printing-box pixels, then multiplied by 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 groupProperties and supported valuesBehavior
Position/originleft, top: finite numbers; originX: 'left' | 'center' | 'right'; originY: 'top' | 'center' | 'bottom'; autoCenter: true | falseCanvas position and transform origin. Center origins are recommended.
TransformscaleX, scaleY, minScaleLimit: numbers > 0; angle, skewX, skewY: finite degree values; lockUniScaling, flipX, flipY: true | falseInitial transform and limits.
PermissionscanDuplicate, canReset, canMove, canRotate, canResize, canDelete, canReorder: each true | falseControls both behavior and visible UI actions.
Layer stateshowInLayers, locked, visible, alwaysOnTop, autoSelect: each true | falseLayer-list visibility, editing lock, canvas visibility, permanent visual top order and initial selection.
Appearancefill: #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 behaviorprice: number ≥ 0 | currency-free numeric string; syncInAllViews, excludeFromExport, excludeFromProductionExport: true | false; boundingBoxMode: 'none' | 'inside' | 'clipping' | object-title stringPrice, cross-view synchronization, bounds, all-export exclusion and production-only exclusion.
Loading/renderingscaleMode: '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.

Locking is independent from permissions: an element with every 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

  • fill is the initial single fill/tint.
  • Module-level colors define the default swatches for Text, Images, Shapes or Artwork.
  • Item-level colors, either directly on the item or inside parameters, replace the module palette for that item.
  • An explicit empty colors: [] removes preset swatches from that item.
  • svgFill stores one color per detected SVG fill group for multi-fill SVG editing.
  • colorPicker: false keeps the Color section and swatches but prevents opening the custom picker.
  • An empty fill with an empty colors array 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
    }
}
PropertyValuesDescription
curvedType'normal' | 'curvedUp' | 'curvedDown' | 'oblique' | 'bridge'Text geometry mode.
curveRadiusNumber from 0 to 300Arc radius for curved up/down. Smaller values create a stronger curve.
curveNumber from -100 to 100Oblique/bridge deformation strength.
curveOffsetNumber from 0 to 100Internal vertical deformation offset without changing object position.
letterSpacingFinite number; negative, zero or positiveFabric character spacing, synchronized between Format Text and Curved Text.
maxLinesInteger ≥ 00 means unlimited lines; otherwise limits multiline input.
textTransform'none' | 'uppercase' | 'lowercase'Rendered character transform while preserving editable source text.
widthFontSizetrue | false | finite number > 0When 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

Precedence rule: an item's direct properties or 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

ShortcutRequirementAction
Arrow keysMovable object selectedMove by keuboardMoveNudgeAmmount.
Shift + Arrow keysMovable object selectedLarge movement.
Arrow keysEditable printing box selectedMove the printing box in whole-pixel steps.
Ctrl/Cmd + Arrow keysEditable printing box selectedResize by the configured normal movement step while preserving the physical print ratio. Up/Right enlarge; Down/Left shrink.
Ctrl/Cmd + Shift + Arrow keysEditable printing box selectedRatio-locked resize using the configured large movement step.
Alt + Left / RightRotatable object selectedRotate by the normal configured step.
Shift + Alt + Left / RightRotatable object selectedLarge rotation step.
Ctrl/Cmd + Up / DownResizable object selectedUniform scale up/down.
Ctrl/Cmd + Left / RightResizable object selectedScale X down/up.
Ctrl/Cmd + Shift + Up / DownResizable object selectedScale Y up/down.
Delete / BackspaceDeletable object selectedRequest object deletion.
Ctrl/Cmd + DDuplicable object selectedDuplicate object.
Ctrl/Cmd + ZHistory availableUndo.
Ctrl/Cmd + YRedo availableRedo.
Ctrl/Cmd + Shift + ZRedo availableRedo.
EscapeAny editor modeClose picker/toolbar mode and deselect the object.
Shift while rotatingCanvas rotate handleSnap rotation in 90-degree increments.
Space + dragPointer inside editor and ruler visibleTemporarily disable object interaction and pan the zoomed canvas.
Space + mouse wheelPointer inside editor and ruler visibleZoom the canvas.
Input safety: normal shortcuts do not take over typing in inputs, textareas or active canvas text editing. Space navigation is available only when the ruler is enabled.

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

MethodReturnsDescription
await loadProductByIndex(index, forceReload)PromiseLoads a product by numeric index. With forceReload, restores original product data.
await loadProductView(index)PromiseLoads a specific view and resets view history.
await goToNextView()PromiseMoves to the next available view.
await goToPrevView()PromiseMoves to the previous available view.
await resetCurrentProduct()PromiseRestores the current product's initial state directly.
await requestResetCurrentProduct()PromiseUses the configured reset confirmation before resetting.
await showPreviewWindow()PromiseRenders and opens the full-browser all-view preview.
showSavedDesignsLightbox()voidOpens the independent full-browser saved-design window.
showLightbox()voidOpens an instance configured with display: 'lightbox'. The first call initializes it; later calls reuse its existing products, edits and history.
hideLightbox()voidHides a lightbox instance without destroying or reinitializing the editor.
showInfoWindow(text)voidShows 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.