Roles and accounts
The ProductBuilder Ecosystem recognizes two types of accounts:
- User
- Organization
User accounts
A user account represents a person. With a User account, that person can create and save Projects for editing at a later time. To create a Project, the User needs a Viewer. User accounts can also be members of an Organization account.
Organization account
An Organization account represents a legal entity. Organization accounts can create and own Packages and Viewers. An Organization has at least one admin member, that is a User account. An Organization has one or more of the following roles:
- Manufacturer
- Dealer
- Material supplier
- Designer
- Content creator
Manufacturer
Creates Products.
Dealer
Sells Products, either in a brick-and-mortar store or online.
Material supplier
Creates Materials, such as fabrics, that can be applied to Products.
Designer
Creates and maintains Templates and Themes for Organizations.
Content creator
Creates and maintains Packages for Manufacturers.
Product Family
Set of Products that are designed to be combined with each other, such as the elements of a sofa. Within our Ecosystem, Product Families are represented by Packages.
Examples
Product
Physical object that is created and sold by a Manufacturer. A Product has a price which can be static or dependent on its configuration, territory and other parameters. Products are usually part of a Product Family.
Examples

Dutch & Dutch 8c in White/Natural finish
Package
A bundle of data that captures all relevant information about a Product Family and its members. Inside the package is a JSON file that defines a Block for each of the Products in the Product Family, including its dimensions, configuration options, etc.
Block
Representation of a single Product. Besides defining the 3D shape, the Block also defines how it can be combined with other Blocks through Connectors.
Examples
Below is a typical Block definition from a Package's index file.
{
"id": "513cd38b-782a-4d3b-bbec-97538f8a050e",
"name": "Chaise Longue CL01",
"manRef": "CBFF-MCL0100",
"thumbnail": "a36468b7-5af6-4293-8ade-c93c8a0f1d98",
"categories": [
"f4ec2b9e-78a2-4302-adcb-a025c1944574"
],
"dimensions": {
"x": 0.99,
"y": 0.69,
"z": 1.65
},
"dimensionsCenter": {
"x": -0.165,
"y": 0.345,
"z": 0.165
},
"dimensionsImage": "7108f721-4d96-49e3-857b-2c119e4ebc24",
"positionedMeshGroups": [
{
"id": "55afaf23-0dbe-4233-8e80-19f8ee39f573",
"name": "legs left short side",
"component": "7f35cb60-9f79-405d-846c-954441e16b84",
"position": {
"x": -0.58,
"y": 0,
"z": 0
},
"quaternion": {
"_w": 1,
"_x": 0,
"_y": 0,
"_z": 0
}
},
{
"id": "5396c746-c398-4e01-af2f-a1add9ae8b34",
"name": "legs left",
"component": "cbe9020b-9355-491b-88a6-be84d997d018",
"position": {
"x": -0.25,
"y": 0,
"z": 0
},
"quaternion": {
"_w": 1,
"_x": 0,
"_y": 0,
"_z": 0
}
},
{
"id": "d8b33c84-daec-4301-8603-f9f0e53fafbe",
"name": "legs right",
"component": "cbe9020b-9355-491b-88a6-be84d997d018",
"position": {
"x": 0.25,
"y": 0,
"z": 0
},
"quaternion": {
"_w": 1,
"_x": 0,
"_y": 0,
"_z": 0
}
}
],
"positionedMeshes": [
{
"id": "cb1972e4-03b1-41ed-a081-1e68a317a634",
"name": "sofa",
"component": "bdf035f1-8ea5-448e-8d11-cfac4b0b4b3f",
"position": {
"x": 0,
"y": 0.03,
"z": 0
},
"quaternion": {
"_w": 1,
"_x": 0,
"_y": 0,
"_z": 0
}
}
],
"connectors": [
{
"id": "798c6195-a4f2-4a7f-b568-dd079d4305a1",
"name": "conRight",
"position": {
"x": 0.33,
"y": 0.25,
"z": 0
},
"quaternion": {
"_w": 0.7071408,
"_x": 0,
"_y": 0.7070727,
"_z": 0
},
"type": "2c5a24fb-03f2-413a-901b-9a3481592c20"
},
{
"id": "245b9cdf-8efe-4d83-b5d7-246e2d04e575",
"name": "conLeftFront",
"position": {
"x": 0,
"y": 0.25,
"z": 0.99
},
"quaternion": {
"_w": 1,
"_x": 0,
"_y": 0,
"_z": 0
},
"type": "af85b230-cb36-40fc-b7f9-116a34827f02"
}
]
}
Connector
Blocks can have Connectors. When two Blocks have compatible Connectors, they can be joined together in a Design.
Material
Physical materials, such as fabrics or wood are represented by digital materials simply called Materials.
Blocks can have different Materials applied to them in a Design.
Project
One or more Designs for a Space.
A Project can be saved, opened, edited and shared from the ProductBuilder Cloud.
Configuration
Specific arrangement of connected, materialized blocks. Users create Configurations by connecting Blocks together and applying Materials to them.
Design
One or more configurations that belong together, but are spatially separated.
Space
Details of a specific physical location, such as its dimensions.
Project Price
Price Class
Materials can have a Price Class. A Price Class can act as a price modifier or look-up category for a Product.
Territory
Price Zone
Product Price
The price of a Product in combination with a certain Material.
Embedding a Viewer
Template
ProductBuilder Iframe API V0
The Iframe API lets you embed a ProductBuilder Viewer on your website and control its behavior using JavaScript. This is our first attempt at creating such an API and we expect to make changes in the future, as first attempts are usually not final.
Using the API's JavaScript functions you can select presets; save and load projects; share designs; get a project's current price and take screenshots. You can also add event listeners that will execute in response to certain viewer events, such as a design update.
This guide explains how to use the Iframe API. It identifies the different types of events that the API can send and explains how to write event listeners to respond to those events. It also details the different JavaScript functions that you can call to control the viewer as well as the viewer parameters you can use to customize the viewer.
Requirements
The user's browser must support the HTML5 postMessage feature. Most modern browsers support postMessage.
Getting started
The sample HTML page below creates an embedded viewer that will load a Package and display the first preset. The numbered comments in the HTML are explained in the list below the example.
<!DOCTYPE html>
<html lang="en">
<body>
<!-- The package id is in the URL -->
<iframe width=800 height=600 id="pbapp" src="https://live.productbuilder.nl/demo"></iframe>
<script type="module" async="true">
import PBIframeApi from 'https://cdn.productbuilder.nl/iframe-api.v0.js';
// the iframe to communicate with
const iframe = document.getElementById( 'target' );
// create the control object
const viewer = new PBIframeApi( iframe );
// wait for the connection to be made
await viewer.connectionPromise;
// start controlling the viewer
await viewer.selectPreset( 0 );
</script>
</body>
</html>
Initialisation
A viewer can simply be embedded by embedding an Iframe with the appropriate URL.
To control the API, the iframe-api script must be loaded from https://cdn.productbuilder.nl/iframe-api.v0.js.
The script is a module and must be loaded as such.
It exports the PBIframeApi class, which can be instantiated by providing a reference to a ProductBuilder Iframe DOM element.
The new PBIframeApi object will attempt to connect to the code inside the Iframe by checking whether the
- content is indeed a ProductBuilder viewer
- versions are compatible
- origin of the parent is allowed by the viewer
The PBIframeApi object has a property called connectionPromise which is should be awaited.
If any of the above checks fail, the promise is rejected resulting in an error which you can catch and deal with gracefully.
If the promise resolves, the connection has been made and it is now safe to start communicating with the viewer.
Operations
Change the locale
Only possible after the viewer is connected to the ProductBuilder cloud.
viewer.setLocale(locale:String):Boolean
Get the id of the current project
viewer.projectId():String
Get the slug of the current project
viewer.projectSlug():String
Share a project
Creates a copy with a different id/slug and make it readonly.
viewer.shareProject():Object<string,string>
Save the current project to the ProductBuilder cloud
viewer.saveProject():Object<string,string>
Load a project from the cloud.
viewer.loadProject(identifier:String):Object<string,string>
Get the configurators in the current design
Returns an array of objects with the configurator id and pkg id.
viewer.listConfigurators():Array<Object<string,string>>
Get the presets of a package
Returns a flat list of objects with the preset id and package id.
viewer.listPresets(pkgId:String):Array<Object<string,string>>
Take a screenshot
Returns a DataURI of a screenshot of the current camera angle.
viewer.screenshot():String
Select a preset
Update the current design by changing it into a preset.
viewer.selectPreset({ configuratorId:String, presetId:String }):Boolean
Get project price
Returns the current price object if the viewer is connected to the ProductBuilder cloud.
viewer.price():Object
Call template specific methods
viewer.ui(data:any):any
List the available packages
Returns an array of {id:string} objects.
viewer.listLoadedPackages():Array<Object<string,string>>