diff --git a/python_payload/apps/appearance/flow3r.toml b/python_payload/apps/appearance/flow3r.toml
index fe2957f7256d9fa025b61e8c13952dd98858594f..3f0706653f65849be960506e02c0e8715ecb206b 100644
--- a/python_payload/apps/appearance/flow3r.toml
+++ b/python_payload/apps/appearance/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Appearance"
-menu = "Hidden"
+category = "Hidden"
 
 [metadata]
 author = "Flow3r Badge Authors"
diff --git a/python_payload/apps/audio_config/flow3r.toml b/python_payload/apps/audio_config/flow3r.toml
index 31ab43fbd9fed65189ac75ab20ecaaae8b3a81f2..a2fc23cfee0476db1c7606a957636d3323a9b8c7 100644
--- a/python_payload/apps/audio_config/flow3r.toml
+++ b/python_payload/apps/audio_config/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Audio Config"
-menu = "Hidden"
+category = "Hidden"
 
 [metadata]
 author = "Flow3r Badge Authors"
diff --git a/python_payload/apps/audio_passthrough/flow3r.toml b/python_payload/apps/audio_passthrough/flow3r.toml
index 2b57ba917194aa19ab2016c1f4fb8b17f7f856d3..c43165fd8484b2b3ffbd4b887f26b684b36da5d7 100644
--- a/python_payload/apps/audio_passthrough/flow3r.toml
+++ b/python_payload/apps/audio_passthrough/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Audio Passthrough"
-menu = "Media"
+category = "Media"
 
 [entry]
 class = "AudioPassthrough"
diff --git a/python_payload/apps/clouds/flow3r.toml b/python_payload/apps/clouds/flow3r.toml
index 7c69320a75df539c969c32ff6a0def0e8bb91443..0a7e69484664367463f5640c312c43171adb7c0e 100644
--- a/python_payload/apps/clouds/flow3r.toml
+++ b/python_payload/apps/clouds/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Clouds"
-menu = "Badge"
+category = "Badge"
 
 [metadata]
 author = "Flow3r Badge Authors"
diff --git a/python_payload/apps/demo_cap_touch/flow3r.toml b/python_payload/apps/demo_cap_touch/flow3r.toml
index 468449d8cf832ef30c23c9027e11b8236c748ab3..cc859bb6ca0335054f9710076d3b0d4c7d60feee 100644
--- a/python_payload/apps/demo_cap_touch/flow3r.toml
+++ b/python_payload/apps/demo_cap_touch/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Captouch Demo"
-menu = "Apps"
+category = "Apps"
 
 [entry]
 class = "App"
diff --git a/python_payload/apps/demo_harmonic/flow3r.toml b/python_payload/apps/demo_harmonic/flow3r.toml
index 863bc6deddf848ab05d450fcd5e8b6a9126dcba8..7f3b803e6a03abefd3122908a6e4f39285af1960 100644
--- a/python_payload/apps/demo_harmonic/flow3r.toml
+++ b/python_payload/apps/demo_harmonic/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "chord organ"
-menu = "Music"
+category = "Music"
 
 [entry]
 class = "HarmonicApp"
diff --git a/python_payload/apps/demo_imu/flow3r.toml b/python_payload/apps/demo_imu/flow3r.toml
index 6407ab6436a1783665eee8f100db4f1b536657e8..5c16eaa6dcf056b53d8d5806efc30c97ae811d51 100644
--- a/python_payload/apps/demo_imu/flow3r.toml
+++ b/python_payload/apps/demo_imu/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "IMU Demo"
-menu = "Apps"
+category = "Apps"
 
 [entry]
 class = "IMUDemo"
diff --git a/python_payload/apps/demo_melodic/flow3r.toml b/python_payload/apps/demo_melodic/flow3r.toml
index ad3b0f98d90607442d77fa1b44d2570429ea6392..57d6beb7f0df925428a0f622775fab4e2f5b94a8 100644
--- a/python_payload/apps/demo_melodic/flow3r.toml
+++ b/python_payload/apps/demo_melodic/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "melodic demo"
-menu = "Music"
+category = "Music"
 
 [entry]
 class = "MelodicApp"
