diff --git a/extensions/lock/js/package-lock.json b/extensions/lock/js/package-lock.json
index d252953fb..5f2957a9f 100644
--- a/extensions/lock/js/package-lock.json
+++ b/extensions/lock/js/package-lock.json
@@ -6,9 +6,14 @@
     "": {
       "name": "@flarum/lock",
       "dependencies": {
+        "@flarum/prettier-config": "^1.0.0",
+        "flarum-tsconfig": "^1.0.2",
         "flarum-webpack-config": "^1.0.0",
         "webpack": "^4.46.0",
-        "webpack-cli": "^4.9.0"
+        "webpack-cli": "^4.9.1"
+      },
+      "devDependencies": {
+        "prettier": "^2.5.1"
       }
     },
     "node_modules/@babel/code-frame": {
@@ -1617,16 +1622,44 @@
         "node": ">=10.0.0"
       }
     },
+    "node_modules/@flarum/prettier-config": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@flarum/prettier-config/-/prettier-config-1.0.0.tgz",
+      "integrity": "sha512-3/AcliIi5jPt4i7COb5hsLv6hm4EeXT9yI9I2EuEvhPi2QR+O9Y/8wrqRuO5mDkRzCIhUY+mjIL/f9770Zwfqg=="
+    },
     "node_modules/@polka/url": {
       "version": "1.0.0-next.21",
       "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
       "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g=="
     },
+    "node_modules/@types/jquery": {
+      "version": "3.5.12",
+      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.12.tgz",
+      "integrity": "sha512-AlX/K29WByFhZ3UbVVn8eywPFwhDZGc/qhDWgy5mu4VVr9b+OQZKBegtS6Tqi9pk8A1aXVrYXuLhnjFJX8Wc/w==",
+      "dependencies": {
+        "@types/sizzle": "*"
+      }
+    },
     "node_modules/@types/json-schema": {
       "version": "7.0.9",
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
       "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
     },
+    "node_modules/@types/mithril": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.8.tgz",
+      "integrity": "sha512-QzVV70DqUhWfLFpMFDBI9rRxtzeUUpbhiFDpUJYSV92AePgl+Qfficgv2MOb1Ceb+lBOQU8+L+Hjf2UielQjEw=="
+    },
+    "node_modules/@types/sizzle": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+      "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ=="
+    },
+    "node_modules/@types/throttle-debounce": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz",
+      "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ=="
+    },
     "node_modules/@webassemblyjs/ast": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -2821,6 +2854,11 @@
       "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
       "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
     },
+    "node_modules/dayjs": {
+      "version": "1.10.7",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
+      "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig=="
+    },
     "node_modules/debug": {
       "version": "4.3.2",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
@@ -3378,6 +3416,17 @@
         "node": ">=8"
       }
     },
+    "node_modules/flarum-tsconfig": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/flarum-tsconfig/-/flarum-tsconfig-1.0.2.tgz",
+      "integrity": "sha512-RUaN7D6noLK9vY1F86NIc+IlIP1YAA3bJ4jGR5pIm8UxvLBLW8qrAHzIosuQJgvnge7VgTA5c2LoNefUK/9EiQ==",
+      "dependencies": {
+        "@types/jquery": "^3.5.5",
+        "@types/mithril": "^2.0.7",
+        "@types/throttle-debounce": "^2.1.0",
+        "dayjs": "^1.10.4"
+      }
+    },
     "node_modules/flarum-webpack-config": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/flarum-webpack-config/-/flarum-webpack-config-1.0.0.tgz",
@@ -4699,6 +4748,18 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/prettier": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+      "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+      "dev": true,
+      "bin": {
+        "prettier": "bin-prettier.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
     "node_modules/process": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -6046,11 +6107,6 @@
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
     },
-    "node_modules/v8-compile-cache": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
-      "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA=="
-    },
     "node_modules/vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -6352,9 +6408,9 @@
       }
     },
     "node_modules/webpack-cli": {
-      "version": "4.9.0",
-      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz",
-      "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==",
+      "version": "4.9.1",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz",
+      "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==",
       "dependencies": {
         "@discoveryjs/json-ext": "^0.5.0",
         "@webpack-cli/configtest": "^1.1.0",
@@ -6367,7 +6423,6 @@
         "import-local": "^3.0.2",
         "interpret": "^2.2.0",
         "rechoir": "^0.7.0",
-        "v8-compile-cache": "^2.2.0",
         "webpack-merge": "^5.7.3"
       },
       "bin": {
@@ -7592,16 +7647,44 @@
       "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz",
       "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA=="
     },
+    "@flarum/prettier-config": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@flarum/prettier-config/-/prettier-config-1.0.0.tgz",
+      "integrity": "sha512-3/AcliIi5jPt4i7COb5hsLv6hm4EeXT9yI9I2EuEvhPi2QR+O9Y/8wrqRuO5mDkRzCIhUY+mjIL/f9770Zwfqg=="
+    },
     "@polka/url": {
       "version": "1.0.0-next.21",
       "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
       "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g=="
     },
