diff --git a/modules/homes/ags/.gitignore b/modules/homes/ags/.gitignore
new file mode 100644
index 0000000..298eb4d
--- /dev/null
+++ b/modules/homes/ags/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+@girs/
diff --git a/modules/homes/ags/app.ts b/modules/homes/ags/app.ts
new file mode 100644
index 0000000..51d536f
--- /dev/null
+++ b/modules/homes/ags/app.ts
@@ -0,0 +1,10 @@
+import app from "ags/gtk4/app"
+import style from "./style.scss"
+import Bar from "./widget/Bar"
+
+app.start({
+ css: style,
+ main() {
+ app.get_monitors().map(Bar)
+ },
+})
diff --git a/modules/homes/ags/env.d.ts b/modules/homes/ags/env.d.ts
new file mode 100644
index 0000000..792ebfd
--- /dev/null
+++ b/modules/homes/ags/env.d.ts
@@ -0,0 +1,21 @@
+declare const SRC: string
+
+declare module "inline:*" {
+ const content: string
+ export default content
+}
+
+declare module "*.scss" {
+ const content: string
+ export default content
+}
+
+declare module "*.blp" {
+ const content: string
+ export default content
+}
+
+declare module "*.css" {
+ const content: string
+ export default content
+}
diff --git a/modules/homes/ags/flake.lock b/modules/homes/ags/flake.lock
new file mode 100644
index 0000000..d02c8ad
--- /dev/null
+++ b/modules/homes/ags/flake.lock
@@ -0,0 +1,70 @@
+{
+ "nodes": {
+ "ags": {
+ "inputs": {
+ "astal": "astal",
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1775689345,
+ "narHash": "sha256-tM3s7CX+tgxlYW0Sk3nzVThg2MHn08foIuMxABupxIs=",
+ "owner": "aylur",
+ "repo": "ags",
+ "rev": "bbee2f18939f1ec7ff720e717cf305e73635628f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "aylur",
+ "repo": "ags",
+ "type": "github"
+ }
+ },
+ "astal": {
+ "inputs": {
+ "nixpkgs": [
+ "ags",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1782062955,
+ "narHash": "sha256-FGZHls4eQJ8y3pvf5h3b83PfXlve3vD/Gj3g1qoAK6o=",
+ "owner": "aylur",
+ "repo": "astal",
+ "rev": "11842ae3045c1367fb3a62a2302dba0d9ccb4a33",
+ "type": "github"
+ },
+ "original": {
+ "owner": "aylur",
+ "repo": "astal",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1782467914,
+ "narHash": "sha256-pGvFkM8N0xEkIIXDe5YYfbEAvHrk4IxBrjB/x8OomhE=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "e73de5be04e0eff4190a1432b946d469c794e7b4",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "ags": "ags",
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/modules/homes/ags/flake.nix b/modules/homes/ags/flake.nix
new file mode 100644
index 0000000..eca087e
--- /dev/null
+++ b/modules/homes/ags/flake.nix
@@ -0,0 +1,74 @@
+{
+ description = "My Awesome Desktop Shell";
+
+ inputs = {
+ nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
+
+ ags = {
+ url = "github:aylur/ags";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ };
+
+ outputs = {
+ self,
+ nixpkgs,
+ ags,
+ }: let
+ system = "x86_64-linux";
+ pkgs = nixpkgs.legacyPackages.${system};
+ pname = "my-shell";
+ entry = "app.ts";
+
+ astalPackages = with ags.packages.${system}; [
+ io
+ astal4 # or astal3 for gtk3
+ battery
+ powerprofiles
+ # notifd tray wireplumber
+ ];
+
+ extraPackages =
+ astalPackages
+ ++ [
+ pkgs.libadwaita
+ pkgs.libsoup_3
+ ];
+ in {
+ packages.${system} = {
+ default = pkgs.stdenv.mkDerivation {
+ name = pname;
+ src = ./.;
+
+ nativeBuildInputs = with pkgs; [
+ wrapGAppsHook3
+ gobject-introspection
+ ags.packages.${system}.default
+ ];
+
+ buildInputs = extraPackages ++ [pkgs.gjs];
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out/bin
+ mkdir -p $out/share
+ cp -r * $out/share
+ ags bundle ${entry} $out/bin/${pname} -d "SRC='$out/share'"
+
+ runHook postInstall
+ '';
+ };
+ };
+
+ devShells.${system} = {
+ default = pkgs.mkShell {
+ buildInputs = [
+ (ags.packages.${system}.default.override {
+ inherit extraPackages;
+ })
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/homes/ags/package.json b/modules/homes/ags/package.json
new file mode 100644
index 0000000..cbf736c
--- /dev/null
+++ b/modules/homes/ags/package.json
@@ -0,0 +1,10 @@
+{
+ "dependencies": {
+ "ags": "*",
+ "gnim": "*"
+ },
+ "prettier": {
+ "semi": false,
+ "tabWidth": 2
+ }
+}
diff --git a/modules/homes/ags/style.scss b/modules/homes/ags/style.scss
new file mode 100644
index 0000000..2cc2a19
--- /dev/null
+++ b/modules/homes/ags/style.scss
@@ -0,0 +1,20 @@
+// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
+
+window.Bar {
+ background: transparent;
+ color: $fg-color;
+ font-weight: bold;
+
+ > centerbox {
+ background: $bg-color;
+ border-radius: 10px;
+ margin: 8px;
+ }
+
+ button {
+ border-radius: 8px;
+ margin: 2px;
+ }
+}
diff --git a/modules/homes/ags/tsconfig.json b/modules/homes/ags/tsconfig.json
new file mode 100644
index 0000000..2bb1f01
--- /dev/null
+++ b/modules/homes/ags/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "strict": true,
+ "module": "ES2022",
+ "target": "ES2020",
+ "lib": ["ES2023"],
+ "moduleResolution": "Bundler",
+ // "checkJs": true,
+ // "allowJs": true,
+ "jsx": "react-jsx",
+ "jsxImportSource": "ags/gtk4"
+ }
+}
diff --git a/modules/homes/ags/widget/Bar.tsx b/modules/homes/ags/widget/Bar.tsx
new file mode 100644
index 0000000..7bb2007
--- /dev/null
+++ b/modules/homes/ags/widget/Bar.tsx
@@ -0,0 +1,44 @@
+import app from "ags/gtk4/app"
+import { Astal, Gtk, Gdk } from "ags/gtk4"
+import { execAsync } from "ags/process"
+import { createPoll } from "ags/time"
+import BatteryWidget from "./Battery";
+
+export default function Bar(gdkmonitor: Gdk.Monitor) {
+ const time = createPoll("", 1000, "date '+%a %b %d %l:%M:%S %p'");
+ const { TOP, LEFT, RIGHT } = Astal.WindowAnchor;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/modules/homes/ags/widget/Battery.tsx b/modules/homes/ags/widget/Battery.tsx
new file mode 100644
index 0000000..6557f2b
--- /dev/null
+++ b/modules/homes/ags/widget/Battery.tsx
@@ -0,0 +1,36 @@
+import AstalBattery from "gi://AstalBattery";
+import AstalPowerProfiles from "gi://AstalPowerProfiles";
+import { createBinding } from "ags";
+import { Gtk } from "ags/gtk4";
+
+export default function BatteryWidget() {
+const battery = AstalBattery.get_default()
+ const powerprofiles = AstalPowerProfiles.get_default()
+
+ const percent = createBinding(
+ battery,
+ "percentage",
+ )((p) => `${Math.floor(p * 100)}%`)
+
+ const setProfile = (profile: string) => {
+ powerprofiles.set_active_profile(profile)
+ }
+
+ return (
+
+
+
+
+
+
+
+ {powerprofiles.get_profiles().map(({ profile }) => (
+
+ ))}
+
+
+
+ )
+}
\ No newline at end of file