diff --git a/python_payload/apps/appearance/__init__.py b/python_payload/apps/appearance/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd7b0a53186249cb5409f7cb3f63956605460074
--- /dev/null
+++ b/python_payload/apps/appearance/__init__.py
@@ -0,0 +1,258 @@
+from st3m.application import Application
+import math, random, sys_display
+from st3m import settings
+import leds
+import sys_display
+
+
+class App(Application):
+    def __init__(self, app_ctx):
+        super().__init__(app_ctx)
+
+        self.x = 23
+        self.x_vel = 40 / 1000.0
+
+        self.y = 0
+        self.font_size = 20
+        self.delta_ms = 0
+        self.right_pressed = False
+        self.left_pressed = False
+        self.select_pressed = False
+        self.angle = 0
+        self.focused_widget = 1
+        self.active = False
+        self.num_widgets = 4
+        self.overhang = -20
+        self.line_height = 24
+        self.input.buttons.app.left.repeat_enable(800, 300)
+        self.input.buttons.app.right.repeat_enable(800, 300)
+        self.mid_x = 50
+        self.led_accumulator_ms = 0
+        self.blueish = False
+
+    def draw_widget(self, label):
+        ctx = self.ctx
+        self.widget_no += 1
+        if not self.active:
+            if self.select_pressed and self.focused_widget > 0:
+                self.active = True
+                self.select_pressed = False
+            elif self.left_pressed:
+                self.focused_widget -= 1
+                if self.focused_widget < 1:
+                    self.focused_widget = 1
+                self.left_pressed = False
+            elif self.right_pressed:
+                self.focused_widget += 1
+                if self.focused_widget > self.num_widgets - 1:
+                    self.focused_widget = self.num_widgets - 1
+                self.right_pressed = False
+        if self.widget_no == self.focused_widget and not self.active:
+            ctx.rectangle(-130, int(self.y - self.font_size * 0.8), 260, self.font_size)
+            ctx.line_width = 2.0
+            ctx.rgba(0.8, 0.6, 0.1, 1.0)
+            ctx.stroke()
+        ctx.gray(1)
+        ctx.move_to(self.mid_x, self.y)
+        ctx.save()
+        ctx.rgb(0.8, 0.8, 0.8)
+        ctx.text_align = ctx.RIGHT
+        ctx.text(label + ": ")
+        ctx.restore()
+        self.y += self.line_height
+
+    def draw_choice(self, label, choices, no):
+        ctx = self.ctx
+        self.draw_widget(label)
+        if self.widget_no == self.focused_widget and self.active:
+            if self.left_pressed:
+                no -= 1
+                if no < 0:
+                    no = 0
+            elif self.right_pressed:
+                no += 1
+                if no >= len(choices):
+                    no = len(choices) - 1
+            elif self.select_pressed:
+                self.active = False
+                self.select_pressed = False
+
+        for a in range(len(choices)):
+            if a == no and self.active and self.widget_no == self.focused_widget:
+                ctx.save()
+                ctx.rgba(0.8, 0.6, 0.1, 1.0)
+                ctx.rectangle(
+                    ctx.x - 1,
+                    ctx.y - self.font_size * 0.8,
+                    ctx.text_width(choices[a]) + 2,
+                    self.font_size,
+                ).stroke()
+                ctx.restore()
+                ctx.text(choices[a] + " ")
+            elif a == no:
+                ctx.save()
+                ctx.gray(1)
+                ctx.rectangle(
+                    ctx.x - 1,
+                    ctx.y - self.font_size * 0.8,
+                    ctx.text_width(choices[a]) + 2,
+                    self.font_size,
+                ).fill()
+                ctx.gray(0)
+                ctx.text(choices[a] + " ")
+                ctx.restore()
+            else:
+                ctx.text(choices[a] + " ")
+        return no
+
+    def draw_number(self, label, step_size, no, unit=""):
+        ctx = self.ctx
+        self.draw_widget(label)
+        ret = no
+        if self.widget_no == self.focused_widget and self.active:
+            if self.left_pressed:
+                ret -= step_size
+            elif self.right_pressed:
+                ret += step_size
+            elif self.select_pressed:
+                self.active = False
+                self.select_pressed = False
+
+        if self.active and self.widget_no == self.focused_widget:
+            ctx.save()
+            ctx.rgba(0.8, 0.6, 0.1, 1.0)
+            ctx.rectangle(
+                ctx.x - 1,
+                ctx.y - self.font_size * 0.8,
+                ctx.text_width(str(no)[:4]) + 2,
+                self.font_size,
+            ).stroke()
+            ctx.restore()
+            ctx.text(str(no)[:4] + unit)
+        else:
+            ctx.text(str(no)[:4] + unit)
+        return ret
+
+    def draw_bg(self):
+        ctx = self.ctx
+        ctx.gray(1.0)
+        ctx.move_to(-100, -80)
+        wig = self.focused_widget - 1
+        if wig < 2:
+            wig = 2
+        if wig > self.num_widgets - 3:
+            wig = self.num_widgets - 3
+        focus_pos = self.overhang + (wig - 0.5) * self.line_height
+        if focus_pos > 40:
+            self.overhang -= 7
+        if focus_pos < -40:
+            self.overhang += 7
+        self.y = self.overhang
+        self.widget_no = 0
+        ctx.rectangle(-120, -120, 240, 240)
+        ctx.gray(0)
+        ctx.fill()
+        ctx.save()
+        ctx.translate(self.x, -100)
+        ctx.font_size = 20
+        ctx.gray(0.8)
+        ctx.text("audio settings")
+        ctx.restore()
+        ctx.font_size = self.font_size
+        self.x += self.delta_ms * self.x_vel
+        if self.x < -50 or self.x > 50:
+            self.x_vel *= -1
+            self.x += self.delta_ms * self.x_vel
+
+    def draw(self, ctx: Context):
+        self.ctx = ctx
+        self.draw_bg()
+
+        tmp = self.draw_number(
+            "led brightness", 8, int(settings.num_leds_brightness.value)
+        )
+        if tmp < 7:
+            tmp = 7
+        elif tmp > 255:
+            tmp = 255
+        if tmp != settings.num_leds_brightness.value:
+            settings.num_leds_brightness.set_value(tmp)
+            leds.set_brightness(settings.num_leds_brightness.value)
+
+        tmp = self.draw_number("led speed", 7, int(settings.num_leds_speed.value))
+        if tmp > settings.num_leds_speed.value:
+            tmp = settings.num_leds_speed.value * 2
+        elif tmp < settings.num_leds_speed.value:
+            tmp = (settings.num_leds_speed.value + 1) // 2
+        if tmp < 1:
+            tmp = 1
+        elif tmp > 255:
+            tmp = 255
+        if tmp != settings.num_leds_speed.value:
+            settings.num_leds_speed.set_value(tmp)
+            leds.set_slew_rate(settings.num_leds_speed.value)
+            if 255 == settings.num_leds_speed.value:
+                leds.set_auto_update(0)
+            else:
+                leds.set_auto_update(1)
+
+        tmp = self.draw_number(
+            "display brightness",
+            10,
+            int(settings.num_display_brightness.value),
+            unit="%",
+        )
+        if tmp < 5:
+            tmp = 5
+        if tmp > 100:
+            tmp = 100
+        if tmp != settings.num_display_brightness.value:
+            settings.num_display_brightness.set_value(tmp)
+            sys_display.set_backlight(settings.num_display_brightness.value)
+
+        self.delta_ms = 0
+        self.select_pressed = False
+        self.left_pressed = False
+        self.right_pressed = False
+
+    def think(self, ins, delta_ms):
+        super().think(ins, delta_ms)
+        self.delta_ms += delta_ms
+        if self.focused_widget == 2:
+            self.led_accumulator_ms += delta_ms
+        if (
+            self.input.buttons.app.right.pressed
+            or self.input.buttons.app.right.repeated
+        ):
+            self.right_pressed = True
+        if self.input.buttons.app.left.pressed or self.input.buttons.app.left.repeated:
+            self.left_pressed = True
+        if self.input.buttons.app.middle.pressed:
+            self.select_pressed = True
+
+        while self.led_accumulator_ms > 500:
+            self.led_accumulator_ms = self.led_accumulator_ms % 500
+            self.leds_toggle()
+
+    def leds_toggle(self):
+        self.blueish = not self.blueish
+        if self.blueish:
+            leds.set_all_rgb(0, 127, 255)
+        else:
+            leds.set_all_rgb(127, 0, 255)
+        leds.update()
+
+    def on_enter(self, vm):
+        super().on_enter(vm)
+        settings.load_all()
+        self.leds_toggle()
+
+    def on_exit(self):
+        settings.save_all()
+        super().on_exit()
+
+
+if __name__ == "__main__":
+    from st3m.run import run_app
+
+    run_app(App)
diff --git a/python_payload/apps/appearance/audio_config/__init__.py b/python_payload/apps/appearance/audio_config/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3df2bed300b26b9028b605db21b372c537fbdafa
--- /dev/null
+++ b/python_payload/apps/appearance/audio_config/__init__.py
@@ -0,0 +1,296 @@
+from st3m.application import Application
+import math, random, sys_display
+from st3m import settings
+import audio
+
+
+class App(Application):
+    def __init__(self, app_ctx):
+        super().__init__(app_ctx)
+
+        self.x = 23
+        self.x_vel = 40 / 1000.0
+
+        self.y = 0
+        self.font_size = 20
+        self.delta_ms = 0
+        self.right_pressed = False
+        self.left_pressed = False
+        self.select_pressed = False
+        self.angle = 0
+        self.focused_widget = 1
+        self.active = False
+        self.num_widgets = 11
+        self.overhang = -70
+        self.line_height = 24
+        self.input.buttons.app.left.repeat_enable(800, 300)
+        self.input.buttons.app.right.repeat_enable(800, 300)
+        self.mid_x = 30
+
+    def draw_widget(self, label):
+        ctx = self.ctx
+        self.widget_no += 1
+        if not self.active:
+            if self.select_pressed and self.focused_widget > 0:
+                self.active = True
+                self.select_pressed = False
+            elif self.left_pressed:
+                self.focused_widget -= 1
+                if self.focused_widget < 1:
+                    self.focused_widget = 1
+                self.left_pressed = False
+            elif self.right_pressed:
+                self.focused_widget += 1
+                if self.focused_widget > self.num_widgets - 1:
+                    self.focused_widget = self.num_widgets - 1
+                self.right_pressed = False
+        if self.widget_no == self.focused_widget and not self.active:
+            ctx.rectangle(-130, int(self.y - self.font_size * 0.8), 260, self.font_size)
+            ctx.line_width = 2.0
+            ctx.rgba(0.8, 0.6, 0.1, 1.0)
+            ctx.stroke()
+        ctx.gray(1)
+        ctx.move_to(self.mid_x, self.y)
+        ctx.save()
+        ctx.rgb(0.8, 0.8, 0.8)
+        ctx.text_align = ctx.RIGHT
+        ctx.text(label + ": ")
+        ctx.restore()
+        self.y += self.line_height
+
+    def draw_choice(self, label, choices, no):
+        ctx = self.ctx
+        self.draw_widget(label)
+        if self.widget_no == self.focused_widget and self.active:
+            if self.left_pressed:
+                no -= 1
+                if no < 0:
+                    no = 0
+            elif self.right_pressed:
+                no += 1
+                if no >= len(choices):
+                    no = len(choices) - 1
+            elif self.select_pressed:
+                self.active = False
+                self.select_pressed = False
+
+        for a in range(len(choices)):
+            if a == no and self.active and self.widget_no == self.focused_widget:
+                ctx.save()
+                ctx.rgba(0.8, 0.6, 0.1, 1.0)
+                ctx.rectangle(
+                    ctx.x - 1,
+                    ctx.y - self.font_size * 0.8,
+                    ctx.text_width(choices[a]) + 2,
+                    self.font_size,
+                ).stroke()
+                ctx.restore()
+                ctx.text(choices[a] + " ")
+            elif a == no:
+                ctx.save()
+                ctx.gray(1)
+                ctx.rectangle(
+                    ctx.x - 1,
+                    ctx.y - self.font_size * 0.8,
+                    ctx.text_width(choices[a]) + 2,
+                    self.font_size,
+                ).fill()
+                ctx.gray(0)
+                ctx.text(choices[a] + " ")
+                ctx.restore()
+            else:
+                ctx.text(choices[a] + " ")
+        return no
+
+    def draw_number(self, label, step_size, no, unit=""):
+        ctx = self.ctx
+        self.draw_widget(label)
+        ret = no
+        if self.widget_no == self.focused_widget and self.active:
+            if self.left_pressed:
+                ret -= step_size
+            elif self.right_pressed:
+                ret += step_size
+            elif self.select_pressed:
+                self.active = False
+                self.select_pressed = False
+
+        if self.active and self.widget_no == self.focused_widget:
+            ctx.save()
+            ctx.rgba(0.8, 0.6, 0.1, 1.0)
+            ctx.rectangle(
+                ctx.x - 1,
+                ctx.y - self.font_size * 0.8,
+                ctx.text_width(str(no)[:4]) + 2,
+                self.font_size,
+            ).stroke()
+            ctx.restore()
+            ctx.text(str(no)[:4] + unit)
+        else:
+            ctx.text(str(no)[:4] + unit)
+        return ret
+
+    def draw_bg(self):
+        ctx = self.ctx
+        ctx.gray(1.0)
+        ctx.move_to(-100, -80)
+        wig = self.focused_widget - 1
+        if wig < 2:
+            wig = 2
+        if wig > self.num_widgets - 3:
+            wig = self.num_widgets - 3
+        focus_pos = self.overhang + (wig - 0.5) * self.line_height
+        if focus_pos > 40:
+            self.overhang -= 7
+        if focus_pos < -40:
+            self.overhang += 7
+        self.y = self.overhang
+        self.widget_no = 0
+        ctx.rectangle(-120, -120, 240, 240)
+        ctx.gray(0)
+        ctx.fill()
+        ctx.save()
+        ctx.translate(self.x, -100)
+        ctx.font_size = 20
+        ctx.gray(0.8)
+        ctx.text("audio settings")
+        ctx.restore()
+        ctx.font_size = self.font_size
+        self.x += self.delta_ms * self.x_vel
+        if self.x < -50 or self.x > 50:
+            self.x_vel *= -1
+            self.x += self.delta_ms * self.x_vel
+
+    def draw(self, ctx: Context):
+        self.ctx = ctx
+        self.draw_bg()
+
+        tmp = self.draw_number(
+            "vol step", 0.5, float(settings.num_volume_step_db.value), unit="dB"
+        )
+        if tmp < 0.5:
+            tmp = 0.5
+        if tmp > 5:
+            tmp = 5
+        settings.num_volume_step_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "vol repeat step",
+            0.5,
+            float(settings.num_volume_repeat_step_db.value),
+            unit="dB",
+        )
+        if tmp < 0:
+            tmp = 0
+        if tmp > 5:
+            tmp = 5
+        settings.num_volume_repeat_step_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "vol repeat wait",
+            50,
+            int(settings.num_volume_repeat_wait_ms.value),
+            unit="ms",
+        )
+        if tmp < 100:
+            tmp = 100
+        if tmp > 1000:
+            tmp = 1000
+        settings.num_volume_repeat_wait_ms.set_value(tmp)
+
+        tmp = self.draw_number(
+            "vol repeat", 50, int(settings.num_volume_repeat_ms.value), unit="ms"
+        )
+        if tmp < 100:
+            tmp = 100
+        if tmp > 1000:
+            tmp = 1000
+        settings.num_volume_repeat_ms.set_value(tmp)
+
+        tmp = self.draw_number(
+            "phones startup",
+            1,
+            int(settings.num_headphones_startup_volume_db.value),
+            unit="dB",
+        )
+        if tmp < -70:
+            tmp = -70
+        if tmp > 3:
+            tmp = 3
+        settings.num_headphones_startup_volume_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "phones min", 1, int(settings.num_headphones_min_db.value), unit="dB"
+        )
+        if settings.num_headphones_min_db.value != tmp:
+            audio.headphones_set_minimum_volume_dB(tmp)
+            settings.num_headphones_min_db.set_value(
+                audio.headphones_get_minimum_volume_dB()
+            )
+
+        tmp = self.draw_number(
+            "phones max", 1, int(settings.num_headphones_max_db.value), unit="dB"
+        )
+        if settings.num_headphones_max_db.value != tmp:
+            audio.headphones_set_maximum_volume_dB(tmp)
+            settings.num_headphones_max_db.set_value(
+                audio.headphones_get_maximum_volume_dB()
+            )
+
+        tmp = self.draw_number(
+            "speaker startup",
+            1,
+            int(settings.num_speaker_startup_volume_db.value),
+            unit="dB",
+        )
+        if tmp < -60:
+            tmp = -60
+        if tmp > 14:
+            tmp = 14
+        settings.num_speaker_startup_volume_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "speaker min", 1, int(settings.num_speaker_min_db.value), unit="dB"
+        )
+        if settings.num_speaker_min_db.value != tmp:
+            audio.speaker_set_minimum_volume_dB(tmp)
+            settings.num_speaker_min_db.set_value(audio.speaker_get_minimum_volume_dB())
+
+        tmp = self.draw_number(
+            "speaker max", 1, int(settings.num_speaker_max_db.value), unit="dB"
+        )
+        if settings.num_speaker_max_db.value != tmp:
+            audio.speaker_set_maximum_volume_dB(tmp)
+            settings.num_speaker_max_db.set_value(audio.speaker_get_maximum_volume_dB())
+
+        self.delta_ms = 0
+        self.select_pressed = False
+        self.left_pressed = False
+        self.right_pressed = False
+
+    def think(self, ins, delta_ms):
+        super().think(ins, delta_ms)
+        self.delta_ms += delta_ms
+        if (
+            self.input.buttons.app.right.pressed
+            or self.input.buttons.app.right.repeated
+        ):
+            self.right_pressed = True
+        if self.input.buttons.app.left.pressed or self.input.buttons.app.left.repeated:
+            self.left_pressed = True
+        if self.input.buttons.app.middle.pressed:
+            self.select_pressed = True
+
+    def on_enter(self, vm):
+        super().on_enter(vm)
+        settings.load_all()
+
+    def on_exit(self):
+        settings.save_all()
+        super().on_exit()
+
+
+if __name__ == "__main__":
+    from st3m.run import run_app
+
+    run_app(App)
diff --git a/python_payload/apps/appearance/audio_config/flow3r.toml b/python_payload/apps/appearance/audio_config/flow3r.toml
new file mode 100644
index 0000000000000000000000000000000000000000..31ab43fbd9fed65189ac75ab20ecaaae8b3a81f2
--- /dev/null
+++ b/python_payload/apps/appearance/audio_config/flow3r.toml
@@ -0,0 +1,8 @@
+[app]
+name = "Audio Config"
+menu = "Hidden"
+
+[metadata]
+author = "Flow3r Badge Authors"
+license = "LGPL-3.0-only"
+url = "https://git.flow3r.garden/flow3r/flow3r-firmware"
diff --git a/python_payload/apps/appearance/flow3r.toml b/python_payload/apps/appearance/flow3r.toml
new file mode 100644
index 0000000000000000000000000000000000000000..fe2957f7256d9fa025b61e8c13952dd98858594f
--- /dev/null
+++ b/python_payload/apps/appearance/flow3r.toml
@@ -0,0 +1,8 @@
+[app]
+name = "Appearance"
+menu = "Hidden"
+
+[metadata]
+author = "Flow3r Badge Authors"
+license = "LGPL-3.0-only"
+url = "https://git.flow3r.garden/flow3r/flow3r-firmware"
diff --git a/python_payload/apps/audio_config/__init__.py b/python_payload/apps/audio_config/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3df2bed300b26b9028b605db21b372c537fbdafa
--- /dev/null
+++ b/python_payload/apps/audio_config/__init__.py
@@ -0,0 +1,296 @@
+from st3m.application import Application
+import math, random, sys_display
+from st3m import settings
+import audio
+
+
+class App(Application):
+    def __init__(self, app_ctx):
+        super().__init__(app_ctx)
+
+        self.x = 23
+        self.x_vel = 40 / 1000.0
+
+        self.y = 0
+        self.font_size = 20
+        self.delta_ms = 0
+        self.right_pressed = False
+        self.left_pressed = False
+        self.select_pressed = False
+        self.angle = 0
+        self.focused_widget = 1
+        self.active = False
+        self.num_widgets = 11
+        self.overhang = -70
+        self.line_height = 24
+        self.input.buttons.app.left.repeat_enable(800, 300)
+        self.input.buttons.app.right.repeat_enable(800, 300)
+        self.mid_x = 30
+
+    def draw_widget(self, label):
+        ctx = self.ctx
+        self.widget_no += 1
+        if not self.active:
+            if self.select_pressed and self.focused_widget > 0:
+                self.active = True
+                self.select_pressed = False
+            elif self.left_pressed:
+                self.focused_widget -= 1
+                if self.focused_widget < 1:
+                    self.focused_widget = 1
+                self.left_pressed = False
+            elif self.right_pressed:
+                self.focused_widget += 1
+                if self.focused_widget > self.num_widgets - 1:
+                    self.focused_widget = self.num_widgets - 1
+                self.right_pressed = False
+        if self.widget_no == self.focused_widget and not self.active:
+            ctx.rectangle(-130, int(self.y - self.font_size * 0.8), 260, self.font_size)
+            ctx.line_width = 2.0
+            ctx.rgba(0.8, 0.6, 0.1, 1.0)
+            ctx.stroke()
+        ctx.gray(1)
+        ctx.move_to(self.mid_x, self.y)
+        ctx.save()
+        ctx.rgb(0.8, 0.8, 0.8)
+        ctx.text_align = ctx.RIGHT
+        ctx.text(label + ": ")
+        ctx.restore()
+        self.y += self.line_height
+
+    def draw_choice(self, label, choices, no):
+        ctx = self.ctx
+        self.draw_widget(label)
+        if self.widget_no == self.focused_widget and self.active:
+            if self.left_pressed:
+                no -= 1
+                if no < 0:
+                    no = 0
+            elif self.right_pressed:
+                no += 1
+                if no >= len(choices):
+                    no = len(choices) - 1
+            elif self.select_pressed:
+                self.active = False
+                self.select_pressed = False
+
+        for a in range(len(choices)):
+            if a == no and self.active and self.widget_no == self.focused_widget:
+                ctx.save()
+                ctx.rgba(0.8, 0.6, 0.1, 1.0)
+                ctx.rectangle(
+                    ctx.x - 1,
+                    ctx.y - self.font_size * 0.8,
+                    ctx.text_width(choices[a]) + 2,
+                    self.font_size,
+                ).stroke()
+                ctx.restore()
+                ctx.text(choices[a] + " ")
+            elif a == no:
+                ctx.save()
+                ctx.gray(1)
+                ctx.rectangle(
+                    ctx.x - 1,
+                    ctx.y - self.font_size * 0.8,
+                    ctx.text_width(choices[a]) + 2,
+                    self.font_size,
+                ).fill()
+                ctx.gray(0)
+                ctx.text(choices[a] + " ")
+                ctx.restore()
+            else:
+                ctx.text(choices[a] + " ")
+        return no
+
+    def draw_number(self, label, step_size, no, unit=""):
+        ctx = self.ctx
+        self.draw_widget(label)
+        ret = no
+        if self.widget_no == self.focused_widget and self.active:
+            if self.left_pressed:
+                ret -= step_size
+            elif self.right_pressed:
+                ret += step_size
+            elif self.select_pressed:
+                self.active = False
+                self.select_pressed = False
+
+        if self.active and self.widget_no == self.focused_widget:
+            ctx.save()
+            ctx.rgba(0.8, 0.6, 0.1, 1.0)
+            ctx.rectangle(
+                ctx.x - 1,
+                ctx.y - self.font_size * 0.8,
+                ctx.text_width(str(no)[:4]) + 2,
+                self.font_size,
+            ).stroke()
+            ctx.restore()
+            ctx.text(str(no)[:4] + unit)
+        else:
+            ctx.text(str(no)[:4] + unit)
+        return ret
+
+    def draw_bg(self):
+        ctx = self.ctx
+        ctx.gray(1.0)
+        ctx.move_to(-100, -80)
+        wig = self.focused_widget - 1
+        if wig < 2:
+            wig = 2
+        if wig > self.num_widgets - 3:
+            wig = self.num_widgets - 3
+        focus_pos = self.overhang + (wig - 0.5) * self.line_height
+        if focus_pos > 40:
+            self.overhang -= 7
+        if focus_pos < -40:
+            self.overhang += 7
+        self.y = self.overhang
+        self.widget_no = 0
+        ctx.rectangle(-120, -120, 240, 240)
+        ctx.gray(0)
+        ctx.fill()
+        ctx.save()
+        ctx.translate(self.x, -100)
+        ctx.font_size = 20
+        ctx.gray(0.8)
+        ctx.text("audio settings")
+        ctx.restore()
+        ctx.font_size = self.font_size
+        self.x += self.delta_ms * self.x_vel
+        if self.x < -50 or self.x > 50:
+            self.x_vel *= -1
+            self.x += self.delta_ms * self.x_vel
+
+    def draw(self, ctx: Context):
+        self.ctx = ctx
+        self.draw_bg()
+
+        tmp = self.draw_number(
+            "vol step", 0.5, float(settings.num_volume_step_db.value), unit="dB"
+        )
+        if tmp < 0.5:
+            tmp = 0.5
+        if tmp > 5:
+            tmp = 5
+        settings.num_volume_step_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "vol repeat step",
+            0.5,
+            float(settings.num_volume_repeat_step_db.value),
+            unit="dB",
+        )
+        if tmp < 0:
+            tmp = 0
+        if tmp > 5:
+            tmp = 5
+        settings.num_volume_repeat_step_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "vol repeat wait",
+            50,
+            int(settings.num_volume_repeat_wait_ms.value),
+            unit="ms",
+        )
+        if tmp < 100:
+            tmp = 100
+        if tmp > 1000:
+            tmp = 1000
+        settings.num_volume_repeat_wait_ms.set_value(tmp)
+
+        tmp = self.draw_number(
+            "vol repeat", 50, int(settings.num_volume_repeat_ms.value), unit="ms"
+        )
+        if tmp < 100:
+            tmp = 100
+        if tmp > 1000:
+            tmp = 1000
+        settings.num_volume_repeat_ms.set_value(tmp)
+
+        tmp = self.draw_number(
+            "phones startup",
+            1,
+            int(settings.num_headphones_startup_volume_db.value),
+            unit="dB",
+        )
+        if tmp < -70:
+            tmp = -70
+        if tmp > 3:
+            tmp = 3
+        settings.num_headphones_startup_volume_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "phones min", 1, int(settings.num_headphones_min_db.value), unit="dB"
+        )
+        if settings.num_headphones_min_db.value != tmp:
+            audio.headphones_set_minimum_volume_dB(tmp)
+            settings.num_headphones_min_db.set_value(
+                audio.headphones_get_minimum_volume_dB()
+            )
+
+        tmp = self.draw_number(
+            "phones max", 1, int(settings.num_headphones_max_db.value), unit="dB"
+        )
+        if settings.num_headphones_max_db.value != tmp:
+            audio.headphones_set_maximum_volume_dB(tmp)
+            settings.num_headphones_max_db.set_value(
+                audio.headphones_get_maximum_volume_dB()
+            )
+
+        tmp = self.draw_number(
+            "speaker startup",
+            1,
+            int(settings.num_speaker_startup_volume_db.value),
+            unit="dB",
+        )
+        if tmp < -60:
+            tmp = -60
+        if tmp > 14:
+            tmp = 14
+        settings.num_speaker_startup_volume_db.set_value(tmp)
+
+        tmp = self.draw_number(
+            "speaker min", 1, int(settings.num_speaker_min_db.value), unit="dB"
+        )
+        if settings.num_speaker_min_db.value != tmp:
+            audio.speaker_set_minimum_volume_dB(tmp)
+            settings.num_speaker_min_db.set_value(audio.speaker_get_minimum_volume_dB())
+
+        tmp = self.draw_number(
+            "speaker max", 1, int(settings.num_speaker_max_db.value), unit="dB"
+        )
+        if settings.num_speaker_max_db.value != tmp:
+            audio.speaker_set_maximum_volume_dB(tmp)
+            settings.num_speaker_max_db.set_value(audio.speaker_get_maximum_volume_dB())
+
+        self.delta_ms = 0
+        self.select_pressed = False
+        self.left_pressed = False
+        self.right_pressed = False
+
+    def think(self, ins, delta_ms):
+        super().think(ins, delta_ms)
+        self.delta_ms += delta_ms
+        if (
+            self.input.buttons.app.right.pressed
+            or self.input.buttons.app.right.repeated
+        ):
+            self.right_pressed = True
+        if self.input.buttons.app.left.pressed or self.input.buttons.app.left.repeated:
+            self.left_pressed = True
+        if self.input.buttons.app.middle.pressed:
+            self.select_pressed = True
+
+    def on_enter(self, vm):
+        super().on_enter(vm)
+        settings.load_all()
+
+    def on_exit(self):
+        settings.save_all()
+        super().on_exit()
+
+
+if __name__ == "__main__":
+    from st3m.run import run_app
+
+    run_app(App)
diff --git a/python_payload/apps/audio_config/flow3r.toml b/python_payload/apps/audio_config/flow3r.toml
new file mode 100644
index 0000000000000000000000000000000000000000..31ab43fbd9fed65189ac75ab20ecaaae8b3a81f2
--- /dev/null
+++ b/python_payload/apps/audio_config/flow3r.toml
@@ -0,0 +1,8 @@
+[app]
+name = "Audio Config"
+menu = "Hidden"
+
+[metadata]
+author = "Flow3r Badge Authors"
+license = "LGPL-3.0-only"
+url = "https://git.flow3r.garden/flow3r/flow3r-firmware"
diff --git a/python_payload/apps/graphics_mode/__init__.py b/python_payload/apps/graphics_mode/__init__.py
index 5a4bd83b203bd5e2b33a9c81f2304cb7b41680af..40296bcc134d94730177a2b02a8f7325e81da0ce 100644
--- a/python_payload/apps/graphics_mode/__init__.py
+++ b/python_payload/apps/graphics_mode/__init__.py
@@ -18,6 +18,8 @@ class App(Application):
         self.angle = 0
         self.focused_widget = 2
         self.active = False