diff --git a/python_payload/apps/demo_scroll/flow3r.toml b/python_payload/apps/demo_scroll/flow3r.toml
index 4fd9d7c0707bcdab12a00edbd471abdd7f2c6a84..de1cd6341b6ba2966c63b80406e10f4733dfffae 100644
--- a/python_payload/apps/demo_scroll/flow3r.toml
+++ b/python_payload/apps/demo_scroll/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Scroll Demo"
-menu = "Apps"
+category = "Apps"
 
 [entry]
 class = "ScrollDemo"
diff --git a/python_payload/apps/demo_worms/flow3r.toml b/python_payload/apps/demo_worms/flow3r.toml
index f12d18716d9f28b319aae932986a419cb967d93a..d8b0f4f0448261ff5fb0e23e61f5a53951294b46 100644
--- a/python_payload/apps/demo_worms/flow3r.toml
+++ b/python_payload/apps/demo_worms/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Worms"
-menu = "Apps"
+category = "Apps"
 
 [entry]
 class = "AppWorms"
diff --git a/python_payload/apps/fil3s/flow3r.toml b/python_payload/apps/fil3s/flow3r.toml
index 38f1349b461723d26f4ae109eadbd2bfdd4cf308..1ee6b7ff4ac31274413f86d1c56e0a247c8693fd 100644
--- a/python_payload/apps/fil3s/flow3r.toml
+++ b/python_payload/apps/fil3s/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Files"
-menu = "Apps"
+category = "Apps"
 
 [entry]
 class = "Fil3sApp"
diff --git a/python_payload/apps/gay_drums/flow3r.toml b/python_payload/apps/gay_drums/flow3r.toml
index 278293587e166f382c7f495c04b1be52af045e98..8c81be0e6e8e6cb185052a2075f09b3878cb9d2c 100644
--- a/python_payload/apps/gay_drums/flow3r.toml
+++ b/python_payload/apps/gay_drums/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "gay drums"
-menu = "Music"
+category = "Music"
 
 [entry]
 class = "GayDrums"
diff --git a/python_payload/apps/gr33nhouse/flow3r.toml b/python_payload/apps/gr33nhouse/flow3r.toml
index acdbc16e75be2b45bd8bd60e675cf47c5f9f38a8..a95a55fa26659e4ee768b9cfa2421034a568d21c 100644
--- a/python_payload/apps/gr33nhouse/flow3r.toml
+++ b/python_payload/apps/gr33nhouse/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Get Apps"
-menu = "Hidden"
+category = "Hidden"
 wifi_preference = true
 
 [entry]
diff --git a/python_payload/apps/graphics_mode/flow3r.toml b/python_payload/apps/graphics_mode/flow3r.toml
index 449a2791a526761f3498715d256261b88b7188a8..c36f2d870b636dffddb59aad94da386bee4e4165 100644
--- a/python_payload/apps/graphics_mode/flow3r.toml
+++ b/python_payload/apps/graphics_mode/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Graphics Mode"
-menu = "Hidden"
+category = "Hidden"
 
 [metadata]
 author = "Flow3r Badge Authors"
diff --git a/python_payload/apps/led_painter/flow3r.toml b/python_payload/apps/led_painter/flow3r.toml
index 3fe7eed10c93f7ec926eb5c2a1c31530215f1a78..c96e34f08e28a79f4bdb453aa18937483914ca8f 100644
--- a/python_payload/apps/led_painter/flow3r.toml
+++ b/python_payload/apps/led_painter/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "LED Painter"
-menu = "Apps"
+category = "Apps"
 
 [entry]
 class = "LEDPainter"
diff --git a/python_payload/apps/mandelbrot/flow3r.toml b/python_payload/apps/mandelbrot/flow3r.toml
index beba5e92d1a3d8bdeaafe927cdb6656510831c73..26145b1f2c94924ae1f23938f78c31403370b36c 100644
--- a/python_payload/apps/mandelbrot/flow3r.toml
+++ b/python_payload/apps/mandelbrot/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Mandelbrot"
-menu = "Apps"
+category = "Apps"
 
 [metadata]
 author = "Flow3r Badge Authors"
diff --git a/python_payload/apps/nick/flow3r.toml b/python_payload/apps/nick/flow3r.toml
index f2ce65ed67512c11fe7effd7fc879d84dab42e34..0b548af9bef745d53fa3bae2d6baae807ce7df4d 100644
--- a/python_payload/apps/nick/flow3r.toml
+++ b/python_payload/apps/nick/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Nick"
-menu = "Badge"
+category = "Badge"
 
 [entry]
 class = "NickApp"
