diff --git a/21-Server Reference/homelab/stacks/n8n/JW_Backup/Git_Sync.tsk(1).xml b/21-Server Reference/homelab/stacks/n8n/JW_Backup/Git_Sync.tsk(1).xml
new file mode 100644
index 0000000..19d4591
--- /dev/null
+++ b/21-Server Reference/homelab/stacks/n8n/JW_Backup/Git_Sync.tsk(1).xml
@@ -0,0 +1,71 @@
+
+
+ 1774931800563
+ 1774932946532
+ 9
+ Git Sync
+
+ 107361459
+
+
+ <null>
+ java.lang.String
+ <null>
+ java.lang.String
+ Actions To Perform: openApp(com.viscouspot.gitsync)
+
+click(text,SYNC CHANGES)
+
+backOutOfApp()
+Not In AutoInput: true
+Not In Tasker: true
+Separator: ,
+Check Millis: 1000
+ java.lang.String
+ parameters
+ java.lang.String
+ <StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%ailastbounds
+Last Bounds
+Bounds (left,top,right,bottom) of the item that the action last interacted with</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1>%ailastcoordinates
+Last Coordinates
+Center coordinates (x,y) of the item that the action last interacted with</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2>%err
+Error Code
+Only available if you select <b>Continue Task After Error</b> and the action ends in error</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3>%errmsg
+Error Message
+Only available if you select <b>Continue Task After Error</b> and the action ends in error</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3></StringArray>
+ [Ljava.lang.String;
+ parameters plugininstanceid plugintypeid
+ java.lang.String
+ true
+ java.lang.Boolean
+ {"_action":"openApp(com.viscouspot.gitsync)\n\nclick(text,SYNC CHANGES)\n\nbackOutOfApp()","_additionalOptions":{"checkMs":"1000","separator":",","withCoordinates":false},"_whenToPerformAction":{"notInAutoInput":true,"notInTasker":true},"generatedValues":{}}
+ java.lang.String
+ 5910f160-ad6a-4b47-ab40-810a62e77df1
+ java.lang.String
+ com.joaomgcd.autoinput.intent.IntentActionv2
+ java.lang.String
+
+
+ com.joaomgcd.autoinput
+ com.joaomgcd.autoinput.activity.ActivityConfigActionv2
+
+
+
+
+ 130
+ JWL_Merge
+
+ %priority
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/21-Server Reference/homelab/stacks/n8n/JW_Backup/JW Library Sync(1).json b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JW Library Sync(1).json
new file mode 100644
index 0000000..f32a9a9
--- /dev/null
+++ b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JW Library Sync(1).json
@@ -0,0 +1,175 @@
+{
+ "name": "JW Library Sync",
+ "nodes": [
+ {
+ "parameters": {
+ "command": "bash /home/artanis/Documents/JW_Backup_Sync_Engine.sh"
+ },
+ "type": "n8n-nodes-base.ssh",
+ "typeVersion": 1,
+ "position": [
+ 112,
+ -112
+ ],
+ "id": "5a156815-edbb-4c08-9e7d-75f98c2f6c39",
+ "name": "Execute a command",
+ "alwaysOutputData": true,
+ "credentials": {
+ "sshPassword": {
+ "id": "wILbpFcpVSKcewXl",
+ "name": "Homelab Login"
+ }
+ },
+ "onError": "continueErrorOutput"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "sync-jw-backup",
+ "responseMode": "responseNode",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -112,
+ -112
+ ],
+ "id": "37b4ca1b-8910-41d5-8b1f-e7696b71f07f",
+ "name": "Webhook",
+ "webhookId": "5e348016-4d6e-4226-a5dc-c91eb7d6ea0e"
+ },
+ {
+ "parameters": {
+ "authentication": "webhook",
+ "content": "=JW SYNC ERROR:\n {{ $json.stderr }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.discord",
+ "typeVersion": 2,
+ "position": [
+ 336,
+ -16
+ ],
+ "id": "abac265b-78c6-4bc0-9ba9-f846d39eefa8",
+ "name": "Discord",
+ "webhookId": "4f823df1-38b6-4a5b-ae32-2fc586a9aa9b",
+ "credentials": {
+ "discordWebhookApi": {
+ "id": "0i1bW7qtePtHMHjA",
+ "name": "SV98"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "respondWith": "text",
+ "responseBody": "Merge Successful",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.respondToWebhook",
+ "typeVersion": 1.5,
+ "position": [
+ 560,
+ -208
+ ],
+ "id": "be993bb8-c654-42d1-9bea-7d6ffbd75db9",
+ "name": "Respond to Webhook"
+ },
+ {
+ "parameters": {
+ "respondWith": "text",
+ "responseBody": "Merge Failed",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.respondToWebhook",
+ "typeVersion": 1.5,
+ "position": [
+ 560,
+ -16
+ ],
+ "id": "daa52075-9bd6-4425-a9d5-8763d935a372",
+ "name": "Respond to Webhook1"
+ }
+ ],
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "user-agent": "Tasker/6.6.20 (Android/16)",
+ "content-type": "application/json",
+ "content-length": "33",
+ "host": "n8n.bunny-wyvern.ts.net:5678",
+ "connection": "Keep-Alive",
+ "accept-encoding": "gzip"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "device": "Samsung-Tablet-S10+"
+ },
+ "webhookUrl": "http://n8n.bunny-wyvern.ts.net:5678/webhook/sync-jw-backup",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Execute a command",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Execute a command": {
+ "main": [
+ [
+ {
+ "node": "Respond to Webhook",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Discord",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Discord": {
+ "main": [
+ [
+ {
+ "node": "Respond to Webhook1",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "active": true,
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate"
+ },
+ "versionId": "e3c5e92f-e32e-4e76-88bb-5167c0c4896c",
+ "meta": {
+ "templateCredsSetupCompleted": true,
+ "instanceId": "cb40080ef54f0b350fa960324602081324276be1181221a02a674c62336f7933"
+ },
+ "id": "rmbJkjlgZi5hbRpg",
+ "tags": []
+}
\ No newline at end of file
diff --git a/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Backup_To_Git.tsk(1).xml b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Backup_To_Git.tsk(1).xml
new file mode 100644
index 0000000..f5ac0d9
--- /dev/null
+++ b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Backup_To_Git.tsk(1).xml
@@ -0,0 +1,151 @@
+
+
+ 1774912401659
+ 1774991619042
+ 3
+ JWL_Backup_To_Git
+ 100
+
+ 18
+
+ org.jw.jwlibrary.mobile.MainActivity
+ org.jw.jwlibrary.mobile
+
+
+
+
+
+ 30
+
+
+
+
+
+
+
+ 20
+
+ org.jw.jwlibrary.mobile.MainActivity
+ org.jw.jwlibrary.mobile
+
+
+
+
+
+
+
+ 30
+
+
+
+
+
+
+
+ 107361459
+
+
+ <null>
+ java.lang.String
+ <null>
+ java.lang.String
+ Actions To Perform: click(id,org.jw.jwlibrary.mobile:id/nav_personal_study)
+
+click(id,org.jw.jwlibrary.mobile:id/action_backup_restore)
+
+click(text,Create Backup)
+Not In AutoInput: true
+Not In Tasker: true
+Separator: ,
+Check Millis: 1000
+ java.lang.String
+ parameters
+ java.lang.String
+ parameters plugininstanceid plugintypeid
+ java.lang.String
+ true
+ java.lang.Boolean
+ {"_action":"click(id,org.jw.jwlibrary.mobile:id/nav_personal_study)\n\nclick(id,org.jw.jwlibrary.mobile:id/action_backup_restore)\n\nclick(text,Create Backup)","_additionalOptions":{"checkMs":"1000","separator":",","withCoordinates":false},"_whenToPerformAction":{"notInAutoInput":true,"notInTasker":true},"generatedValues":{}}
+ java.lang.String
+ 4a568374-2445-46f3-be31-a879d2940e36
+ java.lang.String
+ com.joaomgcd.autoinput.intent.IntentActionv2
+ java.lang.String
+
+
+ com.joaomgcd.autoinput
+ com.joaomgcd.autoinput.activity.ActivityConfigActionv2
+
+
+
+
+ 30
+
+
+
+
+
+
+
+ 107361459
+
+
+ <null>
+ java.lang.String
+ <null>
+ java.lang.String
+ Actions To Perform: click(text,Save Locally)
+
+click(id,android:id/button1)
+Not In AutoInput: true
+Not In Tasker: true
+Separator: ,
+Check Millis: 1000
+ java.lang.String
+ parameters
+ java.lang.String
+ <StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%ailastbounds
+Last Bounds
+Bounds (left,top,right,bottom) of the item that the action last interacted with</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1>%ailastcoordinates
+Last Coordinates
+Center coordinates (x,y) of the item that the action last interacted with</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2>%err
+Error Code
+Only available if you select <b>Continue Task After Error</b> and the action ends in error</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3>%errmsg
+Error Message
+Only available if you select <b>Continue Task After Error</b> and the action ends in error</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3></StringArray>
+ [Ljava.lang.String;
+ parameters plugininstanceid plugintypeid
+ java.lang.String
+ true
+ java.lang.Boolean
+ {"_action":"click(text,Save Locally)\n\nclick(id,android:id/button1)","_additionalOptions":{"checkMs":"1000","separator":",","withCoordinates":false},"_whenToPerformAction":{"notInAutoInput":true,"notInTasker":true},"generatedValues":{}}
+ java.lang.String
+ babe5b2c-f87a-4a8a-ab34-6a891fce327c
+ java.lang.String
+ com.joaomgcd.autoinput.intent.IntentActionv2
+ java.lang.String
+
+
+ com.joaomgcd.autoinput
+ com.joaomgcd.autoinput.activity.ActivityConfigActionv2
+
+
+
+
+ 130
+ Git Sync
+
+ %priority
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Merge.tsk(1).xml b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Merge.tsk(1).xml
new file mode 100644
index 0000000..a569add
--- /dev/null
+++ b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Merge.tsk(1).xml
@@ -0,0 +1,86 @@
+
+
+ 1774931254224
+ 1774986287495
+ 8
+ JWL_Merge
+
+ 339
+
+
+ <StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%http_cookies
+Cookies
+The cookies the server sent in the response in the Cookie:COOKIE_VALUE format. You can use this directly in the 'Headers' field of the HTTP Request action</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1>%http_data
+Data
+Data that the server responded from the HTTP request.</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2>%http_file_output
+File Output
+Will always contain the file's full path even if you specified a directory as the File to save.</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3>%http_response_code
+Response Code
+The HTTP Code the server responded</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES4>%http_headers()
+Response Headers
+The HTTP Headers the server sent in the response. Each header is in the 'key:value' format</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES4><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES5>%http_response_length
+Response Length
+The size of the response in bytes</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES5></StringArray>
+ [Ljava.lang.String;
+
+
+
+
+
+
+ http://n8n.bunny-wyvern.ts.net:5678/webhook/sync-jw-backup
+
+
+ {"device": "Samsung-Tablet-S10+"}
+
+
+
+
+
+
+ 30
+
+
+
+
+
+
+
+ 37
+
+
+ %http_data
+ 2
+ *Successful*
+
+
+
+
+ 30
+
+
+
+
+
+
+
+ 130
+ JWL_Restore_From_Git
+
+ %priority+1
+
+
+
+
+
+
+
+
+
+
+
+
+ 38
+
+
+
diff --git a/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Restore_From_Git.tsk(1).xml b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Restore_From_Git.tsk(1).xml
new file mode 100644
index 0000000..23e5b68
--- /dev/null
+++ b/21-Server Reference/homelab/stacks/n8n/JW_Backup/JWL_Restore_From_Git.tsk(1).xml
@@ -0,0 +1,127 @@
+
+
+ 1774912401659
+ 1774991723740
+ 5
+ JWL_Restore_From_Git
+ 100
+
+ 130
+ false
+ Git Sync
+
+ %priority+1
+
+
+
+
+
+
+
+
+
+
+
+
+ 30
+ false
+
+
+
+
+
+
+
+ 18
+ false
+
+ org.jw.jwlibrary.mobile.MainActivity
+ org.jw.jwlibrary.mobile
+
+
+
+
+
+ 30
+ false
+
+
+
+
+
+
+
+ 20
+ false
+
+ org.jw.jwlibrary.mobile.MainActivity
+ org.jw.jwlibrary.mobile
+
+
+
+
+
+
+
+ 30
+ false
+
+
+
+
+
+
+
+ 102
+ Vault/JW_Backups/master.jwlibrary
+
+
+
+ 107361459
+
+
+ <null>
+ java.lang.String
+ <null>
+ java.lang.String
+ Actions To Perform: click(text,RESTORE)
+
+click(text,CLOSE)
+
+backOutOfApp()
+Not In AutoInput: true
+Not In Tasker: true
+Separator: ,
+Check Millis: 1000
+ java.lang.String
+ parameters
+ java.lang.String
+ <StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%ailastbounds
+Last Bounds
+Bounds (left,top,right,bottom) of the item that the action last interacted with</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1>%ailastcoordinates
+Last Coordinates
+Center coordinates (x,y) of the item that the action last interacted with</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2>%err
+Error Code
+Only available if you select <b>Continue Task After Error</b> and the action ends in error</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3>%errmsg
+Error Message
+Only available if you select <b>Continue Task After Error</b> and the action ends in error</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3></StringArray>
+ [Ljava.lang.String;
+ parameters plugininstanceid plugintypeid
+ java.lang.String
+ true
+ java.lang.Boolean
+ {"_action":"click(text,RESTORE)\n\nclick(text,CLOSE)\n\nbackOutOfApp()","_additionalOptions":{"checkMs":"1000","separator":",","withCoordinates":false},"_whenToPerformAction":{"notInAutoInput":true,"notInTasker":true},"generatedValues":{}}
+ java.lang.String
+ 952ed8a8-d00f-4278-bb41-07599243b5f1
+ java.lang.String
+ com.joaomgcd.autoinput.intent.IntentActionv2
+ java.lang.String
+
+
+ com.joaomgcd.autoinput
+ com.joaomgcd.autoinput.activity.ActivityConfigActionv2
+
+
+
+
+