+        self.min_focus = 0
+        self.min_focus = 3
 
     def draw_widget(self, label):
         ctx = self.ctx
diff --git a/python_payload/st3m/application.py b/python_payload/st3m/application.py
index 4d1dc47431b35017727a4c05cc256c59f6dae48a..b49557aad204da586169adecc65d1af8f5b91c79 100644
--- a/python_payload/st3m/application.py
+++ b/python_payload/st3m/application.py
@@ -67,8 +67,11 @@ class Application(BaseView):
             st3m.wifi.setup_wifi()
         elif self._wifi_preference is False:
             st3m.wifi.disable()
-        leds.set_auto_update(0)
-        leds.set_slew_rate(255)
+        leds.set_slew_rate(settings.num_leds_speed.value)
+        if 255 == settings.num_leds_speed.value:
+            leds.set_auto_update(0)
+        else:
+            leds.set_auto_update(1)
         super().on_enter(vm)
 
     def on_exit(self) -> None:
diff --git a/python_payload/st3m/processors.py b/python_payload/st3m/processors.py
index be45fd771ec5022dad715d3b97794e60d06b21a0..033545d9d08cf4053b6d7bb18669736241eba537 100644
--- a/python_payload/st3m/processors.py
+++ b/python_payload/st3m/processors.py
@@ -30,13 +30,42 @@ class AudioProcessor(Processor):
     def __init__(self) -> None:
         super().__init__()
         self.input = InputController()