+    "@types/jquery": {
+      "version": "3.5.12",
+      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.12.tgz",
+      "integrity": "sha512-AlX/K29WByFhZ3UbVVn8eywPFwhDZGc/qhDWgy5mu4VVr9b+OQZKBegtS6Tqi9pk8A1aXVrYXuLhnjFJX8Wc/w==",
+      "requires": {
+        "@types/sizzle": "*"
+      }
+    },
     "@types/json-schema": {
       "version": "7.0.9",
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
       "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
     },
+    "@types/mithril": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.8.tgz",
+      "integrity": "sha512-QzVV70DqUhWfLFpMFDBI9rRxtzeUUpbhiFDpUJYSV92AePgl+Qfficgv2MOb1Ceb+lBOQU8+L+Hjf2UielQjEw=="
+    },
+    "@types/sizzle": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+      "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ=="
+    },
+    "@types/throttle-debounce": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz",
+      "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ=="
+    },
     "@webassemblyjs/ast": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -8601,6 +8684,11 @@
       "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
       "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
     },
+    "dayjs": {
+      "version": "1.10.7",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
+      "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig=="
+    },
     "debug": {
       "version": "4.3.2",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
@@ -9044,6 +9132,17 @@
         "path-exists": "^4.0.0"
       }
     },
+    "flarum-tsconfig": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/flarum-tsconfig/-/flarum-tsconfig-1.0.2.tgz",
+      "integrity": "sha512-RUaN7D6noLK9vY1F86NIc+IlIP1YAA3bJ4jGR5pIm8UxvLBLW8qrAHzIosuQJgvnge7VgTA5c2LoNefUK/9EiQ==",
+      "requires": {
+        "@types/jquery": "^3.5.5",
+        "@types/mithril": "^2.0.7",
+        "@types/throttle-debounce": "^2.1.0",
+        "dayjs": "^1.10.4"
+      }
+    },
     "flarum-webpack-config": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/flarum-webpack-config/-/flarum-webpack-config-1.0.0.tgz",
@@ -10049,6 +10148,12 @@
       "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
       "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
     },
