diff --git a/roles/webcatalog/tasks/Darwin.yaml b/roles/webcatalog/tasks/Darwin.yaml
new file mode 100644
index 0000000..b42d672
--- /dev/null
+++ b/roles/webcatalog/tasks/Darwin.yaml
@@ -0,0 +1,5 @@
+---
+- name: install homebrew package
+  homebrew_cask:
+    name: webcatalog
+    state: latest
diff --git a/roles/webcatalog/tasks/Linux.yaml b/roles/webcatalog/tasks/Linux.yaml
new file mode 100644
index 0000000..f560698
--- /dev/null
+++ b/roles/webcatalog/tasks/Linux.yaml
@@ -0,0 +1,48 @@
+---
+- name: stat symlink
+  stat:
+    path: '{{ansible_env.HOME}}/.local/bin/WebCatalog'
+  register: symlink_file
+
+- name: get releases
+  uri:
+    url: https://raw.githubusercontent.com/kbenzie/webcatalog-release-scraper/main/webcatalog-releases.json
+    return_content: true
+  register: releases_raw
+
+- set_fact:
+    releases: '{{releases_raw.content | from_json}}'
+- set_fact:
+    appimage: 'WebCatalog-{{releases[0].version}}.AppImage'
+- set_fact:
+    filepath: '{{ansible_env.HOME}}/.local/bin/{{appimage}}'
+
+- set_fact:
+    needs_installed:
+      '{{not symlink_file.stat.exists or symlink_file.stat.lnk_source != filepath}}'
+
+- name: download latest version
+  when: needs_installed
+  get_url:
+    url: 'https://cdn-2.webcatalog.io/webcatalog/{{appimage}}'
+    dest: '{{ansible_env.HOME}}/.local/bin/{{appimage}}'
+    mode: '0755'
+
+- name: create symlink
+  file:
+    src: '{{filepath}}'
+    dest: '{{ansible_env.HOME}}/.local/bin/WebCatalog'
+    state: link
+
+# TODO: icon for desktop file
+
+- name: create desktop file
+  template:
+    src: webcatalog.desktop.j2
+    dest: '{{ansible_env.HOME}}/.local/share/applications/webcatalog-webcatalog.desktop'
+
+- name: remove old appimage
+  when: needs_installed and symlink_file.stat.exists
+  file:
+    path: '{{symlink_file.stat.lnk_source}}'
+    state: absent
diff --git a/roles/webcatalog/tasks/main.yaml b/roles/webcatalog/tasks/main.yaml
index 9e2432d..50c9a81 100644
--- a/roles/webcatalog/tasks/main.yaml
+++ b/roles/webcatalog/tasks/main.yaml
@@ -1,8 +1,7 @@
 ---
-- assert:
-    that: ansible_os_family == "Darwin"
-
-- name: install homebrew package
-  homebrew_cask:
-    name: webcatalog
-    state: latest
+- when: ansible_os_family == 'Darwin'
+  include_tasks: 'Darwin.yaml'
+- when: ansible_os_family == 'Windows'
+  include_tasks: 'Windows.yaml'
+- when: ansible_os_family != 'Darwin' and ansible_os_family != 'Windows'
+  include_tasks: 'Linux.yaml'
diff --git a/roles/webcatalog/templates/webcatalog.desktop.j2 b/roles/webcatalog/templates/webcatalog.desktop.j2
new file mode 100644
index 0000000..eacecf9
--- /dev/null
+++ b/roles/webcatalog/templates/webcatalog.desktop.j2
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Name=WebCatalog
+Exec={{ansible_env.HOME}}/.local/bin/WebCatalog
+Terminal=false
+Type=Application
+Icon=webcatalog
+StartupWMClass=WebCatalog
+X-AppImage-Version={{releases[0].version}}
+Comment=Turn Any Websites Into Real Desktop Apps
+MimeType=x-scheme-handler/webcatalog;
+Categories=Utility;