{
  "id": "GPKQHbK0ytLztiaT",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Dead Man's Switch for Solo Founders",
  "tags": [],
  "nodes": [
    {
      "id": "trigger-schedule",
      "name": "Daily Check (9 AM)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "read-checkins",
      "name": "Read Check-in Log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        224,
        0
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1thTJ-MtGvJnK6Qo3waeAhkAqto748g_dscSa6V7NW2w/edit#gid=0",
          "cachedResultName": "CheckIns"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1thTJ-MtGvJnK6Qo3waeAhkAqto748g_dscSa6V7NW2w/edit?gid=0#gid=0"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "calc-hours",
      "name": "Calculate Hours Since Last Check-in",
      "type": "n8n-nodes-base.code",
      "position": [
        448,
        0
      ],
      "parameters": {
        "jsCode": "const rows = $input.all();\nif (rows.length === 0) {\n  return [{ json: { hoursSinceCheckIn: 9999, lastCheckIn: 'never', status: 'CRITICAL' } }];\n}\nconst configRow = rows[0];\nconst lastRow = rows[rows.length - 1];\nconst lastCheckIn = new Date(lastRow.json.timestamp);\nconst now = new Date();\nconst hoursDiff = (now - lastCheckIn) / (1000 * 60 * 60);\nconst threshold = configRow.json.threshold_hours ? parseInt(configRow.json.threshold_hours) : 24;\n\nlet status = 'OK';\nif (hoursDiff > threshold * 2) {\n  status = 'CRITICAL';\n} else if (hoursDiff > threshold) {\n  status = 'WARNING';\n}\n\nreturn [{\n  json: {\n    hoursSinceCheckIn: Math.round(hoursDiff * 10) / 10,\n    lastCheckIn: lastCheckIn.toISOString(),\n    thresholdHours: threshold,\n    status,\n    founderName: configRow.json.founder_name || 'Founder',\n    founderEmail: configRow.json.founder_email || '',\n    emergencyContact1: configRow.json.emergency_contact_1 || '',\n    emergencyContact2: configRow.json.emergency_contact_2 || '',\n    emergencyMessage: configRow.json.emergency_message || 'This is an automated message. I have not checked in to my Dead Mans Switch in over ' + Math.round(hoursDiff) + ' hours. Please check on me.'\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "check-status",
      "name": "Status OK?",
      "type": "n8n-nodes-base.if",
      "position": [
        672,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "status-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "OK"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "no-action",
      "name": "All Good - No Action",
      "type": "n8n-nodes-base.set",
      "position": [
        880,
        -128
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "msg",
              "name": "message",
              "type": "string",
              "value": "Check-in is current. No action needed."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "check-critical",
      "name": "Is Critical?",
      "type": "n8n-nodes-base.if",
      "position": [
        880,
        128
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "critical-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "CRITICAL"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "send-reminder",
      "name": "Send Reminder to Founder",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1104,
        240
      ],
      "parameters": {
        "sendTo": "={{ $('Calculate Hours Since Last Check-in').item.json.founderEmail }}",
        "message": "=Hi {{ $('Calculate Hours Since Last Check-in').item.json.founderName }},\n\nThis is your Dead Mans Switch reminder. You havent checked in for {{ $('Calculate Hours Since Last Check-in').item.json.hoursSinceCheckIn }} hours.\n\nYour threshold is set to {{ $('Calculate Hours Since Last Check-in').item.json.thresholdHours }} hours.\n\nClick your check-in link to reset the timer.\n\nIf you dont check in soon, your emergency contacts will be notified.",
        "options": {},
        "subject": "Dead Mans Switch: You Havent Checked In"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "send-emergency-1",
      "name": "Alert Emergency Contact 1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1104,
        0
      ],
      "parameters": {
        "sendTo": "={{ $('Calculate Hours Since Last Check-in').item.json.emergencyContact1 }}",
        "message": "={{ $('Calculate Hours Since Last Check-in').item.json.emergencyMessage }}\n\nLast check-in was {{ $('Calculate Hours Since Last Check-in').item.json.hoursSinceCheckIn }} hours ago.\n\nThis is an automated Dead Mans Switch alert.",
        "options": {},
        "subject": "=URGENT: {{ $('Calculate Hours Since Last Check-in').item.json.founderName }} Has Not Checked In"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "send-emergency-2",
      "name": "Alert Emergency Contact 2",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1328,
        0
      ],
      "parameters": {
        "sendTo": "={{ $('Calculate Hours Since Last Check-in').item.json.emergencyContact2 }}",
        "message": "={{ $('Calculate Hours Since Last Check-in').item.json.emergencyMessage }}\n\nLast check-in was {{ $('Calculate Hours Since Last Check-in').item.json.hoursSinceCheckIn }} hours ago.\n\nThis is an automated Dead Mans Switch alert.",
        "options": {},
        "subject": "=URGENT: {{ $('Calculate Hours Since Last Check-in').item.json.founderName }} Has Not Checked In"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "log-alert",
      "name": "Log Alert to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1552,
        0
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "={{ $('Calculate Hours Since Last Check-in').item.json.status }}",
            "timestamp": "={{ $now.toISO() }}",
            "hours_since_checkin": "={{ $('Calculate Hours Since Last Check-in').item.json.hoursSinceCheckIn }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hours_since_checkin",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "hours_since_checkin",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "AlertLog"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1thTJ-MtGvJnK6Qo3waeAhkAqto748g_dscSa6V7NW2w/edit?gid=1462250637#gid=1462250637"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "checkin-webhook",
      "name": "Check-in Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        0,
        352
      ],
      "parameters": {
        "path": "dead-mans-switch-checkin",
        "options": {},
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "record-checkin",
      "name": "Record Check-in",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        224,
        352
      ],
      "parameters": {
        "columns": {
          "value": {
            "source": "webhook",
            "timestamp": "={{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "source",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1thTJ-MtGvJnK6Qo3waeAhkAqto748g_dscSa6V7NW2w/edit#gid=0",
          "cachedResultName": "CheckIns"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1thTJ-MtGvJnK6Qo3waeAhkAqto748g_dscSa6V7NW2w",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1thTJ-MtGvJnK6Qo3waeAhkAqto748g_dscSa6V7NW2w/edit?usp=drivesdk",
          "cachedResultName": "DeadMan"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "checkin-confirm",
      "name": "Confirm Check-in",
      "type": "n8n-nodes-base.set",
      "position": [
        448,
        352
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "confirm-msg",
              "name": "message",
              "type": "string",
              "value": "Check-in recorded. Your Dead Mans Switch timer has been reset."
            },
            {
              "id": "confirm-time",
              "name": "checkedInAt",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "sticky-overview",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        -384
      ],
      "parameters": {
        "width": 420,
        "height": 760,
        "content": "## Dead Man's Switch for Solo Founders\nA personal safety net for solo founders, freelancers, and one-person businesses. If you stop checking in, your emergency contacts get alerted automatically.\n\n### How it works\n1. **Bookmark your check-in URL** and visit it daily to reset the timer\n2. Every day at 9 AM, the workflow checks how long since your last check-in\n3. **Past threshold** (default 24h) \u2014 you get a reminder email\n4. **Past 2x threshold** (48h) \u2014 your emergency contacts are alerted\n5. Every alert is logged to a Google Sheet for a full audit trail\n\n### Setup\n1. Create a Google Sheet with two tabs: **CheckIns** and **AlertLog**\n2. In **CheckIns**, add columns: `timestamp`, `source`, `founder_name`, `founder_email`, `emergency_contact_1`, `emergency_contact_2`, `emergency_message`, `threshold_hours`\n3. In **AlertLog**, add columns: `timestamp`, `status`, `hours_since_checkin`\n4. Add one seed row in CheckIns with your details and threshold (e.g. 24)\n5. Paste your Google Sheet URL into the three Google Sheets nodes\n6. Connect your **Gmail OAuth2** and **Google Sheets** credentials\n7. Activate the workflow and bookmark the webhook URL"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-monitoring",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        -384
      ],
      "parameters": {
        "width": 560,
        "height": 200,
        "content": "### Daily Monitoring\nRuns every day at 9 AM. Reads all check-in rows from Google Sheets, then calculates how many hours have passed since the last check-in. Compares against your configured threshold to determine status: **OK**, **WARNING**, or **CRITICAL**."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-routing",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        -512
      ],
      "parameters": {
        "width": 300,
        "height": 344,
        "content": "### Status Routing\nIf status is **OK**, no action is taken. Otherwise, it checks whether the situation is **CRITICAL** (past 2x threshold) or just a **WARNING** (past 1x threshold) and routes accordingly."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-escalation",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1168,
        -496
      ],
      "parameters": {
        "width": 580,
        "height": 276,
        "content": "### Alert Escalation\n**CRITICAL path** \u2014 Emails both emergency contacts sequentially, then logs the alert to the AlertLog sheet tab for a full audit trail.\n\n**WARNING path** \u2014 Sends a reminder email only to the founder, prompting them to check in before it escalates to emergency contacts."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-checkin",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        544
      ],
      "parameters": {
        "width": 560,
        "height": 168,
        "content": "### Check-in Endpoint\nA simple webhook URL you bookmark and visit to check in. Records the timestamp to Google Sheets and returns a confirmation message. This is how you reset your dead man's switch timer each day."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "timezone": "America/New_York",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "b6bb63b5-00ad-4ba6-beca-9db8568e23de",
  "connections": {
    "Status OK?": {
      "main": [
        [
          {
            "node": "All Good - No Action",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Is Critical?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Critical?": {
      "main": [
        [
          {
            "node": "Alert Emergency Contact 1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Reminder to Founder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Record Check-in": {
      "main": [
        [
          {
            "node": "Confirm Check-in",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check-in Webhook": {
      "main": [
        [
          {
            "node": "Record Check-in",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Check-in Log": {
      "main": [
        [
          {
            "node": "Calculate Hours Since Last Check-in",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Check (9 AM)": {
      "main": [
        [
          {
            "node": "Read Check-in Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Emergency Contact 1": {
      "main": [
        [
          {
            "node": "Alert Emergency Contact 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Emergency Contact 2": {
      "main": [
        [
          {
            "node": "Log Alert to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Hours Since Last Check-in": {
      "main": [
        [
          {
            "node": "Status OK?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}