diff --git a/nixosModules/ags/default.nix b/nixosModules/ags/default.nix
index 26e61e64..430bc858 100644
--- a/nixosModules/ags/default.nix
+++ b/nixosModules/ags/default.nix
@@ -142,6 +142,7 @@ in {
 
           wayland.windowManager.hyprland = let
             runAgs = cmd: "pgrep ags -a | grep '/bin/gjs' && ags ${cmd} || agsV2 ${cmd}";
+            runAgsJs = cmd: "pgrep ags -a | grep '/bin/gjs' && ags -r ${cmd} || agsV2 -m ${cmd}";
           in {
             settings = {
               animations = {
@@ -178,11 +179,11 @@ in {
               ];
               binde = [
                 ## Brightness control
-                ", XF86MonBrightnessUp  , exec, ${runAgs "-r 'Brightness.screen += 0.05'"}"
-                ", XF86MonBrightnessDown, exec, ${runAgs "-r 'Brightness.screen -= 0.05'"}"
+                ", XF86MonBrightnessUp  , exec, ${runAgsJs "'Brightness.screen += 0.05'"}"
+                ", XF86MonBrightnessDown, exec, ${runAgsJs "'Brightness.screen -= 0.05'"}"
               ];
-              bindn = ["    , Escape   , exec, ${runAgs "-r 'closeAll()'"}"];
-              bindr = ["CAPS, Caps_Lock, exec, ${runAgs "-r 'Brightness.fetchCapsState()'"}"];
+              bindn = ["    , Escape   , exec, ${runAgsJs "'closeAll()'"}"];
+              bindr = ["CAPS, Caps_Lock, exec, ${runAgsJs "'Brightness.fetchCapsState()'"}"];
             };
           };
         })
diff --git a/nixosModules/ags/v2/app.ts b/nixosModules/ags/v2/app.ts
index 828e52e3..5dab4e54 100644
--- a/nixosModules/ags/v2/app.ts
+++ b/nixosModules/ags/v2/app.ts
@@ -14,10 +14,20 @@ import { NotifPopups, NotifCenter } from './widgets/notifs/main';
 import PowerMenu from './widgets/powermenu/main';
 import Screenshot from './widgets/screenshot/main';
 
+import { closeAll as closeAllFunc } from './lib';
+import BrightnessService from './services/brightness';
 import MonitorClicks from './services/monitor-clicks';
 
 import Lockscreen from './widgets/lockscreen/main';
 
+declare global {
+    function closeAll(): void;
+    // eslint-disable-next-line
+    var Brightness: typeof BrightnessService;
+}
+globalThis.closeAll = closeAllFunc;
+globalThis.Brightness = BrightnessService;
+
 
 const CONF = GLib.getenv('CONF');
 
