diff --git a/aleksis/core/vite.config.js b/aleksis/core/vite.config.js
index fcaf916e41decd4053c9805b8e310b9baa1a2ad8..b459ae1f3b761875a59de70dfdf39cb9a26e32ca 100644
--- a/aleksis/core/vite.config.js
+++ b/aleksis/core/vite.config.js
@@ -97,6 +97,22 @@ function generateAppImporter(appDetails) {
   return code;
 }
 
+/**
+ * Generate a mapping of esbuild import aliases for apps.
+ *
+ * App code locations are discovered by the `aleksis-admin` vite wrapper and passed
+ * in the django_values hints.
+ */
+function generateAppAliases(appDetails) {
+  let aliases = { "aleksis.core": django_values.coreAssetDir };
+
+  for (const [appPackage, appMeta] of Object.entries(appDetails)) {
+    aliases[appPackage] = appMeta.assetDir;
+  }
+
+  return aliases;
+}
+
 export default defineConfig({
   // root must always be the base directory of the AlekSIS-Core source tree
   //  Changing this will mangle the manifest key of the entrypoint!
@@ -293,6 +309,8 @@ export default defineConfig({
     alias: {
       "@": path.resolve(django_values.node_modules),
       vue: path.resolve(django_values.node_modules + "/vue/dist/vue.esm.js"),
+      // Add aliases for every app using their package name
+      ...generateAppAliases(django_values.appDetails),
     },
   },
 });