{ "name": "Contact-cards", "nodes": [ { "parameters": {}, "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ -352, -368 ], "id": "f1141f30-1190-4aa5-beba-c5cd71b5d2da", "name": "When clicking ‘Execute workflow’" }, { "parameters": { "jsCode": "// n8n Code node (run once per item)\n// Input (minimaal):\n// name, title, company, email, website, street, postcode, city\n// telefoons (ruw): workTel (of phone), companyTel, mobile (optioneel)\n// social (optioneel): facebookUrl, linkedinUrl\n// slug (optioneel)\n\nfunction initials(name) {\n const p = String(name || \"\").trim().split(/\\s+/).filter(Boolean);\n if (!p.length) return \"\";\n if (p.length === 1) return p[0].slice(0, 2).toUpperCase();\n return (p[0][0] + p[p.length - 1][0]).toUpperCase();\n}\n\nfunction slugify(s) {\n return String(s || \"\")\n .toLowerCase()\n .normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\nfunction escHtml(v) {\n return String(v ?? \"\")\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction digits(s) {\n return String(s || \"\").replace(/\\D+/g, \"\");\n}\n\nfunction toE164NL(raw) {\n const d = digits(raw);\n if (!d) return \"\";\n if (String(raw || \"\").trim().startsWith(\"+\")) return String(raw).trim();\n if (d.startsWith(\"0\")) return \"+31\" + d.slice(1);\n if (d.startsWith(\"31\")) return \"+\" + d;\n return \"+\" + d;\n}\n\nfunction formatNLDisplay(raw) {\n const d = digits(raw);\n if (!d) return \"\";\n if (d.length === 10 && d.startsWith(\"088\")) return `${d.slice(0, 3)} ${d.slice(3, 6)} ${d.slice(6)}`;\n if (d.length === 10 && d.startsWith(\"06\")) return `${d.slice(0, 2)} ${d.slice(2)}`;\n return String(raw || \"\");\n}\n\nconst d0 = items[0].json;\n\nconst company = d0.company || \"De Wit Transport\";\nconst name = d0.name || \"\";\nconst title = d0.title || \"\";\nconst email = d0.email || \"\";\nconst website = d0.website || \"\";\n\nconst workTelRaw = d0.workTel ?? d0.phone ?? \"\";\nconst mobileRaw = d0.mobile ?? \"\";\nconst companyTelRaw = d0.companyTel ?? \"\";\n\nconst slug = d0.slug ? slugify(d0.slug) : slugify(name);\nconst cardUrl = d0.cardUrl || `https://cards.tmsconnector.nl/${slug}`;\n\nconst mapsQuery = `${d0.street || \"\"} ${d0.postcode || \"\"} ${d0.city || \"\"}`.trim();\nconst mapsUrl = d0.mapsUrl || `https://www.google.com/maps?q=${encodeURIComponent(mapsQuery)}`;\n\nconst workTelE164 = d0.workTelE164 || toE164NL(workTelRaw);\nconst workTelDisplay = d0.workTelDisplay || formatNLDisplay(workTelRaw) || workTelRaw;\n\nconst mobileE164 = d0.mobileE164 || (mobileRaw ? toE164NL(mobileRaw) : \"\");\nconst mobileDisplay = d0.mobileDisplay || (mobileRaw ? formatNLDisplay(mobileRaw) : \"\");\n\nconst companyTelE164 = d0.companyTelE164 || (companyTelRaw ? toE164NL(companyTelRaw) : \"\");\nconst companyTelDisplay = d0.companyTelDisplay || (companyTelRaw ? formatNLDisplay(companyTelRaw) : \"\");\n\nconst facebookUrl = d0.facebookUrl ?? \"https://www.facebook.com/profile.php?id=100063917050863\";\nconst linkedinUrl = d0.linkedinUrl ?? \"https://www.linkedin.com/company/de-wit-transport/\";\n\n// ==== Umami config ====\nconst UMAMI_SCRIPT = \"https://analytics.tmsconnector.nl/script.js\";\nconst UMAMI_WEBSITE_ID = \"27321573-6471-41b3-9e0d-0e2c57615d14\";\nconst UMAMI_DOMAINS = \"cards.tmsconnector.nl,card.dewittransport.nl\";\n\n// ==== CSS versie ====\nconst CSS_VERSION = \"20260310-1\";\n\nconst html = `\n\n\n \n \n Visitekaartje | ${escHtml(name)}\n\n \n \n \n\n \n \n \n \n\n \n\n \n \n\n\n
\n
\n
\n
\n \"${escHtml(company)}\"\n\n
${escHtml(company)}
\n
\n
\n\n
\n \n \n \n\n \n \n \n\n \n \n \n
\n\n
\n
\n
\n

${escHtml(name)}

\n ${title ? `

${escHtml(title)}

` : \"\"}\n
\n
${escHtml(initials(name))}
\n
\n\n
\n
\n

Contactgegevens

\n \n
\n\n
\n

Adres

\n \n
\n
\n
\n\n
\n \n \n
\n
\n
\n\n
\n
\n
\n
Deel dit kaartje
\n \n
\n
\n
\n \n
\n
\n \n \n
\n
\n
\n
\n
\n
\n\n \n \n\n`;\n\nconst dataBuffer = Buffer.from(html, \"utf8\");\n\nreturn [{\n json: {\n slug,\n path: `${slug}/index.html`,\n cardUrl\n },\n binary: {\n data: await this.helpers.prepareBinaryData(dataBuffer, \"index.html\", \"text/html\")\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, -368 ], "id": "805af8c4-8dd1-409d-9e6d-2ec048e5f91c", "name": "Code in JavaScript" }, { "parameters": { "mode": "raw", "jsonOutput": "{\n \"name\": \"Eric de Wit\",\n \"title\": \"Commercieel directeur\",\n \"company\": \"De Wit Transport\",\n \"email\": \"e.dewit@dewittransport.nl\",\n \"website\": \"https://www.dewittransport.nl\",\n\n \"workTel\": \"088665392\",\n \"companyTel\": \"0886653300\",\n \"mobile\": \"0651316371\",\n\n \"street\": \"Haarlemmerstraatweg 52\",\n \"postcode\": \"2343 LB\",\n \"city\": \"Oegstgeest\",\n\n \"facebookUrl\": \"https://www.facebook.com/profile.php?id=100063917050863\",\n \"linkedinUrl\": \"https://www.linkedin.com/company/de-wit-transport/\"\n}\n", "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ -96, -368 ], "id": "eec908ce-ab3c-43b0-af18-7e0559ecb9e1", "name": "Edit Fields" }, { "parameters": { "protocol": "sftp", "operation": "upload", "path": "=/cards/{{ $json.path }}", "options": {} }, "type": "n8n-nodes-base.ftp", "typeVersion": 1, "position": [ 336, -368 ], "id": "aa3ddd75-e9dc-4aed-8d98-9f05a4867d67", "name": "FTP", "credentials": { "sftp": { "id": "uKyzg5cSXQqXOuHI", "name": "SFTP n8n" } } }, { "parameters": { "protocol": "sftp", "operation": "list", "path": "/cards/", "options": {} }, "type": "n8n-nodes-base.ftp", "typeVersion": 1, "position": [ 144, -656 ], "id": "7fd74991-605e-4854-a0e3-0b4fb686f638", "name": "FTP1", "credentials": { "sftp": { "id": "uKyzg5cSXQqXOuHI", "name": "SFTP n8n" } } } ], "pinData": {}, "connections": { "When clicking ‘Execute workflow’": { "main": [ [ { "node": "Edit Fields", "type": "main", "index": 0 } ] ] }, "Edit Fields": { "main": [ [ { "node": "Code in JavaScript", "type": "main", "index": 0 } ] ] }, "Code in JavaScript": { "main": [ [ { "node": "FTP", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1", "availableInMCP": false }, "versionId": "bd68247e-cb5a-49bd-aa67-15d2b868821b", "meta": { "templateCredsSetupCompleted": true, "instanceId": "22b0779b2e76c14be6b62c9c2bf1df5938c4e0bee54f033e17614db1892a6369" }, "id": "HX3DFRGFN9ZG7adu0wfsT", "tags": [] }