The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "FormatLab - Export Bundle (ZIP)",
"nodes": [
{
"parameters": {
"path": "export",
"responseMode": "responseNode",
"responseData": "noData",
"options": {}
},
"id": "webhook_trigger",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
]
},
{
"parameters": {
"functionCode": "// Prepare export data\nconst runId = $input.first().json.run_id;\nconst sceneJson = $input.first().json.scene_json;\nconst patchJson = $input.first().json.patch_json || [];\nconst outputUrls = $input.first().json.output_urls || [];\nconst include16bit = $input.first().json.include_16bit !== false;\n\nconst metadata = {\n export_id: require('crypto').randomUUID(),\n run_id: runId,\n timestamp: new Date().toISOString(),\n include_16bit: include16bit,\n num_variants: outputUrls.length,\n scene_name: sceneJson.name || 'Untitled Scene',\n seed: sceneJson.seed,\n version: '1.0'\n};\n\nreturn {\n export_id: metadata.export_id,\n run_id: runId,\n scene_json: sceneJson,\n patch_json: patchJson,\n output_urls: outputUrls,\n metadata: metadata,\n include_16bit: include16bit\n};"
},
"id": "prepare_export",
"name": "Prepare Export",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
]
},
{
"parameters": {
"functionCode": "// Download all images\nconst urls = $input.first().json.output_urls || [];\nconst images = [];\n\nfor (let i = 0; i < urls.length; i++) {\n const url = urls[i];\n const filename = `preview_${i}.png`;\n \n images.push({\n index: i,\n url: url,\n filename: filename,\n role: 'preview'\n });\n}\n\nreturn {\n ...($input.first().json),\n images: images\n};"
},
"id": "prepare_images",
"name": "Prepare Images",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
650,
300
]
},
{
"parameters": {
"functionCode": "// Create ZIP bundle structure\nconst JSZip = require('jszip');\nconst zip = new JSZip();\n\nconst data = $input.first().json;\n\n// Add scene.json\nzip.file(\n 'scene.json',\n JSON.stringify(data.scene_json, null, 2)\n);\n\n// Add patch.json\nif (data.patch_json && data.patch_json.length > 0) {\n zip.file(\n 'patch.json',\n JSON.stringify(data.patch_json, null, 2)\n );\n}\n\n// Add metadata.json\nzip.file(\n 'metadata.json',\n JSON.stringify(data.metadata, null, 2)\n);\n\n// Note: Images would be added here in real implementation\n// For now, just include references\nconst imageManifest = data.images.map(img => ({\n filename: img.filename,\n url: img.url,\n role: img.role\n}));\n\nzip.file(\n 'images-manifest.json',\n JSON.stringify(imageManifest, null, 2)\n);\n\n// Add schemas folder\nconst schemas = {\n 'scene.schema.json': {\n type: 'object',\n properties: {\n version: { type: 'string' },\n id: { type: 'string' },\n subject: { type: 'object' },\n camera: { type: 'object' },\n lighting: { type: 'object' },\n color: { type: 'object' },\n constraints: { type: 'object' }\n }\n },\n 'patch.schema.json': {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n op: { enum: ['add', 'remove', 'replace', 'move', 'copy', 'test'] },\n path: { type: 'string' },\n value: {}\n }\n }\n }\n};\n\nconst schemasFolder = zip.folder('schemas');\nfor (const [filename, schema] of Object.entries(schemas)) {\n schemasFolder.file(filename, JSON.stringify(schema, null, 2));\n}\n\n// Generate ZIP\nconst zipped = await zip.generateAsync({ type: 'base64' });\n\nreturn {\n export_id: data.export_id,\n run_id: data.run_id,\n zip_base64: zipped,\n filename: `formatlab_export_${data.run_id.substring(0, 8)}_${new Date().toISOString().split('T')[0]}.zip`,\n size: Buffer.from(zipped, 'base64').length,\n timestamp: new Date().toISOString()\n};"
},
"id": "create_zip",
"name": "Create ZIP",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
300
]
},
{
"parameters": {
"respondWithData": true
},
"id": "respond_export",
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1050,
300
]
}
],
"connections": {
"webhook_trigger": {
"main": [
[
{
"node": "prepare_export",
"type": "main",
"index": 0
}
]
]
},
"prepare_export": {
"main": [
[
{
"node": "prepare_images",
"type": "main",
"index": 0
}
]
]
},
"prepare_images": {
"main": [
[
{
"node": "create_zip",
"type": "main",
"index": 0
}
]
]
},
"create_zip": {
"main": [
[
{
"node": "respond_export",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"saveManualExecutions": true,
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
FormatLab - Export Bundle (ZIP). Webhook trigger; 5 nodes.
Source: https://github.com/rkabota/formatlab-studio/blob/6f0c6e1322a5d7c1a0ff857bc9ca4b0c839b6834/n8n-workflows/export-workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A production-ready authentication workflow implementing secure user registration, login, token verification, and refresh token mechanisms. Perfect for adding authentication to any application without
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
This n8n template demonstrates how a simple Multi-Layer Perceptron (MLP) neural network can predict housing prices. The prediction is based on four key features, processed through a three-layer model.
github code Try yourself
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.