+        self.repeat_wait_ms = 800
+        self.repeat_ms = 300
+        self._update_repeat()
+
+    def _update_repeat(self):
+        changed = False
+        if self.repeat_wait_ms != settings.num_volume_repeat_wait_ms.value:
+            changed = True
+        if self.repeat_ms != settings.num_volume_repeat_ms.value:
+            changed = True
+        if changed:
+            self.repeat_wait_ms = settings.num_volume_repeat_wait_ms.value
+            self.repeat_ms = settings.num_volume_repeat_ms.value
+            self.input.buttons.os.left.repeat_enable(
+                self.repeat_wait_ms, self.repeat_ms
+            )
+            self.input.buttons.os.right.repeat_enable(
+                self.repeat_wait_ms, self.repeat_ms
+            )
 
     def think(self, ins: InputState, delta_ms: int) -> None:
         self.input.think(ins, delta_ms)
-        if self.input.buttons.os.left.pressed:
+        os_button = self.input.buttons.os
+        event = True
+        if os_button.left.pressed:
             audio.adjust_volume_dB(-settings.num_volume_step_db.value)
-        if self.input.buttons.os.right.pressed:
+        elif os_button.right.pressed:
             audio.adjust_volume_dB(settings.num_volume_step_db.value)
+        elif os_button.left.repeated:
+            audio.adjust_volume_dB(-settings.num_volume_repeat_step_db.value)
+        elif os_button.right.repeated:
+            audio.adjust_volume_dB(settings.num_volume_repeat_step_db.value)
+        else:
+            event = False
+        if event:
+            self._update_repeat()
 
 
 class ProcessorMidldeware(Responder):
