diff --git a/aleksis/apps/kort/frontend/index.js b/aleksis/apps/kort/frontend/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..534f76bcc6ada493df218cae7febd676c290cf81
--- /dev/null
+++ b/aleksis/apps/kort/frontend/index.js
@@ -0,0 +1,173 @@
+export default {
+  meta: {
+    inMenu: true,
+    titleKey: "kort.menu_title",
+    icon: "mdi-card-account-details-outline",
+  },
+  children: [
+    {
+      path: "cards/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.cards",
+      meta: {
+        inMenu: true,
+        titleKey: "kort.card.menu_title",
+        icon: "mdi-card-multiple-outline",
+        permission: "kort.view_cards_rule",
+      },
+
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "cards/create/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.createCard",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "cards/:pk/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.card",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "cards/:pk/generate_pdf/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.generateCardPdf",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "cards/:pk/deactivate/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.deactivateCard",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "cards/:pk/print/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.printCard",
+
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "cards/:pk/delete/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.deleteCard",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "printers/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.cardPrinters",
+      meta: {
+        inMenu: true,
+        titleKey: "kort.printer.menu_title",
+        icon: "mdi-printer-outline",
+        permission: "kort.view_cardprinters_rule",
+      },
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "printers/create/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.createCardPrinter",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "printers/:pk/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.cardPrinter",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "printers/:pk/edit/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.editCardPrinter",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "printers/:pk/delete/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.deleteCardPrinter",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "printers/:pk/config/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.cardPrinterConfig",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "layouts/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.cardLayouts",
+      meta: {
+        inMenu: true,
+        titleKey: "kort.layout.menu_title",
+        icon: "mdi-card-account-details-star-outline",
+        permission: "kort.view_cardlayouts_rule",
+      },
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "layouts/create/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.createCardLayout",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "layouts/:pk/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.cardLayout",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "layouts/:pk/edit/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.editCardLayout",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+    {
+      path: "layouts/:pk/delete/",
+      component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
+      name: "kort.deleteCardLayout",
+      props: {
+        byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
+      },
+    },
+  ],
+};
diff --git a/aleksis/apps/kort/frontend/messages/en.json b/aleksis/apps/kort/frontend/messages/en.json
new file mode 100644
index 0000000000000000000000000000000000000000..ef986e7686f7fe8b61b75b3728704b5ce235bc00
--- /dev/null
+++ b/aleksis/apps/kort/frontend/messages/en.json
@@ -0,0 +1,14 @@
+{
+  "kort": {
+    "menu_title": "Student ID Cards",
+    "card": {
+      "menu_title": "All Cards"
+    },
+    "printer": {
+      "menu_title": "Card Printers"
+    },
+    "layout": {
+      "menu_title": "Card Layouts"
+    }
+  }
+}
diff --git a/aleksis/apps/kort/menus.py b/aleksis/apps/kort/menus.py
deleted file mode 100644
index 939fe3f657c45b96aa2d0c2d3d7ff89066fc30c3..0000000000000000000000000000000000000000
--- a/aleksis/apps/kort/menus.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-MENUS = {
-    "NAV_MENU_CORE": [
-        {
-            "name": _("Student ID Cards"),
-            "url": "#",
-            "root": True,
-            "svg_icon": "mdi:card-account-details-outline",
-            "validators": [
-                (
-                    "aleksis.core.util.predicates.permission_validator",
-                    "kort.view_menu_rule",
-                )
-            ],
-            "submenu": [
-                {
-                    "name": _("All Cards"),
-                    "url": "cards",
-                    "svg_icon": "mdi:card-multiple-outline",
-                    "validators": [
-                        (
-                            "aleksis.core.util.predicates.permission_validator",
-                            "kort.view_cards_rule",
-                        )
-                    ],
-                },
-                {
-                    "name": _("Card Printers"),
-                    "url": "card_printers",
-                    "svg_icon": "mdi:printer-outline",
-                    "validators": [
-                        (
-                            "aleksis.core.util.predicates.permission_validator",
-                            "kort.view_cardprinters_rule",
-                        )
-                    ],
-                },
-                {
-                    "name": _("Card Layouts"),
-                    "url": "card_layouts",
-                    "svg_icon": "mdi:card-account-details-star-outline",
-                    "validators": [
-                        (
-                            "aleksis.core.util.predicates.permission_validator",
-                            "kort.view_cardlayouts_rule",
-                        )
-                    ],
-                },
-            ],
-        }
-    ]
-}
diff --git a/aleksis/apps/kort/urls.py b/aleksis/apps/kort/urls.py
index e9809ccdf3a377aa267b5caf62ffd4cdd8c38b3a..424fd51ca8b788cc738c9ff755377173a7e4fb54 100644
--- a/aleksis/apps/kort/urls.py
+++ b/aleksis/apps/kort/urls.py
@@ -37,6 +37,9 @@ urlpatterns = [
         views.CardLayoutDeleteView.as_view(),
         name="delete_card_layout",
     ),
+]
+
+api_urlpatterns = [
     path("api/v1/printers/", api.CardPrinterDetails.as_view(), name="api_card_printer"),
     path(
         "api/v1/printers/<int:pk>/status/",
diff --git a/pyproject.toml b/pyproject.toml
index 2b33e1b7da5044d61543e562b5e6810cfb4410cb..62f4f083dc11a59107e6c0074f64c23ee1849cbb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -25,7 +25,7 @@ secondary = true
 
 [tool.poetry.dependencies]
 python = "^3.9"
-aleksis-core = "^2.12"
+aleksis-core = "^3.0b2"
 python-barcode = "^0.14.0"
 django-formtools = "^2.3"
 django-ace = "^1.0.12"