diff --git a/flake.nix b/flake.nix
index 5c07246..7ad5e47 100644
--- a/flake.nix
+++ b/flake.nix
@@ -38,8 +38,9 @@
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
+ home-manager.backupFileExtension = "hm-back";
home-manager.sharedModules = [ plasma-manager.homeModules.plasma-manager ];
- home-manager.users.duynguyen = import ./home/duynguyen/default.nix;
+ home-manager.users.duynguyen = import ./home/hosts/nixos.nix;
}
];
};
diff --git a/home/duynguyen/config/niri/config.kdl b/home/duynguyen/config/niri/config.kdl
deleted file mode 100644
index 4731ef0..0000000
--- a/home/duynguyen/config/niri/config.kdl
+++ /dev/null
@@ -1,277 +0,0 @@
-// This config is in the KDL format: https://kdl.dev
-// "/-" comments out the following node.
-// Check the wiki for a full description of the configuration:
-// https://niri-wm.github.io/niri/Configuration:-Introduction
-
-input {
- keyboard {
- xkb {
- // If this section is empty, niri will fetch xkb settings
- // from org.freedesktop.locale1. You can control these using
- // localectl set-x11-keymap.
- }
- numlock
- }
-
- touchpad {
- tap
- natural-scroll
- accel-profile "flat"
- scroll-factor 1.0
- }
-
- mouse {
- // natural-scroll
- // accel-speed 0.2
- // accel-profile "flat"
- }
-
- trackpoint {
- // natural-scroll
- // accel-speed 0.2
- }
-}
-
-/-output "eDP-1" {
- mode "1920x1080@120.030"
- scale 1.5
- transform "normal"
- position x=1280 y=0
-}
-
-layout {
- gaps 8
- center-focused-column "never"
-
- preset-column-widths {
- proportion 0.33333
- proportion 0.5
- proportion 0.66667
- }
-
- default-column-width { proportion 0.5; }
-
- focus-ring {
- width 1
- active-color "#7fc8ff"
- inactive-color "#505050"
- }
-
- border {
- off
- width 4
- active-color "#ffc87f"
- inactive-color "#505050"
- urgent-color "#9b0000"
- }
-
- shadow {
- softness 30
- spread 5
- offset x=0 y=5
- color "#0007"
- }
-
- struts {
- // left 64
- // right 64
- // top 64
- // bottom 64
- }
-}
-
-spawn-at-startup "noctalia"
-spawn-at-startup "xwayland-satellite"
-
-hotkey-overlay {
- skip-at-startup
-}
-
-screenshot-path null
-
-gestures {
- hot-corners {
- off
- }
-}
-
-prefer-no-csd
-
-animations {
- slowdown 0.5
-}
-
-window-rule {
- match app-id=r#"^org\.wezfurlong\.wezterm$"#
- default-column-width {}
-}
-
-// Rounded corners
-window-rule {
- geometry-corner-radius 12
- clip-to-geometry true
-}
-
-// Floating windows
-window-rule {
- match app-id=r#"^Tk$"#
- match app-id=r#"^gimp$"# title=r#"Preferences"#
- match app-id=r#"^mpv$"#
- match app-id=r#"^soffice$"# title=r#"^Text Import"#
- match app-id=r#"^thunar$"# title=r#"^Rename "#
- match app-id=r#"^xarchiver$"#
- match app-id=r#"firefox$"# title=r#"^(Picture-in-Picture|Library|About Mozilla Firefox|Firefox - Choose a profile)$"#
-
- open-floating true
-}
-
-binds {
- Mod+Shift+Slash { show-hotkey-overlay; }
-
- Mod+T hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
- Mod+Space hotkey-overlay-title="Noctalia: Launcher" { spawn "noctalia-ipc" "panel-toggle" "launcher"; }
- Mod+S hotkey-overlay-title="Noctalia: Control Center" { spawn "noctalia-ipc" "panel-toggle" "control-center"; }
- Super+Alt+L hotkey-overlay-title="Noctalia: Lock" { spawn "noctalia-ipc" "session" "lock"; }
-
- XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; }
- XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; }
- XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
- XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
-
- XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }
- XF86AudioPause allow-when-locked=true { spawn-sh "playerctl play-pause"; }
- XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; }
- XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; }
- XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; }
-
- XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; }
- XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; }
-
- Mod+O repeat=false { toggle-overview; }
- Mod+Shift+Q repeat=false { close-window; }
-
- Mod+Left { focus-column-left; }
- Mod+Down { focus-window-down; }
- Mod+Up { focus-window-up; }
- Mod+Right { focus-column-right; }
- Mod+H { focus-column-left; }
- Mod+J { focus-window-down; }
- Mod+K { focus-window-up; }
- Mod+L { focus-column-right; }
-
- Mod+Shift+Left { move-column-left; }
- Mod+Shift+Down { move-window-down; }
- Mod+Shift+Up { move-window-up; }
- Mod+Shift+Right { move-column-right; }
- Mod+Shift+H { move-column-left; }
- Mod+Shift+J { move-window-down; }
- Mod+Shift+K { move-window-up; }
- Mod+Shift+L { move-column-right; }
-
- Mod+Home { focus-column-first; }
- Mod+End { focus-column-last; }
- Mod+Ctrl+Home { move-column-to-first; }
- Mod+Ctrl+End { move-column-to-last; }
-
- Mod+Ctrl+Left { focus-monitor-left; }
- Mod+Ctrl+Down { focus-monitor-down; }
- Mod+Ctrl+Up { focus-monitor-up; }
- Mod+Ctrl+Right { focus-monitor-right; }
- Mod+Ctrl+H { focus-monitor-left; }
- Mod+Ctrl+J { focus-monitor-down; }
- Mod+Ctrl+K { focus-monitor-up; }
- Mod+Ctrl+L { focus-monitor-right; }
-
- Mod+Shift+Ctrl+Left { move-column-to-monitor-left; }
- Mod+Shift+Ctrl+Down { move-column-to-monitor-down; }
- Mod+Shift+Ctrl+Up { move-column-to-monitor-up; }
- Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
- Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
- Mod+Shift+Ctrl+J { move-column-to-monitor-down; }
- Mod+Shift+Ctrl+K { move-column-to-monitor-up; }
- Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
-
- Mod+Page_Down { focus-workspace-down; }
- Mod+Page_Up { focus-workspace-up; }
- Mod+U { focus-workspace-down; }
- Mod+I { focus-workspace-up; }
- Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
- Mod+Ctrl+Page_Up { move-column-to-workspace-up; }
- Mod+Ctrl+U { move-column-to-workspace-down; }
- Mod+Ctrl+I { move-column-to-workspace-up; }
-
- Mod+Shift+Page_Down { move-workspace-down; }
- Mod+Shift+Page_Up { move-workspace-up; }
- Mod+Shift+U { move-workspace-down; }
- Mod+Shift+I { move-workspace-up; }
-
- Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
- Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
- Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
- Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
-
- Mod+WheelScrollRight { focus-column-right; }
- Mod+WheelScrollLeft { focus-column-left; }
- Mod+Ctrl+WheelScrollRight { move-column-right; }
- Mod+Ctrl+WheelScrollLeft { move-column-left; }
-
- Mod+Shift+WheelScrollDown { focus-column-right; }
- Mod+Shift+WheelScrollUp { focus-column-left; }
- Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
- Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
-
- Mod+1 { focus-workspace 1; }
- Mod+2 { focus-workspace 2; }
- Mod+3 { focus-workspace 3; }
- Mod+4 { focus-workspace 4; }
- Mod+5 { focus-workspace 5; }
- Mod+6 { focus-workspace 6; }
- Mod+7 { focus-workspace 7; }
- Mod+8 { focus-workspace 8; }
- Mod+9 { focus-workspace 9; }
- Mod+Ctrl+1 { move-column-to-workspace 1; }
- Mod+Ctrl+2 { move-column-to-workspace 2; }
- Mod+Ctrl+3 { move-column-to-workspace 3; }
- Mod+Ctrl+4 { move-column-to-workspace 4; }
- Mod+Ctrl+5 { move-column-to-workspace 5; }
- Mod+Ctrl+6 { move-column-to-workspace 6; }
- Mod+Ctrl+7 { move-column-to-workspace 7; }
- Mod+Ctrl+8 { move-column-to-workspace 8; }
- Mod+Ctrl+9 { move-column-to-workspace 9; }
-
- Mod+BracketLeft { consume-or-expel-window-left; }
- Mod+BracketRight { consume-or-expel-window-right; }
-
- Mod+Comma { consume-window-into-column; }
- Mod+Period { expel-window-from-column; }
-
- Mod+R { switch-preset-column-width; }
- Mod+Shift+R { switch-preset-column-width-back; }
- Mod+Ctrl+Shift+R { switch-preset-window-height; }
- Mod+Ctrl+R { reset-window-height; }
-
- Mod+F { maximize-column; }
- Mod+Shift+F { fullscreen-window; }
- Mod+M { maximize-window-to-edges; }
- Mod+Ctrl+F { expand-column-to-available-width; }
- Mod+C { center-column; }
- Mod+Ctrl+C { center-visible-columns; }
-
- Mod+Minus { set-column-width "-10%"; }
- Mod+Equal { set-column-width "+10%"; }
- Mod+Shift+Minus { set-window-height "-10%"; }
- Mod+Shift+Equal { set-window-height "+10%"; }
-
- Mod+V { toggle-window-floating; }
- Mod+Shift+V { switch-focus-between-floating-and-tiling; }
- Mod+W { toggle-column-tabbed-display; }
-
- Print { screenshot; }
- Ctrl+Print { screenshot-screen; }
- Mod+Print { screenshot-window; }
-
- Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
- Mod+Shift+E { quit; }
- Ctrl+Alt+Delete { quit; }
- Mod+Shift+P { power-off-monitors; }
-}
diff --git a/home/duynguyen/config/waybar/config.json b/home/duynguyen/config/waybar/config.json
deleted file mode 100644
index 2fe7657..0000000
--- a/home/duynguyen/config/waybar/config.json
+++ /dev/null
@@ -1,154 +0,0 @@
-{
- "reload_style_on_change": true,
- "layer": "top",
- "position": "top",
- "spacing": 0,
- "height": 24,
- "modules-left": [
- "custom/menu",
- "niri/workspaces"
- ],
- "modules-center": [
- "clock"
- ],
- "modules-right": [
- "group/tray-expander",
- "pulseaudio",
- "bluetooth",
- "network",
- "cpu",
- "battery"
- ],
-
- "custom/menu": {
- "format": "",
- "on-click": "walker",
- "tooltip-format": "Open launcher"
- },
-
- "niri/workspaces": {
- "on-click": "activate",
- "on-click-right": "niri msg action toggle-overview",
- "format": "{icon}",
- "format-icons": {
- "default": "",
- "1": "1",
- "2": "2",
- "3": "3",
- "4": "4",
- "5": "5",
- "6": "6",
- "7": "7",
- "8": "8",
- "9": "9",
- "active": ""
- }
- },
-
- "clock": {
- "format": "{:%I:%M %p %Z :: %a %b %d %Y}",
- "format-alt": "{:%H:%M %Z :: %a %b %d %Y}",
- "tooltip": true,
- "tooltip-format": "{calendar}",
- "timezones": ["", "UTC"],
- "on-click-right": "xdg-open https://calendar.google.com",
- "actions": {
- "on-scroll-up": "tz_up",
- "on-scroll-down": "tz_down"
- },
- "calendar": {
- "mode": "year",
- "mode-mon-col": 3,
- "weeks-pos": "right",
- "on-scroll": 1,
- "format": {
- "months": "{}",
- "days": "{}",
- "weeks": "W{:%V}",
- "weekdays": "{}",
- "today": "{}"
- }
- }
- },
-
- "group/tray-expander": {
- "orientation": "horizontal",
- "drawer": {
- "transition-duration": 300,
- "children-class": "tray-group-item"
- },
- "modules": [
- "custom/expand-icon",
- "tray"
- ]
- },
-
- "custom/expand-icon": {
- "format": "",
- "tooltip": false
- },
-
- "tray": {
- "icon-size": 12,
- "spacing": 12
- },
-
- "pulseaudio": {
- "format": "{icon}",
- "on-click": "wiremix",
- "on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
- "tooltip-format": "Playback volume: {volume}%",
- "scroll-step": 5,
- "format-muted": "",
- "format-icons": {
- "default": ["", "", ""]
- }
- },
-
- "bluetooth": {
- "format": "",
- "format-disabled": "",
- "format-connected": "",
- "tooltip-format": "Devices connected: {num_connections}",
- "on-click": "blueman-manager"
- },
-
- "network": {
- "format-icons": ["", "", "", "", ""],
- "format": "{icon}",
- "format-wifi": "{icon}",
- "format-ethernet": "",
- "format-disconnected": "",
- "tooltip-format-wifi": "{essid} ({frequency} GHz)\n⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}\n\n{ipaddr}",
- "tooltip-format-ethernet": "⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}\n\n{ipaddr}",
- "tooltip-format-disconnected": "Disconnected",
- "interval": 10,
- "on-click-right": "xdg-open https://speedtest.net"
- },
-
- "cpu": {
- "interval": 5,
- "format": "",
- "on-click": "kitty -e btop",
- "tooltip-format": "CPU usage: {usage}%"
- },
-
- "battery": {
- "format": "{capacity}% {icon}",
- "format-discharging": "{icon}",
- "format-charging": "{icon}",
- "format-plugged": "",
- "format-icons": {
- "charging": ["", "", "", "", "", "", "", "", "", ""],
- "default": ["", "", "", "", "", "", "", "", "", ""]
- },
- "format-full": "",
- "tooltip-format-discharging": "{power:>1.0f}W↓ {capacity}%",
- "tooltip-format-charging": "{power:>1.0f}W↑ {capacity}%",
- "interval": 5,
- "states": {
- "warning": 20,
- "critical": 10
- }
- }
-}
diff --git a/home/duynguyen/config/waybar/style.css b/home/duynguyen/config/waybar/style.css
deleted file mode 100644
index 4d6093a..0000000
--- a/home/duynguyen/config/waybar/style.css
+++ /dev/null
@@ -1,95 +0,0 @@
-* {
- font-family: "JetBrainsMono Nerd Font", "Font Awesome 6 Free", "FreeSans", sans-serif;
- font-size: 13px;
- border: none;
- border-radius: 0;
- min-height: 0;
- margin: 0;
- padding: 0;
-}
-
-window#waybar {
- background-color: #1e1e2e;
- color: #cdd6f4;
-}
-
-.modules-left,
-.modules-center,
-.modules-right {
- margin: 4px 8px;
-}
-
-#workspaces button {
- padding: 0 8px;
- color: #6c7086;
- background: transparent;
-}
-
-#workspaces button.active {
- color: #cdd6f4;
- font-weight: bold;
-}
-
-#workspaces button:hover {
- color: #89b4fa;
- box-shadow: none;
- text-shadow: none;
- background: transparent;
-}
-
-#window {
- color: #a6adc8;
- padding: 0 8px;
-}
-
-#clock,
-#battery,
-#network,
-#pulseaudio,
-#bluetooth,
-#cpu,
-#tray,
-#custom-menu,
-#custom-expand-icon {
- padding: 0 10px;
- color: #cdd6f4;
-}
-
-#clock {
- font-weight: bold;
-}
-
-#custom-menu {
- color: #89b4fa;
- font-size: 16px;
- padding: 0 12px;
-}
-
-#custom-expand-icon {
- padding: 0 6px;
- color: #6c7086;
-}
-
-.tray-group-item {
- padding: 0 4px;
-}
-
-#battery.warning {
- color: #f9e2af;
-}
-
-#battery.critical {
- color: #f38ba8;
-}
-
-#network.disconnected {
- color: #f38ba8;
-}
-
-#bluetooth.disabled {
- color: #6c7086;
-}
-
-#pulseaudio.muted {
- color: #6c7086;
-}
diff --git a/home/duynguyen/default.nix b/home/duynguyen/default.nix
deleted file mode 100644
index 102f45b..0000000
--- a/home/duynguyen/default.nix
+++ /dev/null
@@ -1,248 +0,0 @@
-{ config, pkgs, lib, inputs, ... }:
-
-let
- wallpaperDir = "${config.home.homeDirectory}/.config/wallpapers";
- defaultWallpaper = "${wallpaperDir}/even-in-arcadia.png";
-
- # Thin wrapper so niri keybinds can call noctalia msg
- # without hard-coding the nix-store path.
- noctaliaIpc = pkgs.writeShellScriptBin "noctalia-ipc" ''
- set -eu
- exec noctalia msg "$@"
- '';
-in
-{
- imports = [
- inputs.noctalia.homeModules.default
- ];
-
- home.username = "duynguyen";
- home.homeDirectory = "/home/duynguyen";
- home.stateVersion = "26.05";
-
- # home-manager's fontconfig module references removed nodePackages;
- # NixOS manages fontconfig at the system level anyway
- fonts.fontconfig.enable = false;
-
- home.packages = with pkgs; [
- noctaliaIpc
-
- # Browsers
- zen-browser
- claude-desktop
-
- # Terminals
- ghostty
- kitty
- foot
-
- # Niri supporting tools
- xwayland-satellite # X11 app support in Niri
- xdg-utils # xdg-open, file associations
- inotify-tools # filesystem event tools
-
- # Polkit agent for Niri session (graphical auth dialogs)
- kdePackages.polkit-kde-agent-1
-
- # Editor
- vscodium
-
- # Daily apps
- mpv
- imv
- gimp
- obs-studio
- zathura
- thunar
- xfce.thunar-archive-plugin
- xfce.tumbler
- ffmpegthumbnailer
- xarchiver
- grim
- slurp
- swappy
- libreoffice
- telegram-desktop
- pavucontrol
- blueman
-
- # Clipboard
- cliphist
- wl-clipboard
-
- # CLI tools
- vim
- neovim
- tmux
- fastfetch
- btop
- ripgrep
- fd
- fzf
- eza
- bat
- dust
- jq
- yq
- shellcheck
- ffmpeg
- imagemagick
- unzip
- p7zip
- wiremix
-
- # System control
- brightnessctl
- playerctl
-
- # Dev tools
- gh
- ];
-
- # Required for Electron apps (VSCodium, Zen Browser, etc.) to use
- # Wayland natively and work correctly with fcitx5 input
- home.sessionVariables.NIXOS_OZONE_WL = "1";
-
- # Wallpapers folder — add images to home/duynguyen/wallpapers/ in the repo
- # and rebuild; noctalia reads from ~/.config/wallpapers
- xdg.configFile."wallpapers".source = ./wallpapers;
-
- # Polkit agent as a systemd user service so it starts with the Niri session
- systemd.user.services.polkit-kde-agent = {
- Unit = {
- Description = "KDE Polkit Authentication Agent";
- PartOf = [ "graphical-session.target" ];
- After = [ "graphical-session.target" ];
- };
- Service = {
- ExecStart = "${pkgs.kdePackages.polkit-kde-agent-1}/libexec/polkit-kde-authentication-agent-1";
- Restart = "on-failure";
- RestartSec = 1;
- };
- Install.WantedBy = [ "graphical-session.target" ];
- };
-
- # ── Noctalia ──────────────────────────────────────────────────────────────
- # Replaces: waybar, walker, swaylock, swaybg, swayidle, mako
- programs.noctalia = {
- enable = true;
- settings = {
- bar.default = {
- start = [ "launcher" "clipboard" "cpu" "network" "ram" ];
- center = [ "clock" ];
- end = [ "notifications" "volume" "brightness" "battery" "control-center" "session" ];
- thickness = 40;
- padding = 10;
- radius = 0;
- margin_edge = 0;
- margin_ends = 0;
- widget_spacing = 8;
- };
-
- idle = {
- behavior_order = [ "lock" "screen-off" ];
- behavior = {
- lock = {
- action = "lock";
- enabled = true;
- timeout = 600; # 10 min
- };
- screen-off = {
- action = "screen_off";
- enabled = true;
- timeout = 660;
- };
- };
- };
-
- lockscreen.wallpaper = defaultWallpaper;
-
- nightlight.enabled = true;
-
- osd.position = "top_right";
-
- shell = {
- font_family = "JetBrainsMono Nerd Font";
- polkit_agent = true;
- corner_radius_scale = 0.0;
- animation.speed = 1.5;
- panel = {
- clipboard_placement = "attached";
- launcher_placement = "attached";
- launcher_session_search = true;
- };
- shadow.alpha = 0.5;
- };
-
- theme.builtin = "Kanagawa";
-
- wallpaper = {
- enabled = true;
- directory = wallpaperDir;
- default.path = defaultWallpaper;
- };
- };
- };
-
- # ── Shell ─────────────────────────────────────────────────────────────────
- programs.zsh = {
- enable = true;
- autosuggestion.enable = true;
- syntaxHighlighting.enable = true;
- };
-
- programs.kitty = {
- enable = true;
- settings.wheel_scroll_multiplier = 10;
- };
-
- programs.zoxide = {
- enable = true;
- enableZshIntegration = true;
- };
-
- programs.starship.enable = true;
-
- programs.git = {
- enable = true;
- settings.user = {
- name = "duynguyen";
- email = "huonghaiduynhim@gmail.com";
- };
- };
-
- # ── KDE Plasma (for the Plasma session; dark theme + touchpad) ────────────
- programs.plasma = {
- enable = true;
- workspace.lookAndFeel = "org.kde.breezedark.desktop";
- input.touchpads = [
- {
- name = "SynPS/2 Synaptics TouchPad";
- vendorId = "2";
- productId = "7";
- naturalScroll = true;
- pointerSpeed = 0.4;
- scrollSpeed = 0.75;
- }
- ];
- };
-
- # ── Zen Browser scroll speed ──────────────────────────────────────────────
- home.activation.zenBrowserUserJs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
- for profile in "$HOME/.config/zen/"*.*/; do
- [[ -d "$profile" ]] || continue
- echo 'user_pref("mousewheel.default.delta_multiplier_y", 50);' > "$profile/user.js"
- done
- '';
-
- # ── Niri config ───────────────────────────────────────────────────────────
- xdg.configFile."niri/config.kdl".source =
- pkgs.runCommand "niri-config-checked"
- { nativeBuildInputs = [ pkgs.niri ]; }
- ''
- niri validate -c ${./config/niri/config.kdl}
- cp ${./config/niri/config.kdl} $out
- '';
-
- programs.home-manager.enable = true;
-}
diff --git a/home/hosts/nixos.nix b/home/hosts/nixos.nix
new file mode 100644
index 0000000..28213f5
--- /dev/null
+++ b/home/hosts/nixos.nix
@@ -0,0 +1,23 @@
+{ lib, ... }:
+{
+ home.username = "duynguyen";
+ home.homeDirectory = "/home/duynguyen";
+ home.stateVersion = "26.05";
+
+ imports = [
+ ../modules/niri
+ ../modules/kitty
+ ../modules/cli
+ ../modules/applications
+ ];
+
+ # Zen Browser scroll speed — written to all profiles so it survives profile ID changes
+ home.activation.zenBrowserUserJs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
+ for profile in "$HOME/.config/zen/"*.*/; do
+ [[ -d "$profile" ]] || continue
+ echo 'user_pref("mousewheel.default.delta_multiplier_y", 50);' > "$profile/user.js"
+ done
+ '';
+
+ programs.home-manager.enable = true;
+}
diff --git a/home/modules/applications/default.nix b/home/modules/applications/default.nix
new file mode 100644
index 0000000..b1c7263
--- /dev/null
+++ b/home/modules/applications/default.nix
@@ -0,0 +1,93 @@
+{ pkgs, ... }:
+{
+ # home-manager's fontconfig module references removed nodePackages;
+ # NixOS manages fontconfig at the system level anyway
+ fonts.fontconfig.enable = false;
+
+ home.sessionVariables.NIXOS_OZONE_WL = "1";
+
+ home.packages = with pkgs; [
+ # Browsers
+ zen-browser
+ claude-desktop
+
+ # Terminals
+ ghostty
+ kitty
+ foot
+
+ # Niri support
+ xdg-utils
+ inotify-tools
+
+ # Editor
+ vscodium
+
+ # Daily apps
+ mpv
+ imv
+ gimp
+ obs-studio
+ zathura
+ thunar
+ xfce.thunar-archive-plugin
+ xfce.tumbler
+ ffmpegthumbnailer
+ xarchiver
+ grim
+ slurp
+ swappy
+ libreoffice
+ telegram-desktop
+ pavucontrol
+ blueman
+
+ # Clipboard
+ cliphist
+ wl-clipboard
+
+ # CLI tools
+ vim
+ neovim
+ tmux
+ fastfetch
+ btop
+ ripgrep
+ fd
+ fzf
+ eza
+ bat
+ dust
+ jq
+ yq
+ shellcheck
+ ffmpeg
+ imagemagick
+ unzip
+ p7zip
+ wiremix
+
+ # System control
+ brightnessctl
+ playerctl
+
+ # Dev tools
+ gh
+ ];
+
+ # KDE Plasma session: dark theme + touchpad preferences
+ programs.plasma = {
+ enable = true;
+ workspace.lookAndFeel = "org.kde.breezedark.desktop";
+ input.touchpads = [
+ {
+ name = "SynPS/2 Synaptics TouchPad";
+ vendorId = "2";
+ productId = "7";
+ naturalScroll = true;
+ pointerSpeed = 0.4;
+ scrollSpeed = 0.75;
+ }
+ ];
+ };
+}
diff --git a/home/modules/cli/default.nix b/home/modules/cli/default.nix
new file mode 100644
index 0000000..61c573f
--- /dev/null
+++ b/home/modules/cli/default.nix
@@ -0,0 +1,23 @@
+{ ... }:
+{
+ programs.zsh = {
+ enable = true;
+ autosuggestion.enable = true;
+ syntaxHighlighting.enable = true;
+ };
+
+ programs.zoxide = {
+ enable = true;
+ enableZshIntegration = true;
+ };
+
+ programs.starship.enable = true;
+
+ programs.git = {
+ enable = true;
+ settings.user = {
+ name = "duynguyen";
+ email = "huonghaiduynhim@gmail.com";
+ };
+ };
+}
diff --git a/home/modules/kitty/default.nix b/home/modules/kitty/default.nix
new file mode 100644
index 0000000..e563220
--- /dev/null
+++ b/home/modules/kitty/default.nix
@@ -0,0 +1,7 @@
+{ ... }:
+{
+ programs.kitty = {
+ enable = true;
+ settings.wheel_scroll_multiplier = 10;
+ };
+}
diff --git a/home/modules/niri/default.nix b/home/modules/niri/default.nix
new file mode 100644
index 0000000..d1c5253
--- /dev/null
+++ b/home/modules/niri/default.nix
@@ -0,0 +1,98 @@
+{ pkgs, lib, ... }:
+let
+ # Start from niri's own default config so we inherit every new default
+ # automatically on updates. We patch only what we need to change.
+ base = builtins.readFile "${pkgs.niri.doc}/share/doc/niri/default-config.kdl";
+
+ # waybar → noctalia + add xwayland-satellite
+ r1 = builtins.replaceStrings
+ [ "spawn-at-startup \"waybar\"\n" ]
+ [ "spawn-at-startup \"noctalia\"\nspawn-at-startup \"xwayland-satellite\"\n" ]
+ base;
+
+ # terminal: alacritty → kitty
+ r2 = builtins.replaceStrings
+ [ " Mod+T hotkey-overlay-title=\"Open a Terminal: alacritty\" { spawn \"alacritty\"; }\n" ]
+ [ " Mod+T hotkey-overlay-title=\"Open a Terminal: kitty\" { spawn \"kitty\"; }\n" ]
+ r1;
+
+ # launcher: fuzzel → noctalia launcher + control-center
+ r3 = builtins.replaceStrings
+ [ " Mod+D hotkey-overlay-title=\"Run an Application: fuzzel\" { spawn \"fuzzel\"; }\n" ]
+ [ " Mod+Space hotkey-overlay-title=\"Noctalia: Launcher\" { spawn \"noctalia-ipc\" \"panel-toggle\" \"launcher\"; }\n Mod+S hotkey-overlay-title=\"Noctalia: Control Center\" { spawn \"noctalia-ipc\" \"panel-toggle\" \"control-center\"; }\n" ]
+ r2;
+
+ # lock: swaylock → noctalia
+ r4 = builtins.replaceStrings
+ [ " Super+Alt+L hotkey-overlay-title=\"Lock the Screen: swaylock\" { spawn \"swaylock\"; }\n" ]
+ [ " Super+Alt+L hotkey-overlay-title=\"Noctalia: Lock\" { spawn \"noctalia-ipc\" \"session\" \"lock\"; }\n" ]
+ r3;
+
+ # skip the hotkey overlay pop-up at startup
+ r5 = builtins.replaceStrings
+ [ " // skip-at-startup\n" ]
+ [ " skip-at-startup\n" ]
+ r4;
+
+ # tighter gaps
+ r6 = builtins.replaceStrings
+ [ " gaps 16\n" ]
+ [ " gaps 8\n" ]
+ r5;
+
+ # enable animations slowdown
+ r7 = builtins.replaceStrings
+ [ " // slowdown 3.0\n" ]
+ [ " slowdown 0.5\n" ]
+ r6;
+
+ # Our additions appended after the patched default config.
+ # A second `input { touchpad { } }` block overrides earlier touchpad settings.
+ customConfig = ''
+
+ // ── Touchpad ─────────────────────────────────────────────────────────────
+ input {
+ touchpad {
+ tap
+ natural-scroll
+ accel-profile "flat"
+ scroll-factor 1.0
+ }
+ }
+
+ // ── Prefer no client-side decorations ────────────────────────────────────
+ prefer-no-csd
+
+ // ── Gestures ─────────────────────────────────────────────────────────────
+ gestures {
+ hot-corners {
+ off
+ }
+ }
+
+ // ── Rounded corners ──────────────────────────────────────────────────────
+ window-rule {
+ geometry-corner-radius 12
+ clip-to-geometry true
+ }
+
+ // ── Floating windows ─────────────────────────────────────────────────────
+ window-rule {
+ match app-id=r#"^Tk$"#
+ match app-id=r#"^gimp$"# title=r#"Preferences"#
+ match app-id=r#"^mpv$"#
+ match app-id=r#"^soffice$"# title=r#"^Text Import"#
+ match app-id=r#"^thunar$"# title=r#"^Rename "#
+ match app-id=r#"^xarchiver$"#
+ match app-id=r#"firefox$"# title=r#"^Picture-in-Picture$"#
+
+ open-floating true
+ }
+ '';
+in
+{
+ imports = [ ./noctalia ./polkit ];
+
+ # .text writes a real file (not a nix-store symlink) so niri auto-reloads on rebuild
+ xdg.configFile."niri/config.kdl".text = r7 + customConfig;
+}
diff --git a/home/modules/niri/noctalia/default.nix b/home/modules/niri/noctalia/default.nix
new file mode 100644
index 0000000..f54d005
--- /dev/null
+++ b/home/modules/niri/noctalia/default.nix
@@ -0,0 +1,78 @@
+{ config, inputs, pkgs, ... }:
+let
+ wallpaperDir = "${config.home.homeDirectory}/.config/wallpapers";
+ defaultWallpaper = "${wallpaperDir}/even-in-arcadia.png";
+
+ noctaliaIpc = pkgs.writeShellScriptBin "noctalia-ipc" ''
+ set -eu
+ exec noctalia msg "$@"
+ '';
+in
+{
+ imports = [ inputs.noctalia.homeModules.default ];
+
+ home.packages = [ noctaliaIpc ];
+
+ # Wallpapers tracked in the repo; linked to ~/.config/wallpapers for noctalia
+ xdg.configFile."wallpapers".source = ./wallpapers;
+
+ programs.noctalia = {
+ enable = true;
+ settings = {
+ bar.default = {
+ start = [ "launcher" "clipboard" "cpu" "network" "ram" ];
+ center = [ "clock" ];
+ end = [ "notifications" "volume" "brightness" "battery" "control-center" "session" ];
+ thickness = 40;
+ padding = 10;
+ radius = 0;
+ margin_edge = 0;
+ margin_ends = 0;
+ widget_spacing = 8;
+ };
+
+ idle = {
+ behavior_order = [ "lock" "screen-off" ];
+ behavior = {
+ lock = {
+ action = "lock";
+ enabled = true;
+ timeout = 600;
+ };
+ screen-off = {
+ action = "screen_off";
+ enabled = true;
+ timeout = 660;
+ };
+ };
+ };
+
+ lockscreen.wallpaper = defaultWallpaper;
+
+ nightlight.enabled = true;
+
+ osd.position = "top_right";
+
+ shell = {
+ font_family = "JetBrainsMono Nerd Font";
+ polkit_agent = true;
+ corner_radius_scale = 0.0;
+ animation.speed = 1.5;
+ panel = {
+ clipboard_placement = "attached";
+ launcher_placement = "attached";
+ launcher_session_search = true;
+ };
+ shadow.alpha = 0.5;
+ };
+
+ theme.builtin = "Kanagawa";
+
+ wallpaper = {
+ enabled = true;
+ directory = wallpaperDir;
+ default.path = defaultWallpaper;
+ };
+ };
+ };
+}
diff --git a/home/duynguyen/wallpapers/.gitkeep b/home/modules/niri/noctalia/wallpapers/.gitkeep
similarity index 100%
rename from home/duynguyen/wallpapers/.gitkeep
rename to home/modules/niri/noctalia/wallpapers/.gitkeep
diff --git a/home/duynguyen/wallpapers/even-in-arcadia.png b/home/modules/niri/noctalia/wallpapers/even-in-arcadia.png
similarity index 100%
rename from home/duynguyen/wallpapers/even-in-arcadia.png
rename to home/modules/niri/noctalia/wallpapers/even-in-arcadia.png
diff --git a/home/modules/niri/polkit/default.nix b/home/modules/niri/polkit/default.nix
new file mode 100644
index 0000000..51a0a25
--- /dev/null
+++ b/home/modules/niri/polkit/default.nix
@@ -0,0 +1,18 @@
+{ pkgs, ... }:
+{
+ home.packages = [ pkgs.kdePackages.polkit-kde-agent-1 ];
+
+ systemd.user.services.polkit-kde-agent = {
+ Unit = {
+ Description = "KDE Polkit Authentication Agent";
+ PartOf = [ "graphical-session.target" ];
+ After = [ "graphical-session.target" ];
+ };
+ Service = {
+ ExecStart = "${pkgs.kdePackages.polkit-kde-agent-1}/libexec/polkit-kde-authentication-agent-1";
+ Restart = "on-failure";
+ RestartSec = 1;
+ };
+ Install.WantedBy = [ "graphical-session.target" ];
+ };
+}