@@ -39,6 +49,10 @@ switch (CONF) {
         App.start({
             css: style,
 
+            requestHandler(js, res) {
+                App.eval(js).then(res).catch(res);
+            },
+
             main: () => {
                 AppLauncher();
                 Bar();
@@ -51,6 +65,10 @@ switch (CONF) {
                 PowerMenu();
                 Screenshot();
 
+                Brightness.initService({
+                    kbd: 'tpacpi::kbd_backlight',
+                    caps: 'input1::capslock',
+                });
                 new MonitorClicks();
             },
         });
diff --git a/nixosModules/ags/v2/lib.ts b/nixosModules/ags/v2/lib.ts
index c5a54c71..84fe0fee 100644
--- a/nixosModules/ags/v2/lib.ts
+++ b/nixosModules/ags/v2/lib.ts
@@ -1,9 +1,10 @@
-import { Gdk } from 'astal/gtk3';
+import { App, Gdk } from 'astal/gtk3';
 
 import AstalHyprland from 'gi://AstalHyprland';
 const Hyprland = AstalHyprland.get_default();
 
 /* Types */
+import type { PopupWindow } from './widgets/misc/popup-window';
 export interface Layer {
     address: string
     x: number
@@ -109,3 +110,13 @@ export const centerCursor = async(): Promise<void> => {
 
     await hyprMessage(`dispatch movecursor ${x} ${y}`);
 };
+
+export const closeAll = () => {
+    (App.get_windows() as PopupWindow[])
+        .filter((w) => w &&
+          w.close_on_unfocus &&
+          w.close_on_unfocus !== 'stay')
+        .forEach((w) => {
+            App.get_window(w.name)?.set_visible(false);
+        });
+};
diff --git a/nixosModules/ags/v2/services/brightness.ts b/nixosModules/ags/v2/services/brightness.ts
new file mode 100644
index 00000000..25817dec
--- /dev/null
+++ b/nixosModules/ags/v2/services/brightness.ts
@@ -0,0 +1,156 @@
+import { execAsync, interval } from 'astal';
+import GObject, { register, property } from 'astal/gobject';
+
+
+const SCREEN_ICONS: Record<number, string> = {
+    90: 'display-brightness-high-symbolic',
+    70: 'display-brightness-medium-symbolic',
+    20: 'display-brightness-low-symbolic',
+    5: 'display-brightness-off-symbolic',
+};
+
+const INTERVAL = 500;
+
+
+@register()
+class Brightness extends GObject.Object {
+    declare private _kbd: string;
+    declare private _caps: string;
+
+    declare private _screen: number;
+
+    @property(Number)
+    get screen() {
+        return this._screen;
+    };
+
+    set screen(percent) {
+        if (percent < 0) {
+            percent = 0;
+        }
+
+        if (percent > 1) {
+            percent = 1;
+        }
+
+        percent = parseFloat(percent.toFixed(2));
+
+        execAsync(`brightnessctl s ${percent * 100}% -q`)
+            .then(() => {
+                this._screen = percent;
+                this.notify('screen');
+                this._getScreenIcon();
+            })
+            .catch(console.error);
+    }
+
+    declare private _screenIcon: string;
+
+    @property(String)
+    get screenIcon() {
+        return this._screenIcon;
+    }
+
+    declare private _kbdMax: number;
+    declare private _kbdLevel: number;
+
+    @property(Number)
+    get kbdLevel() {
+        return this._kbdLevel;
+    }
+
+    set kbdLevel(value) {
+        if (value < 0 || value > this._kbdMax) {
+            return;
+        }
+
+        execAsync(`brightnessctl -d ${this._kbd} s ${value} -q`)
+            .then(() => {
+                this._kbdLevel = value;
+                this.notify('kbd-level');
+            })
+            .catch(console.error);
+    }
+
+    declare private _capsLevel: number;
+
+    @property(Number)
+    get capsLevel() {
+        return this._capsLevel;
+    }
+
+    declare private _capsIcon: string;
+
+    @property(String)
+    get capsIcon() {
+        return this._capsIcon;
+    }
+
+    /**
+     * This is to basically have the constructor run when I want and
+     * still export this to wherever I need to.
+     *
+     * @param o      params
+     * @param o.kbd  name of kbd in brightnessctl
+     * @param o.caps name of caps_lock in brightnessctl
+     */
+    public async initService({ kbd = '', caps = '' }) {
+        this._kbd = kbd;
+        this._caps = caps;
+        try {
+            this._monitorKbdState();
+            this._kbdMax = Number(await execAsync(`brightnessctl -d ${this._kbd} m`));
+
+            this._screen = Number(await execAsync('brightnessctl g')) /
+                Number(await execAsync('brightnessctl m'));
+        }
+        catch (_e) {
+            console.error('missing dependancy: brightnessctl');
+        }
+    }
+
+    private _getScreenIcon() {
+        const brightness = this._screen * 100;
+
+        // eslint-disable-next-line
+        for (const threshold of [4, 19, 69, 89]) {
+            if (brightness > threshold + 1) {
+                this._screenIcon = SCREEN_ICONS[threshold + 1];
+                this.notify('screen-icon');
+            }
+        }
+    }
+
+    private _monitorKbdState() {
+        const timer = interval(INTERVAL, () => {
+            execAsync(`brightnessctl -d ${this._kbd} g`).then(
+                (out) => {
+                    if (parseInt(out) !== this._kbdLevel) {
+                        this._kbdLevel = parseInt(out);
+                        this.notify('kbd-level');
+                    }
+                },
+            ).catch(() => {
+                timer?.cancel();
+            });
+        });
+    }
+
+    public fetchCapsState() {
+        execAsync(`brightnessctl -d ${this._caps} g`)
+            .then((out) => {
+                this._capsLevel = Number(out);
+                this._capsIcon = this._capsLevel ?
+                    'caps-lock-symbolic' :
+                    'capslock-disabled-symbolic';
+
+                this.notify('caps-icon');
+                this.notify('caps-level');
+            })
+            .catch(logError);
+    }
+}
+
+const brightnessService = new Brightness();
+
+export default brightnessService;