Skip to main content

Tutorial: Creating Customizable 3D Text for Shopify Products

What You Will Learn: Interactive 3D Text Configuration

This tutorial focuses on creating a Shopify product that features customizable 3D text. You will learn how to:

  • Use Shopify product variants to allow customers to select different fonts for the 3D text.
  • Implement custom Liquid line item inputs to enable customers to enter their own text content and adjust properties like the text's height.
  • Integrate a Bitbybit Rete script (designed for generating 3D text) into your Shopify product page using the "3D Bits" app and the BITBYBIT RUNNER block.

View the Demo:

  • Check out the live example on our Demo Store: Text 3D Product Page. (Note: The demo link might be for a generic "industrial part" but showcases the text functionality).
  • Demo store password: 3d-bits-demo

A screenshot of the customizable 3D text model as it appears in the Shopify store. Customizable 3D Text Example

Video Tutorial: Building the 3D Text Configurator

Key Configuration Steps

Custom Liquid for Line Item Inputs

Similar to the Palm Table tutorial, this example utilizes a custom Liquid form to gather specific inputs from the customer (the text content and its height) as line item properties.

  • Metafield Setup: If you haven't already, you'll need to set up a product metafield with the key custom.liquid-custom-line-items to hold your Liquid form code. Please refer to the Palm Table tutorial or the video for detailed instructions on setting up this metafield.
  • Liquid Form Snippet: The following HTML/Liquid snippet defines the form inputs for the custom text and its height. Copy this code into the custom.liquid-custom-line-items product metafield you created.
<style>
label {
margin-top: 20px;
}
input {
width: 100%;
max-width: 440px;
}
input[type='text'] {
height: 40px;
padding: 20px;
-webkit-user-select: text;
}
::selection {
background-color: #000000;
color: #ffffff;
}
input[type='range'] {
margin: 0px;
appearance: none;
background-color: #000000;
color: #000000;
height: 2px;
border-radius: 0.5vmin;
}
input::-webkit-slider-thumb {
cursor: pointer;
appearance: none;
width: 1vmin;
height: 1vmin;
background: black;
}
</style>

<p class="line-item-property__field">
<label class="form__label" for="html5colorpicker">Color</label>
<input name="properties[Color]" form="{{product_form_id}}" type="color" id="html5colorpicker" onchange="clickColor(0, -1, -1, 5)" value="#f0cebb">
<label class="form__label" id="text-height-range-label" for="text-height-range">Text Height</label>
<input
id="text-height-range"
form="{{product_form_id}}"
name="properties[Text Height]"
type="range"
min="0.1"
max="2"
value="0.5"
step="0.1"
class="slider"
/>
<label class="form__label" id="base-height-range-label" for="base-height-range">Base Height</label>
<input
id="base-height-range"
form="{{product_form_id}}"
name="properties[Base Height]"
type="range"
min="0.1"
max="2"
value="0.5"
step="0.1"
class="slider"
/>
<label class="form__label" for="text-to-form">3D Text</label>
<input
id="text-to-form"
name="properties[Text 3D]"
maxlength="30"
value="bitbybit.dev 3D WebCAD"
form="{{product_form_id}}"
type="text"
/>
</p>
<script>
setTimeout(() => {
setupUpdates('text-height-range', 'Text Height: ');
setupUpdates('base-height-range', 'Base Height: ');
});

function setupUpdates(id, label){
const value = document.querySelector(`#${id}-label`);
const input = document.querySelector(`#${id}`);
value.textContent = label + input.value;
input.addEventListener('change', (event) => {
value.textContent = label + event.target.value;
});
}
</script>

Setting Up Product Variants for Font Selection

For the font selection, you will use standard Shopify product variants:

  • Variant Option Name: Font
  • Variant Option Values: Tektur, Roboto, Orbitron (or any other font names your Bitbybit script is programmed to handle).

Your Bitbybit script will read both the line item properties (text content, height) and the selected font variant to generate the 3D text.

The Bitbybit Rete Script