diff --git a/python_payload/apps/otamatone/flow3r.toml b/python_payload/apps/otamatone/flow3r.toml
index c1b05d93b111abd8e3a2edadb48f4995b8dc53d9..b60063b94676ce3560168629e8783611f597f24a 100644
--- a/python_payload/apps/otamatone/flow3r.toml
+++ b/python_payload/apps/otamatone/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Otamatone"
-menu = "Music"
+category = "Music"
 
 [entry]
 class = "Otamatone"
diff --git a/python_payload/apps/scalar/flow3r.toml b/python_payload/apps/scalar/flow3r.toml
index bf300d7e5ede47f3674905c79088facfe65e117f..9f2e258539a5a6fc9d0d63167819a9a1a07f7999 100644
--- a/python_payload/apps/scalar/flow3r.toml
+++ b/python_payload/apps/scalar/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Scalar"
-menu = "Music"
+category = "Music"
 
 [entry]
 class = "ScalarApp"
diff --git a/python_payload/apps/shoegaze/flow3r.toml b/python_payload/apps/shoegaze/flow3r.toml
index 39618a4a6ddc3628b5dfdeb7d763fea054fe2a33..a96d517bbf38702c63bb7b6d3ac5a2c80b0faf81 100644
--- a/python_payload/apps/shoegaze/flow3r.toml
+++ b/python_payload/apps/shoegaze/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "shoegaze"
-menu = "Music"
+category = "Music"
 wifi_preference = false
 
 [entry]
diff --git a/python_payload/apps/tiny_sampler/flow3r.toml b/python_payload/apps/tiny_sampler/flow3r.toml
index 18917097fce63eacaf543f1e8568f3b387a9089b..b71a361528f5bec8eb5f338f88ba6f776710a90d 100644
--- a/python_payload/apps/tiny_sampler/flow3r.toml
+++ b/python_payload/apps/tiny_sampler/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "tiny sampler"
-menu = "Music"
+category = "Music"
 
 [entry]
 class = "TinySampler"
diff --git a/python_payload/apps/updat3r/flow3r.toml b/python_payload/apps/updat3r/flow3r.toml
index b17e390c93d380efa34dd6ad8d0185fe14a7a8dd..b3c1adad0add9053a52af3f6f4f3cb7b6ff52734 100644
--- a/python_payload/apps/updat3r/flow3r.toml
+++ b/python_payload/apps/updat3r/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Check for Updates"
-menu = "Hidden"
+category = "Hidden"
 wifi_preference = true
 
 [entry]
diff --git a/python_payload/apps/w1f1/flow3r.toml b/python_payload/apps/w1f1/flow3r.toml
index 5a141f0799eb88a9f3fba2a44387e4ca171f71e0..1b1a7b45122b02a3b197f1b43959a278d6e663e1 100644
--- a/python_payload/apps/w1f1/flow3r.toml
+++ b/python_payload/apps/w1f1/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "WiFi"
-menu = "Hidden"
+category = "Hidden"
 
 [entry]
 class = "WifiApp"
diff --git a/python_payload/apps/wurzelitzer/flow3r.toml b/python_payload/apps/wurzelitzer/flow3r.toml
index 0751bd28c66e36b5f89c3aaa701fe61b4a08475d..b7f4aaa16acf73055648de0ffb55a4e2f1a868c4 100644
--- a/python_payload/apps/wurzelitzer/flow3r.toml
+++ b/python_payload/apps/wurzelitzer/flow3r.toml
@@ -1,6 +1,6 @@
 [app]
 name = "Wurzelitzer"
-menu = "Media"
+category = "Media"
 wifi_preference = true
 
 [metadata]
diff --git a/python_payload/st3m/application.py b/python_payload/st3m/application.py
index ae5fad58ef123e9b3b5edc3b024106771e20deb4..38c1550b2fc25681f92d50c73b646f6f1ef3705d 100644
--- a/python_payload/st3m/application.py
+++ b/python_payload/st3m/application.py
@@ -99,7 +99,7 @@ class BundleMetadata:
        name = "Name of the application"
        # One of "Apps", "Badge", "Music", "Games", "Media". Picks which menu
        # the bundle's class will be loadable from.
-       menu = "Apps"
+       category = "Apps"
 
        [entry]
        # Required for app to actually load. Defines the name of the class that