diff --git a/python_payload/st3m/run.py b/python_payload/st3m/run.py
index 0b7761dcc75bf48bd800080308b65f8d6d610ea6..f609dead4f0f2c241ddb2708b97b474a05ff073a 100644
--- a/python_payload/st3m/run.py
+++ b/python_payload/st3m/run.py
@@ -151,9 +151,16 @@ def run_main() -> None:
     audio.headphones_set_volume_dB(settings.num_headphones_startup_volume_db.value)
     audio.speaker_set_volume_dB(settings.num_speaker_startup_volume_db.value)
     audio.headphones_set_minimum_volume_dB(settings.num_headphones_min_db.value)
-    audio.speaker_set_minimum_volume_dB(settings.num_speakers_min_db.value)
+    audio.speaker_set_minimum_volume_dB(settings.num_speaker_min_db.value)
     audio.headphones_set_maximum_volume_dB(settings.num_headphones_max_db.value)
-    audio.speaker_set_maximum_volume_dB(settings.num_speakers_max_db.value)
+    audio.speaker_set_maximum_volume_dB(settings.num_speaker_max_db.value)
+    leds.set_brightness(settings.num_leds_brightness.value)
+    leds.set_slew_rate(settings.num_leds_speed.value)
+    if 255 == settings.num_leds_speed.value:
+        leds.set_auto_update(0)
+    else:
+        leds.set_auto_update(1)
+    sys_display.set_backlight(settings.num_display_brightness.value)
 
     leds.set_rgb(0, 255, 0, 0)
     leds.update()
