{
  "name": "Client Onboarding (ep09)",
  "nodes": [
    {
      "parameters": {
        "formTitle": "New client intake \u2014 Northgate Labs",
        "formDescription": "Five minutes now saves us both a week of email.",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Company name",
              "placeholder": "Acme Inc.",
              "requiredField": true
            },
            {
              "fieldLabel": "Contact name",
              "placeholder": "Who signs off?",
              "requiredField": true
            },
            {
              "fieldLabel": "Contact email",
              "fieldType": "email",
              "requiredField": true
            },
            {
              "fieldLabel": "Project type",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Automation retainer"
                  },
                  {
                    "option": "Website build"
                  },
                  {
                    "option": "Ongoing support"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Kickoff date",
              "fieldType": "date",
              "requiredField": true
            },
            {
              "fieldLabel": "Main goal for the first 90 days",
              "fieldType": "textarea",
              "requiredField": true
            }
          ]
        },
        "options": {}
      },
      "id": "e9000000-0000-4000-8000-000000000001",
      "name": "New client intake",
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.2,
      "position": [
        200,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// One folder per client, plus a welcome doc from a template.\nconst fs = require('fs');\nconst path = require('path');\nconst base = $env.EP09_DIR;\nconst j = $input.first().json;\n\nconst slug = j['Company name'].toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');\nconst dir = path.join(base, 'clients', slug);\nfs.mkdirSync(dir, { recursive: true });\n\nlet doc = fs.readFileSync(path.join(base, 'templates', 'welcome-template.md'), 'utf8');\ndoc = doc.replace(/{{company}}/g, j['Company name'])\n  .replace(/{{contact}}/g, j['Contact name'])\n  .replace(/{{goal}}/g, j['Main goal for the first 90 days'])\n  .replace(/{{kickoff}}/g, String(j['Kickoff date']).slice(0, 10));\nfs.writeFileSync(path.join(dir, 'welcome.md'), doc);\n\nj.slug = slug;\nj.dir = dir;\nreturn $input.all();"
      },
      "id": "e9000000-0000-4000-8000-000000000002",
      "name": "Client folder + welcome doc",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        420,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Contract from a template. SAMPLE ribbon stays in \u2014 fictional client, fictional terms.\nconst fs = require('fs');\nconst path = require('path');\nconst base = $env.EP09_DIR;\nconst j = $input.first().json;\n\nlet html = fs.readFileSync(path.join(base, 'templates', 'contract-template.html'), 'utf8');\nhtml = html.replace(/{{company}}/g, j['Company name'])\n  .replace(/{{contact}}/g, j['Contact name'])\n  .replace(/{{project}}/g, j['Project type'])\n  .replace(/{{kickoff}}/g, String(j['Kickoff date']).slice(0, 10))\n  .replace(/{{date_today}}/g, new Date().toISOString().slice(0, 10));\nfs.writeFileSync(path.join(j.dir, 'contract.html'), html);\nreturn $input.all();"
      },
      "id": "e9000000-0000-4000-8000-000000000003",
      "name": "Contract from template",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        640,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// A real calendar invite: 45 minutes, 10:00 local, on the kickoff date.\nconst fs = require('fs');\nconst path = require('path');\nconst j = $input.first().json;\n\nconst d = String(j['Kickoff date']).slice(0, 10).replace(/-/g, '');\nconst ics = [\n  'BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Northgate Labs//Onboarding//EN',\n  'BEGIN:VEVENT', 'UID:' + j.slug + '-kickoff@shipsitself.local',\n  'DTSTART:' + d + 'T100000', 'DTEND:' + d + 'T104500',\n  'SUMMARY:Kickoff - ' + j['Company name'],\n  'DESCRIPTION:First 90 days: ' + j['Main goal for the first 90 days'].replace(/\\n/g, ' '),\n  'END:VEVENT', 'END:VCALENDAR',\n].join('\\r\\n');\nfs.writeFileSync(path.join(j.dir, 'kickoff.ics'), ics);\nreturn $input.all();"
      },
      "id": "e9000000-0000-4000-8000-000000000004",
      "name": "Kickoff invite (.ics)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        860,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// One CRM: a CSV I can open, sort, and grep. Header written on first run.\nconst fs = require('fs');\nconst path = require('path');\nconst base = $env.EP09_DIR;\nconst j = $input.first().json;\n\nconst file = path.join(base, 'crm', 'crm.csv');\nif (!fs.existsSync(file)) {\n  fs.writeFileSync(file, 'Company,Contact,Email,Project,Kickoff,Status,Created\\n');\n}\nconst esc = (v) => '\"' + String(v).replace(/\"/g, '\"\"') + '\"';\nconst row = [\n  j['Company name'], j['Contact name'], j['Contact email'], j['Project type'],\n  String(j['Kickoff date']).slice(0, 10), 'Onboarding', new Date().toISOString(),\n].map(esc).join(',');\nfs.appendFileSync(file, row + '\\n');\nreturn $input.all();"
      },
      "id": "e9000000-0000-4000-8000-000000000005",
      "name": "CRM row",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1080,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Task checklist with real dates: T+1, T+3, T+7 from kickoff.\nconst fs = require('fs');\nconst path = require('path');\nconst base = $env.EP09_DIR;\nconst j = $input.first().json;\n\nconst kick = String(j['Kickoff date']).slice(0, 10);\nconst plus = (n) => {\n  const t = new Date(kick);\n  t.setDate(t.getDate() + n);\n  return t.toISOString().slice(0, 10);\n};\nlet md = fs.readFileSync(path.join(base, 'templates', 'checklist-template.md'), 'utf8');\nmd = md.replace(/{{company}}/g, j['Company name'])\n  .replace(/{{contact}}/g, j['Contact name'])\n  .replace(/{{kickoff}}/g, kick)\n  .replace(/{{t1}}/g, plus(1)).replace(/{{t3}}/g, plus(3)).replace(/{{t7}}/g, plus(7));\nfs.writeFileSync(path.join(j.dir, 'tasks.md'), md);\nreturn $input.all();"
      },
      "id": "e9000000-0000-4000-8000-000000000006",
      "name": "Task checklist",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1300,
        300
      ]
    },
    {
      "parameters": {
        "operation": "completion",
        "completionTitle": "Onboarding complete",
        "completionMessage": "Folder, welcome doc, contract, calendar invite, CRM entry, and task checklist were just created.",
        "options": {}
      },
      "id": "e9000000-0000-4000-8000-000000000007",
      "name": "Done page",
      "type": "n8n-nodes-base.form",
      "typeVersion": 1,
      "position": [
        1520,
        300
      ]
    }
  ],
  "connections": {
    "New client intake": {
      "main": [
        [
          {
            "node": "Client folder + welcome doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Client folder + welcome doc": {
      "main": [
        [
          {
            "node": "Contract from template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Contract from template": {
      "main": [
        [
          {
            "node": "Kickoff invite (.ics)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Kickoff invite (.ics)": {
      "main": [
        [
          {
            "node": "CRM row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CRM row": {
      "main": [
        [
          {
            "node": "Task checklist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Task checklist": {
      "main": [
        [
          {
            "node": "Done page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}