+    "prettier": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+      "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+      "dev": true
+    },
     "process": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -11143,11 +11248,6 @@
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
-    "v8-compile-cache": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
-      "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA=="
-    },
     "vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -11387,9 +11487,9 @@
       }
     },
     "webpack-cli": {
-      "version": "4.9.0",
-      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz",
-      "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==",
+      "version": "4.9.1",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz",
+      "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==",
       "requires": {
         "@discoveryjs/json-ext": "^0.5.0",
         "@webpack-cli/configtest": "^1.1.0",
@@ -11402,7 +11502,6 @@
         "import-local": "^3.0.2",
         "interpret": "^2.2.0",
         "rechoir": "^0.7.0",
-        "v8-compile-cache": "^2.2.0",
         "webpack-merge": "^5.7.3"
       },
       "dependencies": {
diff --git a/extensions/lock/js/package.json b/extensions/lock/js/package.json
index 29f1b8f0b..d47ae5944 100644
--- a/extensions/lock/js/package.json
+++ b/extensions/lock/js/package.json
@@ -1,13 +1,21 @@
 {
   "private": true,
   "name": "@flarum/lock",
+  "prettier": "@flarum/prettier-config",
   "dependencies": {
+    "@flarum/prettier-config": "^1.0.0",
+    "flarum-tsconfig": "^1.0.2",
     "flarum-webpack-config": "^1.0.0",
     "webpack": "^4.46.0",
-    "webpack-cli": "^4.9.0"
+    "webpack-cli": "^4.9.1"
+  },
+  "devDependencies": {
+    "prettier": "^2.5.1"
   },
   "scripts": {
     "dev": "webpack --mode development --watch",
-    "build": "webpack --mode production"
+    "build": "webpack --mode production",
+    "format": "prettier --write src",
+    "format-check": "prettier --check src"
   }
 }
diff --git a/extensions/lock/js/src/admin/index.js b/extensions/lock/js/src/admin/index.js
deleted file mode 100644
index 3e8e6eeed..000000000
--- a/extensions/lock/js/src/admin/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import app from 'flarum/app';
-
-app.initializers.add('lock', () => {
-  app.extensionData.for('flarum-lock')
-    .registerPermission({
-      icon: 'fas fa-lock',
-      label: app.translator.trans('flarum-lock.admin.permissions.lock_discussions_label'),
-      permission: 'discussion.lock'
-    }, 'moderate', 95);
-});
diff --git a/extensions/lock/js/src/admin/index.ts b/extensions/lock/js/src/admin/index.ts
new file mode 100644
index 000000000..55c5a208a
--- /dev/null
+++ b/extensions/lock/js/src/admin/index.ts
@@ -0,0 +1,13 @@
+import app from 'flarum/admin/app';
+
+app.initializers.add('lock', () => {
+  app.extensionData.for('flarum-lock').registerPermission(
+    {
+      icon: 'fas fa-lock',
+      label: app.translator.trans('flarum-lock.admin.permissions.lock_discussions_label'),
+      permission: 'discussion.lock',
+    },
+    'moderate',
+    95
+  );
+});
diff --git a/extensions/lock/js/src/forum/addLockBadge.js b/extensions/lock/js/src/forum/addLockBadge.js
index 9daf908f2..0d150b9f6 100644
--- a/extensions/lock/js/src/forum/addLockBadge.js
+++ b/extensions/lock/js/src/forum/addLockBadge.js
@@ -1,15 +1,19 @@
-import { extend } from 'flarum/extend';
-import Discussion from 'flarum/models/Discussion';
-import Badge from 'flarum/components/Badge';
+import app from 'flarum/forum/app';
+import { extend } from 'flarum/common/extend';
+import Discussion from 'flarum/common/models/Discussion';
+import Badge from 'flarum/common/components/Badge';
 
 export default function addLockBadge() {
-  extend(Discussion.prototype, 'badges', function(badges) {
+  extend(Discussion.prototype, 'badges', function (badges) {
     if (this.isLocked()) {
-      badges.add('locked', Badge.component({
-        type: 'locked',
-        label: app.translator.trans('flarum-lock.forum.badge.locked_tooltip'),
-        icon: 'fas fa-lock'
-      }));
+      badges.add(
+        'locked',
+        Badge.component({
+          type: 'locked',
+          label: app.translator.trans('flarum-lock.forum.badge.locked_tooltip'),
+          icon: 'fas fa-lock',
+        })
+      );
     }
   });
 }
diff --git a/extensions/lock/js/src/forum/addLockControl.js b/extensions/lock/js/src/forum/addLockControl.js
index 33df41b3f..975eb976e 100644
--- a/extensions/lock/js/src/forum/addLockControl.js
+++ b/extensions/lock/js/src/forum/addLockControl.js
@@ -1,20 +1,29 @@
-import { extend } from 'flarum/extend';
-import DiscussionControls from 'flarum/utils/DiscussionControls';
-import DiscussionPage from 'flarum/components/DiscussionPage';
-import Button from 'flarum/components/Button';
+import app from 'flarum/forum/app';
+import { extend } from 'flarum/common/extend';
+import DiscussionControls from 'flarum/forum/utils/DiscussionControls';
+import DiscussionPage from 'flarum/forum/components/DiscussionPage';
+import Button from 'flarum/common/components/Button';
 
 export default function addLockControl() {
-  extend(DiscussionControls, 'moderationControls', function(items, discussion) {
+  extend(DiscussionControls, 'moderationControls', function (items, discussion) {
     if (discussion.canLock()) {
-      items.add('lock', Button.component({
-        icon: 'fas fa-lock',
-        onclick: this.lockAction.bind(discussion)
-      }, app.translator.trans(discussion.isLocked() ? 'flarum-lock.forum.discussion_controls.unlock_button' : 'flarum-lock.forum.discussion_controls.lock_button')));
+      items.add(
+        'lock',
+        Button.component(
+          {
+            icon: 'fas fa-lock',
+            onclick: this.lockAction.bind(discussion),
+          },
+          app.translator.trans(
+            discussion.isLocked() ? 'flarum-lock.forum.discussion_controls.unlock_button' : 'flarum-lock.forum.discussion_controls.lock_button'
+          )
+        )
+      );
     }
   });
 
-  DiscussionControls.lockAction = function() {
-    this.save({isLocked: !this.isLocked()}).then(() => {
+  DiscussionControls.lockAction = function () {
+    this.save({ isLocked: !this.isLocked() }).then(() => {
       if (app.current.matches(DiscussionPage)) {
         app.current.get('stream').update();
       }
diff --git a/extensions/lock/js/src/forum/components/DiscussionLockedNotification.js b/extensions/lock/js/src/forum/components/DiscussionLockedNotification.js
index da2ba7eb7..adc96149c 100644
--- a/extensions/lock/js/src/forum/components/DiscussionLockedNotification.js
+++ b/extensions/lock/js/src/forum/components/DiscussionLockedNotification.js
@@ -1,4 +1,5 @@
-import Notification from 'flarum/components/Notification';
+import app from 'flarum/forum/app';
+import Notification from 'flarum/forum/components/Notification';
 
 export default class DiscussionLockedNotification extends Notification {
   icon() {
@@ -12,6 +13,6 @@ export default class DiscussionLockedNotification extends Notification {
   }
 
   content() {
-    return app.translator.trans('flarum-lock.forum.notifications.discussion_locked_text', {user: this.attrs.notification.fromUser()});
+    return app.translator.trans('flarum-lock.forum.notifications.discussion_locked_text', { user: this.attrs.notification.fromUser() });
   }
 }
diff --git a/extensions/lock/js/src/forum/components/DiscussionLockedPost.js b/extensions/lock/js/src/forum/components/DiscussionLockedPost.js
index 20c4dab77..72b2da70b 100644
--- a/extensions/lock/js/src/forum/components/DiscussionLockedPost.js
+++ b/extensions/lock/js/src/forum/components/DiscussionLockedPost.js
@@ -1,10 +1,8 @@
-import EventPost from 'flarum/components/EventPost';
+import EventPost from 'flarum/forum/components/EventPost';
 
 export default class DiscussionLockedPost extends EventPost {
   icon() {
-    return this.attrs.post.content().locked
-      ? 'fas fa-lock'
-      : 'fas fa-unlock';
+    return this.attrs.post.content().locked ? 'fas fa-lock' : 'fas fa-unlock';
   }
 
   descriptionKey() {
diff --git a/extensions/lock/js/src/forum/index.js b/extensions/lock/js/src/forum/index.js
index 14af1fafc..b52ec4ae2 100644
--- a/extensions/lock/js/src/forum/index.js
+++ b/extensions/lock/js/src/forum/index.js
@@ -1,8 +1,8 @@
-import { extend } from 'flarum/extend';
-import app from 'flarum/app';
-import Model from 'flarum/Model';
-import Discussion from 'flarum/models/Discussion';
-import NotificationGrid from 'flarum/components/NotificationGrid';
+import { extend } from 'flarum/common/extend';
+import app from 'flarum/forum/app';
+import Model from 'flarum/common/Model';
+import Discussion from 'flarum/common/models/Discussion';
+import NotificationGrid from 'flarum/forum/components/NotificationGrid';
 
 import DiscussionLockedPost from './components/DiscussionLockedPost';
 import DiscussionLockedNotification from './components/DiscussionLockedNotification';
@@ -23,7 +23,7 @@ app.initializers.add('flarum-lock', () => {
     items.add('discussionLocked', {
       name: 'discussionLocked',
       icon: 'fas fa-lock',
-      label: app.translator.trans('flarum-lock.forum.settings.notify_discussion_locked_label')
+      label: app.translator.trans('flarum-lock.forum.settings.notify_discussion_locked_label'),
     });
   });
 });
diff --git a/extensions/lock/js/tsconfig.json b/extensions/lock/js/tsconfig.json
new file mode 100644
index 000000000..207c5b382
--- /dev/null
+++ b/extensions/lock/js/tsconfig.json
@@ -0,0 +1,16 @@
+{
+  // Use Flarum's tsconfig as a starting point
+  "extends": "flarum-tsconfig",
+  // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
+  // and also tells your Typescript server to read core's global typings for
+  // access to `dayjs` and `$` in the global namespace.
+  "include": ["src/**/*", "../vendor/flarum/core/js/dist-typings/@types/**/*"],
+  "compilerOptions": {
+    // This will output typings to `dist-typings`
+    "declarationDir": "./dist-typings",
+    "baseUrl": ".",
+    "paths": {
+      "flarum/*": ["../vendor/flarum/core/js/dist-typings/*"]
+    }
+  }
+}