diff --git a/python_payload/st3m/settings.py b/python_payload/st3m/settings.py
index 6cd7409d65f80518e462e836cf5f5efa62dfdb1c..48f62a22bc0dd0c154e599e83f434999a2e57d63 100644
--- a/python_payload/st3m/settings.py
+++ b/python_payload/st3m/settings.py
@@ -207,9 +207,20 @@ onoff_wifi_preference = OnOffTunable(
 str_wifi_ssid = StringTunable("WiFi SSID", "system.wifi.ssid", "Camp2023-open")
 str_wifi_psk = ObfuscatedStringTunable("WiFi Password", "system.wifi.psk", None)
 str_hostname = StringTunable("Hostname", "system.hostname", "flow3r")
+
 num_volume_step_db = StringTunable(
-    "Volume Change dB", "system.audio.volume_step_dB", 2.5
+    "Volume Change dB", "system.audio.volume_step_dB", 1.5
+)
+num_volume_repeat_step_db = StringTunable(
+    "Volume Repeat Change dB", "system.audio.volume_repeat_step_dB", 2.5
+)
+num_volume_repeat_wait_ms = StringTunable(
+    "Volume Repeat Wait Time ms", "system.audio.volume_repeat_wait_ms", 800
+)
+num_volume_repeat_ms = StringTunable(
+    "Volume Repeat Time ms", "system.audio.volume_repeat_ms", 300
 )
+
 num_speaker_startup_volume_db = StringTunable(
     "Speaker Startup Volume dB", "system.audio.speaker_startup_volume_dB", -10
 )
@@ -219,15 +230,22 @@ num_headphones_startup_volume_db = StringTunable(
 num_headphones_min_db = StringTunable(
     "Min Headphone Volume dB", "system.audio.headphones_min_dB", -45
 )
-num_speakers_min_db = StringTunable(
-    "Min Speakers Volume dB", "system.audio.speakers_min_dB", -40
+num_speaker_min_db = StringTunable(
+    "Min Speaker Volume dB", "system.audio.speakers_min_dB", -40
 )
 num_headphones_max_db = StringTunable(
     "Max Headphone Volume dB", "system.audio.headphones_max_dB", 3
 )
-num_speakers_max_db = StringTunable(
-    "Max Speakers Volume dB", "system.audio.speakers_max_dB", 14
+num_speaker_max_db = StringTunable(
+    "Max Speaker Volume dB", "system.audio.speakers_max_dB", 14
+)
+
+num_display_brightness = StringTunable(
+    "Display Brightness", "system.brightness.display", 100
 )
+num_leds_brightness = StringTunable("LED Brightness", "system.brightness.leds", 200)
+
+num_leds_speed = StringTunable("LED speed", "system.brightness.leds_speed", 255)
 
 # List of all settings to be loaded/saved
 load_save_settings: List[UnaryTunable] = [
@@ -243,12 +261,18 @@ load_save_settings: List[UnaryTunable] = [
     str_wifi_psk,
     str_hostname,
     num_volume_step_db,
+    num_volume_repeat_step_db,
+    num_volume_repeat_wait_ms,
+    num_volume_repeat_ms,
     num_speaker_startup_volume_db,
     num_headphones_startup_volume_db,
     num_headphones_min_db,
-    num_speakers_min_db,
+    num_speaker_min_db,
     num_headphones_max_db,
-    num_speakers_max_db,
+    num_speaker_max_db,
+    num_display_brightness,
+    num_leds_brightness,
+    num_leds_speed,
 ]
 
 
diff --git a/python_payload/st3m/settings_menu.py b/python_payload/st3m/settings_menu.py
index c775baacf4b16ee2567645a07b05a5f96914c365..6a0eeb432f5f28ca1d58d16bc4e26c8c48242856 100644
--- a/python_payload/st3m/settings_menu.py
+++ b/python_payload/st3m/settings_menu.py
@@ -214,6 +214,8 @@ if TYPE_CHECKING:
 # Main settings menu
 settings_menu_structure: "MenuStructure" = [
     MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/w1f1")),
+    MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/audio_config")),
+    MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/appearance")),
     onoff_wifi,
     onoff_wifi_preference,
     onoff_show_tray,
diff --git a/sim/fakes/leds.py b/sim/fakes/leds.py
index 6df4deb57d7c42ccf4769186be3c927a29a55a46..c7144899bcab079f133c49b627ab39d76bf40894 100644
--- a/sim/fakes/leds.py
+++ b/sim/fakes/leds.py
@@ -47,3 +47,7 @@ def update():
 
 def set_auto_update(b: int):
     pass
+
+
+def set_brightness(b: float):
+    pass
diff --git a/sim/fakes/sys_display.py b/sim/fakes/sys_display.py
index a2f38c76a7eb5868674464ca6ebdeff98c3860aa..f8aff92572d848a13640a699708172c02fa7f33b 100644
--- a/sim/fakes/sys_display.py
+++ b/sim/fakes/sys_display.py
@@ -25,3 +25,7 @@ osd = 256
 
 def ctx(foo):
     return _sim.get_ctx()
+
+
+def set_backlight(a):
+    pass