diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 033f8824cf2453c780f9a630619b05215b992d4e..d35e93c4dfbe7086b8fa7773f01f532718b8d4f0 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -576,6 +576,7 @@ YARN_INSTALLED_APPS = [
     "@vitejs/plugin-vue2@^2.2.0",
     "@rollup/plugin-node-resolve@^15.0.1",
     "@rollup/plugin-graphql@^2.0.2",
+    "@rollup/plugin-multi-entry@^6.0.0",
     "vue-i18n@8",
     "eslint@^8.26.0",
     "eslint-plugin-vue@^9.7.0",
diff --git a/aleksis/core/templates/core/vue_base.html b/aleksis/core/templates/core/vue_base.html
index d7232a6a9f959ca910f0336395514c943e32be03..9eb966cd67c7bf7a068fea9f01731ceed6344feb 100644
--- a/aleksis/core/templates/core/vue_base.html
+++ b/aleksis/core/templates/core/vue_base.html
@@ -224,7 +224,7 @@
 {{ request.site.preferences.theme__primary|json_script:"primary-color" }}
 {{ request.site.preferences.theme__secondary|json_script:"secondary-color" }}
 <script type="text/javascript" src="{% static 'js/search.js' %}"></script>
-{% vite_asset 'aleksis/core/assets/index.js' %}
+{% vite_asset 'virtual:aleksis-local-full.js' %}
 {% block extra_body %}{% endblock %}
 </body>
 </html>
diff --git a/aleksis/core/util/frontend_helpers.py b/aleksis/core/util/frontend_helpers.py
index 3798024658aca54d2661bf7921fd35bdcd967ff7..f17725c5ea8e6b5f59c9cd8065ada8132029bd83 100644
--- a/aleksis/core/util/frontend_helpers.py
+++ b/aleksis/core/util/frontend_helpers.py
@@ -27,12 +27,16 @@ def write_vite_values(out_path: str) -> dict[str, Any]:
         "static_url": settings.STATIC_URL,
     }
     # Write rollup entrypoints for all apps
-    vite_values["entrypoints"] = {
-        app: os.path.join(path, "index") for app, path in get_apps_with_assets().items()
-    }
-    vite_values["entrypoints"]["core"] = os.path.join(
-        settings.BASE_DIR, "aleksis", "core", "assets", "index"
+    vite_values["entrypoints"] = []
+    for app, path in get_apps_with_assets().items():
+        ep = os.path.join(path, "index.js")
+        if os.path.exists(ep):
+            vite_values["entrypoints"].append(ep)
+    # Add core entrypoint
+    vite_values["entrypoints"].append(
+        os.path.join(settings.BASE_DIR, "aleksis", "core", "assets", "index.js")
     )
+
     with open(out_path, "w") as out:
         json.dump(vite_values, out)
 
diff --git a/aleksis/core/vite.config.js b/aleksis/core/vite.config.js
index 4ba226e632c23e71b2087d4b025e070b2f5c3925..c3cf40643b560cd846d171809f7b274c26640f54 100644
--- a/aleksis/core/vite.config.js
+++ b/aleksis/core/vite.config.js
@@ -1,15 +1,15 @@
 const fs = require("fs");
 const path = require("path");
 
-import { defineConfig } from 'vite';
+import { defineConfig } from "vite";
 import vue from "@vitejs/plugin-vue2";
-import { nodeResolve } from '@rollup/plugin-node-resolve';
-import graphql from '@rollup/plugin-graphql';
+import { nodeResolve } from "@rollup/plugin-node-resolve";
+import graphql from "@rollup/plugin-graphql";
+import multi from '@rollup/plugin-multi-entry';
 
 const django_values = JSON.parse(fs.readFileSync("./django-vite-values.json"));
 
 export default defineConfig({
-  root: path.resolve(".."),
   base: django_values.static_url,
   build: {
     outDir: path.resolve("./vite_bundles/"),
@@ -22,10 +22,15 @@ export default defineConfig({
     strictPort: true,
     origin: "http://127.0.0.1:5173",
   },
-  plugins: [vue(), nodeResolve({modulePaths: [path.resolve("./node_modules")]}), graphql()],
+  plugins: [
+    multi({entryFileName: "aleksis-local-full.js"}),
+    vue(),
+    nodeResolve({ modulePaths: [path.resolve("./node_modules")] }),
+    graphql(),
+  ],
   resolve: {
     alias: {
-      "vue": "vue/dist/vue.esm.js",
+      vue: "vue/dist/vue.esm.js",
     },
   },
 });