@@ -144,13 +144,12 @@ class BundleMetadata:
         if "name" not in app or type(app["name"]) != str:
             raise BundleMetadataBroken("missing app.name key")
         self.name = app["name"]
-        if "menu" not in app or type(app["menu"]) != str:
-            raise BundleMetadataBroken("missing app.menu key")
-        self.menu = app["menu"]
-        if self.menu not in ["Apps", "Music", "Badge", "Games", "Media", "Hidden"]:
-            raise BundleMetadataBroken(
-                "app.menu must be either Apps, Music, Badge, Games or Media"
-            )
+        if "category" not in app or type(app["category"]) != str:
+            if "menu" not in app or type(app["menu"]) != str:
+                raise BundleMetadataBroken("missing app.category key")
+            self.menu = app["menu"]
+        else:
+            self.menu = app["category"]
 
         version = 0
         if t.get("metadata") is not None:
@@ -216,11 +215,15 @@ class BundleMetadata:
 
         raise BundleMetadataBroken("no valid entry method specified")
 
+    def menu_kinds(self) -> List[str]:
+        """
+        Returns a list of menu kinds this bundle places its entries in.
+        """
+        return [self.menu]
+
     def menu_entries(self, kind: str) -> List["MenuItemAppLaunch"]:
         """
         Returns MenuItemAppLauch entries for this bundle for a given menu kind.
-
-        Kind is one of 'Apps', 'Badge', 'Music', 'Games', 'Media'.
         """
         if self.menu != kind:
             return []
diff --git a/python_payload/st3m/goose.py b/python_payload/st3m/goose.py
index ad4efee4627b1799952867f795381ed1f4fd1373..a885cc248b650b59a422ae17fae87b359db62b07 100644
--- a/python_payload/st3m/goose.py
+++ b/python_payload/st3m/goose.py
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
 
     from typing import (
         List,
+        Set,
         Optional,
         Tuple,
         Dict,
@@ -44,6 +45,7 @@ else:
     try:
         from typing import (
             List,
+            Set,
             Optional,
             Tuple,
             Dict,
@@ -58,6 +60,7 @@ else:
     except ImportError:
         # We're in Micropython.
         List = None
+        Set = None
         Optional = None
         Tuple = None
         Dict = None
@@ -77,6 +80,7 @@ __all__ = [
     "ABCBase",
     "abstractmethod",
     "List",
+    "Set",
     "Optional",
     "Enum",
     "Tuple",
diff --git a/python_payload/st3m/run.py b/python_payload/st3m/run.py
index 9ffcb875bbdad2358ec4808508f782403d61b59c..e72f267d681e38bb656ca240d3493497cb0e9dc4 100644
--- a/python_payload/st3m/run.py
+++ b/python_payload/st3m/run.py
@@ -1,5 +1,5 @@
 from st3m.reactor import Reactor, Responder
-from st3m.goose import List, Optional
+from st3m.goose import List, Set, Optional
 from st3m.ui.menu import (
     MenuItem,
     MenuItemBack,
@@ -95,6 +95,13 @@ class ApplicationMenu(SimpleMenu):
         leds.update()
 
 
+def _get_bundle_menu_kinds(mgr: BundleManager) -> Set[str]:
+    kinds: Set[str] = set()
+    for bundle in mgr.bundles.values():
+        kinds.update(bundle.menu_kinds())
+    return kinds
+
+
 def _get_bundle_menu_entries(mgr: BundleManager, kind: str) -> List[MenuItem]:
     entries: List[MenuItem] = []
     ids = sorted(mgr.bundles.keys(), key=str.lower)
@@ -254,9 +261,16 @@ def run_main() -> None:
             MenuItemAction("Reboot", machine.reset),
         ],
     )
+
+    app_kinds = _get_bundle_menu_kinds(bundles)
+    menu_categories = ["Badge", "Music", "Media", "Apps", "Games"]
+    for kind in app_kinds:
+        if kind not in ["Hidden", "System"] and kind not in menu_categories:
+            menu_categories.append(kind)
+
     categories = [
         MenuItemForeground(kind, ApplicationMenu([MenuItemBack()] + entries))
-        for kind in ["Badge", "Music", "Media", "Apps", "Games"]
+        for kind in menu_categories
         if (entries := _get_bundle_menu_entries(bundles, kind))
     ]
     categories.append(MenuItemForeground("System", menu_system))