To save you time, here is the embedded Bitbybit Rete script used in this tutorial for generating the parametric 3D text. You can explore it here and then use the "Export to Runner" feature in the Bitbybit editor to get the JavaScript code for your Shopify BITBYBIT RUNNER block.

Bitbybit Platform

Bitbybit Rete Editor - 3D Customizable Text

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"f67f8c01c549a695": {
"id": "f67f8c01c549a695",
"name": "bitbybit.advanced.text3d.create",
"customName": "text 3d",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "bitbybit.dev + shopify.com",
"fontType": "Roboto",
"fontVariant": "Regular",
"fontSize": 1.5,
"height": 0.5,
"rotation": 180,
"origin": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"originAlignment": "centerMiddle"
},
"inputs": {
"origin": {
"connections": [
{
"node": "e7df39c8f146fdaf",
"output": "result",
"data": {}
}
]
},
"text": {
"connections": [
{
"node": "a110775d7aa9121c",
"output": "result",
"data": {}
}
]
},
"height": {
"connections": [
{
"node": "0d5f661d4d739cf2",
"output": "result",
"data": {}
}
]
},
"fontType": {
"connections": [
{
"node": "96d818aece6a9d50",
"output": "result",
"data": {}
}
]
}
},
"position": [
765.6369676148224,
51.69113983022578
]
},
"42f5b7b8481a5ed9": {
"id": "42f5b7b8481a5ed9",
"name": "bitbybit.occt.shapes.wire.createRectangleWire",
"customName": "rectangle wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"width": 23,
"length": 3,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"center": {
"connections": [
{
"node": "ac8e8b03912f1aaa",
"output": "result",
"data": {}
}
]
}
},
"position": [
1015.2578125,
632.22265625
]
},
"ac8e8b03912f1aaa": {
"id": "ac8e8b03912f1aaa",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": -0.3
},
"inputs": {},
"position": [
611.3904900720239,
810.3584842511211
]
},
"a47f31ebcec14863": {
"id": "a47f31ebcec14863",
"name": "bitbybit.occt.fillets.fillet2d",
"customName": "fillet 2d",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 0.5
},
"inputs": {
"shape": {
"connections": [
{
"node": "42f5b7b8481a5ed9",
"output": "result",
"data": {}
}
]
}
},
"position": [
1374.1952481995884,
648.609246399177
]
},
"185f2d72797f11fb": {
"id": "185f2d72797f11fb",
"name": "bitbybit.occt.shapes.face.createFaceFromWire",
"customName": "face from wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"planar": true
},
"inputs": {
"shape": {
"connections": [
{
"node": "a47f31ebcec14863",
"output": "result",
"data": {}
}
]
}
},
"position": [
1869.0289574559004,
674.378493195208
]
},
"460d91137d0323a2": {
"id": "460d91137d0323a2",
"name": "bitbybit.draw.drawAnyAsync",
"customName": "draw any async",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"options": {
"connections": [
{
"node": "8c48c69fc882f42e",
"output": "result",
"data": {}
}
]
},
"entity": {
"connections": [
{
"node": "b9c6383746437f94",
"output": "result",
"data": {}
}
]
}
},
"position": [
3668.5297284505837,
987.5675248490475
]
},
"49bab1541d7b7a5b": {
"id": "49bab1541d7b7a5b",
"name": "bitbybit.babylon.scene.drawDirectionalLight",
"customName": "draw directional light",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
-100,
-100,
-100
],
"intensity": 1,
"diffuse": "#ffffff",
"specular": "#ffffff",
"shadowGeneratorMapSize": 2056,
"enableShadows": true,
"shadowDarkness": 0.3,
"shadowUsePercentageCloserFiltering": true,
"shadowContactHardeningLightSizeUVRatio": 0.2,
"shadowBias": 0.0001,
"shadowNormalBias": 0.002,
"shadowMaxZ": 1000,
"shadowMinZ": 0
},
"inputs": {},
"position": [
89.47921838416175,
2279.8176060045625
]
},
"6148707144527816": {
"id": "6148707144527816",
"name": "bitbybit.draw.drawAnyAsync",
"customName": "draw any async",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"options": {
"connections": [
{
"node": "5b9b11ee25eac7b3",
"output": "result",
"data": {}
}
]
},
"entity": {
"connections": [
{
"node": "4aeb3f8ea04b2309",
"output": "result",
"data": {}
}
]
}
},
"position": [
3574.3320114147064,
26.98652070164698
]
},
"5be569d81ce054da": {
"id": "5be569d81ce054da",
"name": "bitbybit.babylon.material.pbrMetallicRoughness.create",
"customName": "pbr metallic roughness",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "Custom Material",
"baseColor": "#ffffff",
"emissiveColor": "#000000",
"metallic": 0.2,
"roughness": 0.8,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 1
},
"inputs": {
"baseColor": {
"connections": [
{
"node": "699b1e73f22e9fc1",
"output": "result",
"data": {}
}
]
}
},
"position": [
2638.163868090751,
296.38359338205237
]
},
"5b9b11ee25eac7b3": {
"id": "5b9b11ee25eac7b3",
"name": "bitbybit.draw.optionsOcctShapeMaterial",
"customName": "options occt shape material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"precision": 0.05,
"drawEdges": true,
"edgeColour": "#f0cebb",
"edgeWidth": 1.5
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "5be569d81ce054da",
"output": "result",
"data": {}
}
]
}
},
"position": [
3020.961596434065,
239.26131489116065
]
},
"4aeb3f8ea04b2309": {
"id": "4aeb3f8ea04b2309",
"name": "bitbybit.advanced.text3d.getCompoundShape",
"customName": "get compound shape",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"model": {
"connections": [
{
"node": "f67f8c01c549a695",
"output": "result",
"data": {}
}
]
}
},
"position": [
1352.9691460984973,
62.243038689673426
]
},
"916a82ee03e7552b": {
"id": "916a82ee03e7552b",
"name": "bitbybit.babylon.scene.drawDirectionalLight",
"customName": "draw directional light",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
-100,
-100,
-100
],
"intensity": 3,
"diffuse": "#ffffff",
"specular": "#ffffff",
"shadowGeneratorMapSize": 2056,
"enableShadows": true,
"shadowDarkness": 0,
"shadowUsePercentageCloserFiltering": true,
"shadowContactHardeningLightSizeUVRatio": 0.2,
"shadowBias": 0.0001,
"shadowNormalBias": 0.002,
"shadowMaxZ": 1000,
"shadowMinZ": 0
},
"inputs": {
"direction": {
"connections": [
{
"node": "3462604dff61d9cf",
"output": "result",
"data": {}
}
]
}
},
"position": [
1569.2155761655538,
1251.8249401795665
]
},
"3462604dff61d9cf": {
"id": "3462604dff61d9cf",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": -15,
"y": -10,
"z": -10
},
"inputs": {},
"position": [
1056.3298268714798,
1533.0678169740593
]
},
"8c48c69fc882f42e": {
"id": "8c48c69fc882f42e",
"name": "bitbybit.draw.optionsOcctShapeMaterial",
"customName": "options occt shape material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"precision": 0.05,
"drawEdges": true,
"edgeColour": "#f0cebb",
"edgeWidth": 1.5
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "142d8ec2b9845ea3",
"output": "result",
"data": {}
}
]
}
},
"position": [
2994.3013679396067,
1514.8174079045473
]
},
"142d8ec2b9845ea3": {
"id": "142d8ec2b9845ea3",
"name": "bitbybit.babylon.material.pbrMetallicRoughness.create",
"customName": "pbr metallic roughness",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "Custom Material",
"baseColor": "#f0cebb",
"emissiveColor": "#000000",
"metallic": 0.6,
"roughness": 0.8,
"alpha": 1,
"backFaceCulling": false,
"zOffset": 1
},
"inputs": {
"baseColor": {
"connections": [
{
"node": "699b1e73f22e9fc1",
"output": "result",
"data": {}
}
]
}
},
"position": [
2551.4686696014014,
1728.9782873385639
]
},
"e7df39c8f146fdaf": {
"id": "e7df39c8f146fdaf",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0.01,
"z": 0
},
"inputs": {},
"position": [
259.8741357983199,
436.7966548297619
]
},
"3176c2d5a587e191": {
"id": "3176c2d5a587e191",
"name": "bitbybit.text.create",
"customName": "create",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "We Love 3D!"
},
"inputs": {},
"position": [
-393.7632956287673,
-196.29196998809803
]
},
"982a12a9795a5f75": {
"id": "982a12a9795a5f75",
"name": "bitbybit.runner.getRunnerInputValue",
"customName": "get runner input value",
"data": {
"property": "properties[Text 3D]"
},
"inputs": {},
"position": [
-551.1824687081382,
-347.7689971723621
]
},
"a110775d7aa9121c": {
"id": "a110775d7aa9121c",
"name": "bitbybit.logic.firstDefinedValueGate",
"customName": "first defined value gate",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"value1": {
"connections": [
{
"node": "982a12a9795a5f75",
"output": "result",
"data": {}
}
]
},
"value2": {
"connections": [
{
"node": "3176c2d5a587e191",
"output": "result",
"data": {}
}
]
}
},
"position": [
158.79703088870372,
-154.57874211289987
]
},
"2e1bc831c418ccc6": {
"id": "2e1bc831c418ccc6",
"name": "bitbybit.math.number",
"customName": "number",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"number": 0.5
},
"inputs": {},
"position": [
-424.4711150582058,
233.8569176053654
]
},
"120141c05c73df4c": {
"id": "120141c05c73df4c",
"name": "bitbybit.runner.getRunnerInputValue",
"customName": "get runner input value",
"data": {
"property": "properties[Text Height]"
},
"inputs": {},
"position": [
-548.7955399370704,
99.69514102163816
]
},
"0d5f661d4d739cf2": {
"id": "0d5f661d4d739cf2",
"name": "bitbybit.logic.firstDefinedValueGate",
"customName": "first defined value gate",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"value1": {
"connections": [
{
"node": "120141c05c73df4c",
"output": "result",
"data": {}
}
]
},
"value2": {
"connections": [
{
"node": "2e1bc831c418ccc6",
"output": "result",
"data": {}
}
]
}
},
"position": [
174.0282063769109,
129.44924562352833
]
},
"b9c6383746437f94": {
"id": "b9c6383746437f94",
"name": "bitbybit.occt.operations.extrude",
"customName": "extrude",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"direction": [
0,
1,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "185f2d72797f11fb",
"output": "result",
"data": {}
}
]
},
"direction": {
"connections": [
{
"node": "c9d402ef8ffafcfe",
"output": "result",
"data": {}
}
]
}
},
"position": [
3080.834700576882,
805.3351499989922
]
},
"c9d402ef8ffafcfe": {
"id": "c9d402ef8ffafcfe",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": -1,
"z": 0
},
"inputs": {
"y": {
"connections": [
{
"node": "dcb99e33752e59c2",
"output": "result",
"data": {}
}
]
}
},
"position": [
2612.1283990122174,
936.6249692030156
]
},
"ac756c3f1a5325c1": {
"id": "ac756c3f1a5325c1",
"name": "bitbybit.runner.getRunnerInputValue",
"customName": "get runner input value",
"data": {
"property": "properties[Base Height]"
},
"inputs": {},
"position": [
-825.2041602293295,
933.8506869084349
]
},
"4e08a25dd7eaaf0b": {
"id": "4e08a25dd7eaaf0b",
"name": "bitbybit.math.number",
"customName": "number",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"number": 0.7
},
"inputs": {},
"position": [
-720.6045061109694,
1130.9958644118383
]
},
"d8d798c5f420cc76": {
"id": "d8d798c5f420cc76",
"name": "bitbybit.logic.firstDefinedValueGate",
"customName": "first defined value gate",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"value1": {
"connections": [
{
"node": "ac756c3f1a5325c1",
"output": "result",
"data": {}
}
]
},
"value2": {
"connections": [
{
"node": "4e08a25dd7eaaf0b",
"output": "result",
"data": {}
}
]
}
},
"position": [
-316.99698239726405,
1033.6596076410217
]
},
"dcb99e33752e59c2": {
"id": "dcb99e33752e59c2",
"name": "bitbybit.math.oneNrOperation",
"customName": "one nr operation",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"number": 1,
"operation": "negate"
},
"inputs": {
"number": {
"connections": [
{
"node": "d8d798c5f420cc76",
"output": "result",
"data": {}
}
]
}
},
"position": [
202.94826703282672,
1075.7876679070412
]
},
"896daf2b09fd25f4": {
"id": "896daf2b09fd25f4",
"name": "bitbybit.runner.setRunnerResultValue",
"customName": "set runner result value",
"data": {
"property": "meshes"
},
"inputs": {
"value": {
"connections": [
{
"node": "5d4086d2ac7d3f8b",
"output": "list",
"data": {}
}
]
}
},
"position": [
4558.999642094764,
479.7033546130833
]
},
"5d4086d2ac7d3f8b": {
"id": "5d4086d2ac7d3f8b",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "6148707144527816",
"output": "result",
"data": {}
},
{
"node": "460d91137d0323a2",
"output": "result",
"data": {}
}
]
}
},
"position": [
4190.326747239366,
471.3175951458681
]
},
"2e01dd35d521b59c": {
"id": "2e01dd35d521b59c",
"name": "bitbybit.color.hexColor",
"customName": "hex color",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"color": "#000000"
},
"inputs": {},
"position": [
1607.0140809012648,
2151.8820720280114
]
},
"e4841ccf47c790ee": {
"id": "e4841ccf47c790ee",
"name": "bitbybit.runner.getRunnerInputValue",
"customName": "get runner input value",
"data": {
"property": "properties[Color]"
},
"inputs": {},
"position": [
1461.460277535588,
1999.8511049468452
]
},
"699b1e73f22e9fc1": {
"id": "699b1e73f22e9fc1",
"name": "bitbybit.logic.firstDefinedValueGate",
"customName": "first defined value gate",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"value1": {
"connections": [
{
"node": "e4841ccf47c790ee",
"output": "result",
"data": {}
}
]
},
"value2": {
"connections": [
{
"node": "2e01dd35d521b59c",
"output": "result",
"data": {}
}
]
}
},
"position": [
1930.2768050452478,
2019.6159784237263
]
},
"96d818aece6a9d50": {
"id": "96d818aece6a9d50",
"name": "bitbybit.logic.firstDefinedValueGate",
"customName": "first defined value gate",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"value1": {
"connections": [
{
"node": "14edb7db4246948c",
"output": "result",
"data": {}
}
]
},
"value2": {
"connections": [
{
"node": "c26705bac77004ea",
"output": "result",
"data": {}
}
]
}
},
"position": [
87.91691673553828,
-929.2180774041162
]
},
"c26705bac77004ea": {
"id": "c26705bac77004ea",
"name": "bitbybit.text.create",
"customName": "create",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "Orbitron"
},
"inputs": {},
"position": [
-620.0505066396745,
-890.9871599729952
]
},
"14edb7db4246948c": {
"id": "14edb7db4246948c",
"name": "bitbybit.runner.getRunnerInputValue",
"customName": "get runner input value",
"data": {
"property": "Font"
},
"inputs": {},
"position": [
-784.7014978055885,
-1044.4867483116782
]
}
}
}

This tutorial demonstrates a powerful combination: using Shopify's native variants for broader style choices (like font) and custom Liquid line item properties for detailed, user-defined input (like custom text). By integrating this with a Bitbybit script via the Runner, you can offer highly personalized 3D products on your Shopify store. Remember to adapt the index.html and script.js (from previous tutorials, e.g., the Table Configurator) by replacing the placeholder exported script function with the actual JavaScript code generated from your Rete 3D text script.