diff --git a/.config/alacritty/alacritty.toml b/.config/alacritty/alacritty.toml
new file mode 100644
index 0000000..3cbcb72
--- /dev/null
+++ b/.config/alacritty/alacritty.toml
@@ -0,0 +1,6 @@
+[font]
+normal = { family = "JetBrainsMono", style = "Regular" }
+size = 12.0
+
+[window]
+opacity = 0.95
diff --git a/.config/hypr/README.md b/.config/hypr/README.md
new file mode 100644
index 0000000..f8d7291
--- /dev/null
+++ b/.config/hypr/README.md
@@ -0,0 +1,3 @@
+# Modular Hyprland Config
+
+This directory contains a modular Hyprland configuration. Edit files in `includes/` to customize your setup.
diff --git a/.config/hypr/hypridle.conf b/.config/hypr/hypridle.conf
new file mode 100644
index 0000000..8e7b85d
--- /dev/null
+++ b/.config/hypr/hypridle.conf
@@ -0,0 +1,14 @@
+general {
+ lock_cmd = pidof hyprlock || hyprlock
+ before_sleep_cmd = loginctl lock-session
+ after_sleep_cmd = hyprctl dispatch dpms on
+}
+
+listener {
+ timeout = 300
+ on-timeout = pidof hyprlock || hyprlock
+}
+listener {
+ timeout = 600
+ on-timeout = systemctl suspend
+}
diff --git a/.config/hypr/hyprland.conf b/.config/hypr/hyprland.conf
new file mode 100644
index 0000000..38f5917
--- /dev/null
+++ b/.config/hypr/hyprland.conf
@@ -0,0 +1,12 @@
+# Main Hyprland config (modular)
+
+# Source modular configs
+source = ~/.config/hypr/includes/programs.conf
+source = ~/.config/hypr/includes/monitors.conf
+source = ~/.config/hypr/includes/input.conf
+source = ~/.config/hypr/includes/env.conf
+source = ~/.config/hypr/includes/autostart.conf
+source = ~/.config/hypr/includes/binds.conf
+source = ~/.config/hypr/includes/appearance.conf
+
+# You can add more includes as needed
diff --git a/.config/hypr/hyprlock.conf b/.config/hypr/hyprlock.conf
new file mode 100644
index 0000000..560142e
--- /dev/null
+++ b/.config/hypr/hyprlock.conf
@@ -0,0 +1,68 @@
+general {
+ disable_loading_bar = true
+ grace = 300
+ hide_cursor = true
+ no_fade_in = false
+}
+
+background {
+ monitor =
+ path = screenshot
+ blur_passes = 3
+ blur_size = 8
+}
+
+input-field {
+ monitor =
+ size = 200, 50
+ position = 0, -80
+ dots_center = true
+ fade_on_empty = false
+ font_color = rgb(202, 211, 245)
+ inner_color = rgb(91, 96, 120)
+ outer_color = rgb(24, 25, 38)
+ outline_thickness = 5
+ placeholder_text = Input Password...
+ shadow_passes = 2
+}
+
+label {
+ monitor =
+ text = cmd[update:1000] echo "$TIME"
+ color = rgb(200, 200, 200)
+ font_size = 55
+ font_family = Noto Sans
+ position = -40, 40
+ halign = right
+ valign = bottom
+ shadow_passes = 5
+ shadow_size = 10
+}
+
+label {
+ monitor =
+ text = $USER
+ color = rgb(200, 200, 200)
+ font_size = 20
+ font_family = Noto Sans
+ position = -100, 160
+ halign = right
+ valign = bottom
+ shadow_passes = 5
+ shadow_size = 10
+}
+
+image {
+ monitor =
+ path = ~/.face
+ size = 280
+ rounding = -1
+ border_size = 4
+ border_color = rgb(221, 221, 221)
+ rotate = 0
+ reload_time = -1
+ reload_cmd =
+ position = 0, 200
+ halign = center
+ valign = center
+}
diff --git a/.config/hypr/includes/appearance.conf b/.config/hypr/includes/appearance.conf
new file mode 100644
index 0000000..b87b120
--- /dev/null
+++ b/.config/hypr/includes/appearance.conf
@@ -0,0 +1,118 @@
+#####################
+### LOOK AND FEEL ###
+#####################
+
+# Refer to https://wiki.hyprland.org/Configuring/Variables/
+
+# https://wiki.hyprland.org/Configuring/Variables/#general
+
+env = XCURSOR_SIZE,36
+env = HYPRCURSOR_SIZE,36
+env = HYPRCURSOR_THEME,rose-pine-hyprcursor
+
+env = QT_QPA_PLATFORMTHEME,qt6ct # for Qt apps
+exec = gsettings set org.gnome.desktop.interface gtk-theme "Breeze-Dark" # for GTK3 apps
+exec = gsettings set org.gnome.desktop.interface color-scheme "prefer-dark" # for GTK4 apps
+
+general {
+ gaps_in = 2
+ gaps_out = 5
+
+ border_size = 2
+
+ # https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
+ col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
+ col.inactive_border = rgba(595959aa)
+
+ # Set to true enable resizing windows by clicking and dragging on borders and gaps
+ resize_on_border = false
+
+ # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
+ allow_tearing = false
+
+ layout = dwindle
+}
+
+# https://wiki.hyprland.org/Configuring/Variables/#decoration
+decoration {
+ rounding = 5
+ rounding_power = 2
+
+ # Change transparency of focused and unfocused windows
+ active_opacity = 1.0
+ inactive_opacity = 1.0
+
+ shadow {
+ enabled = true
+ range = 4
+ render_power = 3
+ color = rgba(1a1a1aee)
+ }
+
+ # https://wiki.hyprland.org/Configuring/Variables/#blur
+ blur {
+ enabled = true
+ size = 3
+ passes = 1
+
+ vibrancy = 0.1696
+ }
+}
+
+# https://wiki.hyprland.org/Configuring/Variables/#animations
+animations {
+ enabled = yes, please :)
+
+ # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
+
+ bezier = easeOutQuint,0.23,1,0.32,1
+ bezier = easeInOutCubic,0.65,0.05,0.36,1
+ bezier = linear,0,0,1,1
+ bezier = almostLinear,0.5,0.5,0.75,1.0
+ bezier = quick,0.15,0,0.1,1
+
+ animation = global, 1, 10, default
+ animation = border, 1, 5.39, easeOutQuint
+ animation = windows, 1, 4.79, easeOutQuint
+ animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
+ animation = windowsOut, 1, 1.49, linear, popin 87%
+ animation = fadeIn, 1, 1.73, almostLinear
+ animation = fadeOut, 1, 1.46, almostLinear
+ animation = fade, 1, 3.03, quick
+ animation = layers, 1, 3.81, easeOutQuint
+ animation = layersIn, 1, 4, easeOutQuint, fade
+ animation = layersOut, 1, 1.5, linear, fade
+ animation = fadeLayersIn, 1, 1.79, almostLinear
+ animation = fadeLayersOut, 1, 1.39, almostLinear
+ animation = workspaces, 1, 1.94, almostLinear, fade
+ animation = workspacesIn, 1, 1.21, almostLinear, fade
+ animation = workspacesOut, 1, 1.94, almostLinear, fade
+}
+
+# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
+# "Smart gaps" / "No gaps when only"
+# uncomment all if you wish to use that.
+workspace = w[tv1], gapsout:0, gapsin:0
+workspace = f[1], gapsout:0, gapsin:0
+windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
+windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
+windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
+windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
+
+# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
+dwindle {
+ pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
+ preserve_split = true # You probably want this
+}
+
+# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
+master {
+ new_status = master
+}
+
+# https://wiki.hyprland.org/Configuring/Variables/#misc
+misc {
+ force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
+ disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
+}
+
diff --git a/.config/hypr/includes/autostart.conf b/.config/hypr/includes/autostart.conf
new file mode 100644
index 0000000..a5364d3
--- /dev/null
+++ b/.config/hypr/includes/autostart.conf
@@ -0,0 +1,12 @@
+# Autostart applications
+exec-once = waybar &
+exec-once = mako &
+exec-once = wl-clipboard-history -t &
+exec-once = wlogout &
+exec-once = rofi-wayland &
+# exec-once = hyprpaper &
+
+exec-once = hypridle &
+
+# Start Brave browser on Hyprland startup
+exec-once = brave &
diff --git a/.config/hypr/includes/binds.conf b/.config/hypr/includes/binds.conf
new file mode 100644
index 0000000..da29976
--- /dev/null
+++ b/.config/hypr/includes/binds.conf
@@ -0,0 +1,84 @@
+###################
+### KEYBINDINGS ###
+###################
+
+# See https://wiki.hyprland.org/Configuring/Keywords/
+$mainMod = SUPER # Sets "Windows" key as main modifier
+
+# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
+bind = $mainMod, Q, exec, $terminal
+bind = $mainMod, C, killactive,
+bind = $mainMod, M, exit,
+bind = $mainMod, E, exec, $fileManager
+bind = $mainMod CTRL, B, exec, google-chrome-stable
+bind = $mainMod, B, exec, firefox
+bind = $mainMod SHIFT, B, exec, brave
+bind = $mainMod, V, togglefloating,
+bind = $mainMod, R, exec, $menu
+bind = $mainMod, P, pseudo, # dwindle
+bind = $mainMod, J, togglesplit, # dwindle
+bind = $mainMod SHIFT, P, exec, ~/.config/hypr/reway.sh
+bind = $mainMod, L, exec, hyprlock
+
+# Move focus with mainMod + arrow keys
+bind = $mainMod, left, movefocus, l
+bind = $mainMod, right, movefocus, r
+bind = $mainMod, up, movefocus, u
+bind = $mainMod, down, movefocus, d
+
+bind = $mainMod SHIFT, left, swapwindow, l
+bind = $mainMod SHIFT, right, swapwindow, r
+bind = $mainMod SHIFT, up, swapwindow, u
+bind = $mainMod SHIFT, down, swapwindow, d
+
+# Switch workspaces with mainMod + [0-9]
+bind = $mainMod, 1, workspace, 1
+bind = $mainMod, 2, workspace, 2
+bind = $mainMod, 3, workspace, 3
+bind = $mainMod, 4, workspace, 4
+bind = $mainMod, 5, workspace, 5
+bind = $mainMod, 6, workspace, 6
+bind = $mainMod, 7, workspace, 7
+bind = $mainMod, 8, workspace, 8
+bind = $mainMod, 9, workspace, 9
+bind = $mainMod, 0, workspace, 10
+
+# Move active window to a workspace with mainMod + SHIFT + [0-9]
+bind = $mainMod SHIFT, 1, movetoworkspace, 1
+bind = $mainMod SHIFT, 2, movetoworkspace, 2
+bind = $mainMod SHIFT, 3, movetoworkspace, 3
+bind = $mainMod SHIFT, 4, movetoworkspace, 4
+bind = $mainMod SHIFT, 5, movetoworkspace, 5
+bind = $mainMod SHIFT, 6, movetoworkspace, 6
+bind = $mainMod SHIFT, 7, movetoworkspace, 7
+bind = $mainMod SHIFT, 8, movetoworkspace, 8
+bind = $mainMod SHIFT, 9, movetoworkspace, 9
+bind = $mainMod SHIFT, 0, movetoworkspace, 10
+
+# Example special workspace (scratchpad)
+bind = $mainMod, S, togglespecialworkspace, magic
+bind = $mainMod SHIFT, S, movetoworkspace, special:magic
+
+# Scroll through existing workspaces with mainMod + scroll
+bind = $mainMod, mouse_down, workspace, e+1
+bind = $mainMod, mouse_up, workspace, e-1
+
+# Move/resize windows with mainMod + LMB/RMB and dragging
+bindm = $mainMod, mouse:272, movewindow
+bindm = $mainMod, mouse:273, resizewindow
+
+# Laptop multimedia keys for volume and LCD brightness
+bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+
+bindel = ,XF86AudioRaiseVolume, exec, ~/.local/bin/wp-vol
+bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-
+bindel = ,XF86AudioLowerVolume, exec, ~/.local/bin/wp-vol
+bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
+bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
+bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
+bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
+
+# Requires playerctl
+bindl = , XF86AudioNext, exec, playerctl next
+bindl = , XF86AudioPause, exec, playerctl play-pause
+bindl = , XF86AudioPlay, exec, playerctl play-pause
+bindl = , XF86AudioPrev, exec, playerctl previous
diff --git a/.config/hypr/includes/env.conf b/.config/hypr/includes/env.conf
new file mode 100644
index 0000000..e6308b8
--- /dev/null
+++ b/.config/hypr/includes/env.conf
@@ -0,0 +1,3 @@
+# Environment variables
+env = XCURSOR_SIZE,24
+env = QT_QPA_PLATFORM,wayland
diff --git a/.config/hypr/includes/hypridle.conf b/.config/hypr/includes/hypridle.conf
new file mode 100644
index 0000000..e69de29
diff --git a/.config/hypr/includes/input-desktop.conf b/.config/hypr/includes/input-desktop.conf
new file mode 100644
index 0000000..1969870
--- /dev/null
+++ b/.config/hypr/includes/input-desktop.conf
@@ -0,0 +1,21 @@
+# Input configuration (desktop)
+input {
+ kb_layout = de
+ kb_variant = nodeadkeys
+ kb_model =
+ kb_options = caps:escape
+ kb_rules =
+ numlock_by_default = true
+
+ follow_mouse = 1
+
+ sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
+}
+
+# Gestures configuration
+gestures {
+ workspace_swipe = true
+ workspace_swipe_fingers = 4
+ workspace_swipe_distance = 300
+ workspace_swipe_invert = false
+}
diff --git a/.config/hypr/includes/input-laptop.conf b/.config/hypr/includes/input-laptop.conf
new file mode 100644
index 0000000..10fb0cc
--- /dev/null
+++ b/.config/hypr/includes/input-laptop.conf
@@ -0,0 +1,28 @@
+# Input configuration (laptop)
+input {
+ kb_layout = de
+ kb_variant = nodeadkeys
+ kb_model =
+ kb_options = caps:escape
+ kb_rules =
+ numlock_by_default = true
+
+ follow_mouse = 1
+
+ sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
+
+ touchpad {
+ natural_scroll = yes
+ tap-to-click = yes
+ disable_while_typing = yes
+ clickfinger_behavior = yes
+ }
+}
+
+# Gestures configuration
+gestures {
+ workspace_swipe = true
+ workspace_swipe_fingers = 4
+ workspace_swipe_distance = 300
+ workspace_swipe_invert = false
+}
diff --git a/.config/hypr/includes/input.conf b/.config/hypr/includes/input.conf
new file mode 100644
index 0000000..5ebd872
--- /dev/null
+++ b/.config/hypr/includes/input.conf
@@ -0,0 +1,28 @@
+# Input configuration
+input {
+ kb_layout = de
+ kb_variant = nodeadkeys
+ kb_model =
+ kb_options = caps:escape
+ kb_rules =
+ numlock_by_default = true
+
+ follow_mouse = 1
+
+ sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
+
+ touchpad {
+ natural_scroll = yes
+ tap-to-click = yes
+ disable_while_typing = yes
+ clickfinger_behavior = yes
+ }
+}
+
+# Gestures configuration
+gestures {
+ workspace_swipe = true
+ workspace_swipe_fingers = 4
+ workspace_swipe_distance = 300
+ workspace_swipe_invert = false
+}
diff --git a/.config/hypr/includes/monitors-desktop.conf b/.config/hypr/includes/monitors-desktop.conf
new file mode 100644
index 0000000..c9c48ba
--- /dev/null
+++ b/.config/hypr/includes/monitors-desktop.conf
@@ -0,0 +1,13 @@
+# Monitor configuration (desktop)
+monitor=DP-1,preferred,auto,1
+
+# Workspace assignments
+workspace=1,monitor:DP-1
+workspace=2,monitor:DP-1
+workspace=3,monitor:DP-1
+workspace=4,monitor:DP-1
+workspace=5,monitor:DP-1
+workspace=6,monitor:DP-1
+workspace=7,monitor:DP-1
+workspace=8,monitor:DP-1
+workspace=9,monitor:DP-1
diff --git a/.config/hypr/includes/monitors-laptop.conf b/.config/hypr/includes/monitors-laptop.conf
new file mode 100644
index 0000000..1ad81c7
--- /dev/null
+++ b/.config/hypr/includes/monitors-laptop.conf
@@ -0,0 +1,15 @@
+# Monitor configuration (laptop)
+monitor=eDP-1,preferred,auto,1
+monitor=DP-1,preferred,auto,1
+
+# Workspace assignments
+workspace=10,monitor:eDP-1
+workspace=1,monitor:DP-1
+workspace=2,monitor:DP-1
+workspace=3,monitor:DP-1
+workspace=4,monitor:DP-1
+workspace=5,monitor:DP-1
+workspace=6,monitor:DP-1
+workspace=7,monitor:DP-1
+workspace=8,monitor:DP-1
+workspace=9,monitor:DP-1
diff --git a/.config/hypr/includes/monitors.conf b/.config/hypr/includes/monitors.conf
new file mode 100644
index 0000000..1268d49
--- /dev/null
+++ b/.config/hypr/includes/monitors.conf
@@ -0,0 +1,16 @@
+# Monitor configuration
+# Assign workspace 1 to laptop (eDP-1), others to external (DP-1)
+monitor=eDP-1,preferred,auto,1
+monitor=DP-1,preferred,auto,1
+
+# Workspace assignments
+workspace=10,monitor:eDP-1
+workspace=1,monitor:DP-1
+workspace=2,monitor:DP-1
+workspace=3,monitor:DP-1
+workspace=4,monitor:DP-1
+workspace=5,monitor:DP-1
+workspace=6,monitor:DP-1
+workspace=7,monitor:DP-1
+workspace=8,monitor:DP-1
+workspace=9,monitor:DP-1
diff --git a/.config/hypr/includes/programs.conf b/.config/hypr/includes/programs.conf
new file mode 100644
index 0000000..a98853f
--- /dev/null
+++ b/.config/hypr/includes/programs.conf
@@ -0,0 +1,7 @@
+# Set programs that you use
+$terminal = alacritty
+$fileManager = dolphin
+$menu = rofi -show combi
+
+# Always move Brave browser to workspace 10
+windowrulev2 = workspace 10, class:^(Brave-browser)$
diff --git a/.config/mako/config b/.config/mako/config
new file mode 100644
index 0000000..ca0c9cd
--- /dev/null
+++ b/.config/mako/config
@@ -0,0 +1,19 @@
+font=JetBrainsMono 12
+background-color=#1e1e2e
+text-color=#cdd6f4
+border-color=#89b4fa
+border-size=2
+
+
+# Default: notifications at the top right
+anchor=top-right
+margin=20,20,0,0
+
+# Default notification timeout (ms)
+default-timeout=3000
+
+# Shorter timeout and bottom center for volume notifications
+[app-name=Volume]
+anchor=bottom-center
+margin=0,0,40,0
+default-timeout=1200
diff --git a/.config/rofi/config.rasi b/.config/rofi/config.rasi
new file mode 100644
index 0000000..a00c30b
--- /dev/null
+++ b/.config/rofi/config.rasi
@@ -0,0 +1,7 @@
+configuration {
+ font: "JetBrainsMono 12";
+ location: 0;
+ width: 30;
+ lines: 10;
+ columns: 1;
+}
diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf
new file mode 100644
index 0000000..df52a93
--- /dev/null
+++ b/.config/tmux/tmux.conf
@@ -0,0 +1,61 @@
+# Set prefix to Ctrl-a
+set -g prefix C-a
+unbind C-b
+bind C-a send-prefix
+
+# Enable mouse support
+set -g mouse on
+
+# Set 256 color mode
+set -g default-terminal "tmux-256color"
+set-option -ga terminal-overrides ",*:Tc"
+
+# Vi mode for copy mode
+setw -g mode-keys vi
+
+# Split panes
+bind | split-window -h
+bind - split-window -v
+
+# Reload config
+bind r source-file ~/.config/tmux/tmux.conf \; display-message "Config reloaded!"
+
+# --- Modern and simple status bar ---
+set -g status-bg colour236
+set -g status-fg colour250
+set -g status-style "bg=colour236,fg=colour250"
+set -g status-left-length 40
+set -g status-right-length 100
+set -g status-left '#[fg=colour33,bg=colour236,bold] #S #[fg=colour250,bg=colour236,nobold]|'
+set -g status-right '#[fg=colour250,bg=colour236,nobold]| #[fg=colour33,bg=colour236]#(date +"%a %d %b %Y") %H:%M #[fg=colour250,bg=colour236,nobold]| #[fg=colour33]#(whoami)@#H'
+
+# Clean window titles
+setw -g window-status-format ' #[fg=colour250,bg=colour236]#I:#W#{?window_flags,#[fg=colour208]#{window_flags},} '
+setw -g window-status-current-format ' #[fg=colour234,bg=colour33]#I:#W#{?window_flags,#[fg=colour208]#{window_flags},} '
+setw -g window-status-separator ''
+setw -g window-status-style "bg=colour236,fg=colour250"
+setw -g window-status-current-style "bg=colour33,fg=colour234"
+
+# Pane border
+set -g pane-border-style fg=colour238
+set -g pane-active-border-style fg=colour39
+
+# Message styling
+set -g message-style bg=colour234,fg=colour39
+set -g message-command-style bg=colour234,fg=colour208
+
+# Command prompt styling
+
+# Bell
+set -g visual-bell on
+set -g bell-action any
+
+# Allow faster command sequences
+set -s escape-time 0
+
+# Clipboard integration (requires xclip or wl-clipboard)
+bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -in"
+
+# Start window numbering at 1
+set -g base-index 1
+setw -g pane-base-index 1
diff --git a/.config/waybar/config b/.config/waybar/config
new file mode 100644
index 0000000..855a66d
--- /dev/null
+++ b/.config/waybar/config
@@ -0,0 +1,82 @@
+{
+ "layer": "top",
+ "position": "top",
+ "modules-left": ["hyprland/workspaces"],
+ "modules-center": ["clock"],
+ "modules-right": ["idle_inhibitor", "backlight", "cpu", "memory", "disk", "temperature", "pulseaudio", "network", "battery", "tray"],
+ "hyprland/workspaces": {
+ "format": "{icon}",
+ "on-click": "activate",
+ "on-scroll-up": "hyprctl dispatch workspace e-1",
+ "on-scroll-down": "hyprctl dispatch workspace e+1",
+ "all-outputs": true,
+ "persistent-workspaces": {
+ "*": [1,2,3,4,5,6,7,8,9]
+ }
+ },
+ "clock": {
+ "format": "{:%a %d.%m %H:%M}",
+ "tooltip-format": "{:%Y %B}\n{calendar}",
+ "format-alt": "{:%Y-%m-%d}"
+ },
+ "cpu": {
+ "format": " {usage}%"
+ },
+ "memory": {
+ "format": " {used}G/{total}G"
+ },
+ "temperature": {
+ "critical-threshold": 80,
+ "format": " {temperatureC}°C"
+ },
+ "backlight": {
+ "device": "intel_backlight",
+ "format": " {percent}%"
+ },
+ "disk": {
+ "format": " {free} free",
+ "path": "/"
+ },
+ "idle_inhibitor": {
+ "format": " {status}",
+ "format-alt": " {status}"
+ },
+ "network": {
+ "format-wifi": " {essid} ({signalStrength}%)",
+ "format-ethernet": " {ipaddr}/{cidr}",
+ "format-linked": " {ifname} (No IP)",
+ "format-disconnected": " Disconnected",
+ "format-alt": "{ifname}: {ipaddr}/{cidr}",
+ "tooltip-format": "{ifname} via {gwaddr}",
+ "tooltip-format-wifi": " {essid} ({signalStrength}%)\n{ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
+ "tooltip-format-ethernet": " {ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
+ "on-click": "nm-connection-editor"
+ },
+ "pulseaudio": {
+ "format": "{icon} {volume}%",
+ "format-muted": " Muted",
+ "format-icons": {
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
+ },
+ "on-click": "pavucontrol"
+ },
+ "battery": {
+ "states": {
+ "warning": 30,
+ "critical": 15
+ },
+ "format": "{icon} {capacity}%",
+ "format-charging": " {capacity}% ({time})",
+ "format-plugged": " {capacity}%",
+ "format-alt": "{icon} {capacity}% • {power:.1f}W • {time}",
+ "format-time": "{H}h {M}m",
+ "tooltip-format": "{capacity}% • {power:.1f}W\n{timeTo}",
+ "format-icons": ["", "", "", "", "", "", "", "", "", "", ""]
+ }
+}
diff --git a/.config/waybar/config-desktop b/.config/waybar/config-desktop
new file mode 100644
index 0000000..1f7fd2d
--- /dev/null
+++ b/.config/waybar/config-desktop
@@ -0,0 +1,63 @@
+{
+ "layer": "top",
+ "position": "top",
+ "modules-left": ["hyprland/workspaces"],
+ "modules-center": ["clock"],
+ "modules-right": ["idle_inhibitor", "cpu", "memory", "disk", "temperature", "pulseaudio", "network", "tray"],
+ "hyprland/workspaces": {
+ "format": "{icon}",
+ "on-click": "activate",
+ "on-scroll-up": "hyprctl dispatch workspace e-1",
+ "on-scroll-down": "hyprctl dispatch workspace e+1",
+ "all-outputs": true,
+ "persistent-workspaces": {
+ "*": [1,2,3,4,5,6,7,8,9]
+ }
+ },
+ "clock": {
+ "format": "{:%a %d.%m %H:%M}",
+ "tooltip-format": "{:%Y %B}\n{calendar}",
+ "format-alt": "{:%Y-%m-%d}"
+ },
+ "cpu": {
+ "format": " {usage}%"
+ },
+ "memory": {
+ "format": " {used}G/{total}G"
+ },
+ "temperature": {
+ "critical-threshold": 80,
+ "format": " {temperatureC}°C"
+ },
+ "disk": {
+ "format": " {free} free",
+ "path": "/"
+ },
+ "idle_inhibitor": {
+ "format": " {status}",
+ "format-alt": " {status}"
+ },
+ "network": {
+ "format-ethernet": " {ipaddr}/{cidr}",
+ "format-linked": " {ifname} (No IP)",
+ "format-disconnected": " Disconnected",
+ "format-alt": "{ifname}: {ipaddr}/{cidr}",
+ "tooltip-format": "{ifname} via {gwaddr}",
+ "tooltip-format-ethernet": " {ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
+ "on-click": "nm-connection-editor"
+ },
+ "pulseaudio": {
+ "format": "{icon} {volume}%",
+ "format-muted": " Muted",
+ "format-icons": {
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
+ },
+ "on-click": "pavucontrol"
+ }
+}
diff --git a/.config/waybar/config-laptop b/.config/waybar/config-laptop
new file mode 100644
index 0000000..855a66d
--- /dev/null
+++ b/.config/waybar/config-laptop
@@ -0,0 +1,82 @@
+{
+ "layer": "top",
+ "position": "top",
+ "modules-left": ["hyprland/workspaces"],
+ "modules-center": ["clock"],
+ "modules-right": ["idle_inhibitor", "backlight", "cpu", "memory", "disk", "temperature", "pulseaudio", "network", "battery", "tray"],
+ "hyprland/workspaces": {
+ "format": "{icon}",
+ "on-click": "activate",
+ "on-scroll-up": "hyprctl dispatch workspace e-1",
+ "on-scroll-down": "hyprctl dispatch workspace e+1",
+ "all-outputs": true,
+ "persistent-workspaces": {
+ "*": [1,2,3,4,5,6,7,8,9]
+ }
+ },
+ "clock": {
+ "format": "{:%a %d.%m %H:%M}",
+ "tooltip-format": "{:%Y %B}\n{calendar}",
+ "format-alt": "{:%Y-%m-%d}"
+ },
+ "cpu": {
+ "format": " {usage}%"
+ },
+ "memory": {
+ "format": " {used}G/{total}G"
+ },
+ "temperature": {
+ "critical-threshold": 80,
+ "format": " {temperatureC}°C"
+ },
+ "backlight": {
+ "device": "intel_backlight",
+ "format": " {percent}%"
+ },
+ "disk": {
+ "format": " {free} free",
+ "path": "/"
+ },
+ "idle_inhibitor": {
+ "format": " {status}",
+ "format-alt": " {status}"
+ },
+ "network": {
+ "format-wifi": " {essid} ({signalStrength}%)",
+ "format-ethernet": " {ipaddr}/{cidr}",
+ "format-linked": " {ifname} (No IP)",
+ "format-disconnected": " Disconnected",
+ "format-alt": "{ifname}: {ipaddr}/{cidr}",
+ "tooltip-format": "{ifname} via {gwaddr}",
+ "tooltip-format-wifi": " {essid} ({signalStrength}%)\n{ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
+ "tooltip-format-ethernet": " {ifname}: {ipaddr}/{cidr}\nGateway: {gwaddr}",
+ "on-click": "nm-connection-editor"
+ },
+ "pulseaudio": {
+ "format": "{icon} {volume}%",
+ "format-muted": " Muted",
+ "format-icons": {
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
+ },
+ "on-click": "pavucontrol"
+ },
+ "battery": {
+ "states": {
+ "warning": 30,
+ "critical": 15
+ },
+ "format": "{icon} {capacity}%",
+ "format-charging": " {capacity}% ({time})",
+ "format-plugged": " {capacity}%",
+ "format-alt": "{icon} {capacity}% • {power:.1f}W • {time}",
+ "format-time": "{H}h {M}m",
+ "tooltip-format": "{capacity}% • {power:.1f}W\n{timeTo}",
+ "format-icons": ["", "", "", "", "", "", "", "", "", "", ""]
+ }
+}
diff --git a/.config/waybar/style.css b/.config/waybar/style.css
new file mode 100644
index 0000000..787cbfd
--- /dev/null
+++ b/.config/waybar/style.css
@@ -0,0 +1,48 @@
+* {
+ font-family: JetBrainsMono, monospace;
+ font-size: 13px;
+ border: none;
+ box-shadow: none;
+ min-height: 0;
+}
+
+window#waybar {
+ background: rgba(30, 30, 46, 0.95);
+ border-radius: 10px;
+ color: #cdd6f4;
+ border: 1px solid #181825;
+ margin: 6px 6px 0 6px;
+}
+
+#workspaces button {
+ background: transparent;
+ color: #a6adc8;
+ border-radius: 6px;
+ margin: 0 2px;
+ padding: 0 8px;
+ transition: background 0.2s, color 0.2s;
+}
+#workspaces button.active {
+ background: #89b4fa;
+ color: #1e1e2e;
+}
+#workspaces button.urgent {
+ background: #f38ba8;
+ color: #1e1e2e;
+}
+
+#clock, #cpu, #memory, #temperature, #pulseaudio, #network, #battery, #tray, #backlight, #disk, #idle_inhibitor {
+ padding: 0 10px;
+ margin: 0 2px;
+ border-radius: 6px;
+ background: rgba(49, 50, 68, 0.7);
+}
+#battery.charging {
+ color: #a6e3a1;
+}
+#battery.critical {
+ color: #f38ba8;
+}
+#pulseaudio.muted {
+ color: #f9e2af;
+}
diff --git a/.config/wlogout/layout b/.config/wlogout/layout
new file mode 100644
index 0000000..32b2a43
--- /dev/null
+++ b/.config/wlogout/layout
@@ -0,0 +1,4 @@
+{
+ "label": "Logout",
+ "command": "loginctl terminate-user $USER"
+}
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..0877898
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,46 @@
+
+# Copilot Instructions for This Dotfiles Project
+
+## Project Overview
+- This is a modular dotfiles and desktop setup for Arch Linux, focused on Wayland/Hyprland workflows.
+- All package management is done with `paru` (AUR helper). Do not use `pacman` or other helpers.
+- Dotfiles and app configs are version-controlled in the repo root and `.config/` directory, then symlinked to `$HOME` and `$HOME/.config`.
+- The setup is fully modular: each major component (packages, symlinks, shell, Neovim, Hyprland, sound, etc.) is handled by its own script in `modules/`.
+
+## Architecture & Workflow
+- The main entrypoint is `setup.sh`, which finds and runs all numbered scripts in `modules/` in sorted order.
+- Each module script is responsible for a single concern (e.g., `01-packages.sh` for package install, `05-hyprland.sh` for Hyprland/Wayland packages, etc.).
+- The symlinking logic (`02-symlinks.sh`) links all dotfiles (including `.config/`) from the repo to the home directory, so configs are always up to date and versioned.
+- App configs (Hyprland, Waybar, etc.) are stored in `.config/` and should be modular and extensible (e.g., Hyprland uses `includes/` for config fragments).
+
+## Key Conventions
+- Always add new packages to the appropriate module script (e.g., Hyprland-related to `05-hyprland.sh`, sound to `06-sound.sh`).
+- To add new dotfiles, place them in the repo root (for files like `.zshrc`) or in `.config/` for app configs.
+- To add new setup logic, create a new numbered module in `modules/` (e.g., `07-myfeature.sh`).
+- All scripts must be idempotent and safe to re-run.
+- Use only `paru` for package installation.
+
+## Examples
+- To add a new app config (e.g., for `kitty`):
+ 1. Place config files in `.config/kitty/` in the repo.
+ 2. The symlink module will link them to `$HOME/.config/kitty` on setup.
+- To add a new package:
+ 1. Edit the appropriate `modules/XX-*.sh` script and add the package to the array.
+ 2. Re-run `setup.sh`.
+- To add a new setup step:
+ 1. Create `modules/07-myfeature.sh` and make it executable.
+ 2. It will be picked up automatically by `setup.sh`.
+
+## Integration Points
+- Hyprland, Waybar, Rofi, Mako, Alacritty, wlogout, and sound are all integrated and configured via `.config/`.
+- Neovim is set up with AstroNvim by default.
+- Sound is managed with PipeWire, WirePlumber, and related tools.
+
+## Notable Patterns
+- All configuration is declarative and modular. Avoid hardcoding paths; use `$HOME` and relative repo paths.
+- Avoid duplicating logic between modules; each should have a single responsibility.
+
+## See Also
+- `README.md` for user-facing setup and customization instructions.
+- `modules/` for all setup logic.
+- `.config/` for all app configs.
diff --git a/.local/bin/wp-vol b/.local/bin/wp-vol
new file mode 100644
index 0000000..38b531c
--- /dev/null
+++ b/.local/bin/wp-vol
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Show current volume in a Mako notification using wpctl
+
+# Get current volume as a percentage
+VOLUME=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{printf "%d", $2 * 100}')
+
+# Get mute status
+MUTED=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ | grep -q MUTED && echo " (muted)" || echo "")
+
+# Show notification
+notify-send -a Volume -h string:x-canonical-private-synchronous:volume -u low "Volume: $VOLUME%$MUTED"
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..4a74f57
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,12 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Run dotfiles setup script",
+ "type": "shell",
+ "command": "chmod +x ./setup.sh && ./setup.sh",
+ "problemMatcher": [],
+ "group": "build"
+ }
+ ]
+}
diff --git a/.zshrc b/.zshrc
new file mode 100644
index 0000000..9f702f7
--- /dev/null
+++ b/.zshrc
@@ -0,0 +1,88 @@
+# =====================
+# Environment settings
+# =====================
+
+# Do Not Track for CLI tools
+export DO_NOT_TRACK=1
+
+# Preferred editor
+export EDITOR='nvim'
+
+
+# =====================
+# Prompt and UI
+# =====================
+
+# Starship prompt (modern, fast, customizable)
+eval "$(starship init zsh)"
+
+
+# =====================
+# fzf integration
+# =====================
+
+# fzf key bindings and completion
+if [ -f /usr/share/fzf/key-bindings.zsh ]; then
+ source /usr/share/fzf/key-bindings.zsh
+fi
+if [ -f /usr/share/fzf/completion.zsh ]; then
+ source /usr/share/fzf/completion.zsh
+fi
+
+
+# =====================
+# Aliases
+# =====================
+
+# Modern replacements for coreutils
+alias cat="bat"
+alias ls="exa --icons"
+alias ll="exa -l --icons"
+alias la="exa -la --icons"
+
+# Developer tools
+alias lg="lazygit"
+
+
+# =====================
+# Zsh history settings
+# =====================
+
+HISTFILE=~/.zsh_history
+HISTSIZE=10000
+SAVEHIST=10000
+setopt append_history
+setopt inc_append_history
+setopt share_history
+setopt hist_ignore_dups
+setopt hist_reduce_blanks
+
+
+# =====================
+# Zsh plugin integrations
+# =====================
+
+# Autosuggestions
+if [ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]; then
+ source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
+fi
+# Syntax highlighting
+if [ -f /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
+ source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
+fi
+# Additional completions
+fpath+=/usr/share/zsh/site-functions
+autoload -Uz compinit && compinit
+
+
+# =====================
+# Command-not-found handler (Arch/pkgfile)
+# =====================
+
+if [ -f /usr/share/doc/pkgfile/command-not-found.zsh ]; then
+ source /usr/share/doc/pkgfile/command-not-found.zsh
+fi
+
+# =====================
+# End of .zshrc
+# =====================
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d09e33e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,65 @@
+# Arch Linux Dotfiles & Hyprland Setup
+
+This repository manages your personal dotfiles and a modular, Wayland-ready desktop environment for Arch Linux using `paru`.
+
+
+## Features
+- Modular setup: each aspect (packages, symlinks, shell, Neovim, Hyprland, sound, browsers, devtools, etc.) is handled by its own script in `modules/`.
+- All dotfiles and app configs are version-controlled and symlinked to your home directory.
+- Out-of-the-box integration for Hyprland, Waybar, Rofi, Mako, Alacritty, wlogout, and more.
+- Modern sound stack (PipeWire, WirePlumber, pavucontrol, etc.).
+- Volume notifications: see current volume as a Mako popup at the bottom center when changed.
+- Multi-monitor workspace rules: workspace 1 always on laptop, others on external (DP-1) if connected; all on laptop if standalone.
+- Brave browser always launches on workspace 10 and autostarts with Hyprland.
+- TTY/console uses German nodeadkeys layout (`de-latin1-nodeadkeys`).
+- Devtools module installs git, Python, Node.js, Docker, VS Code, opencode-bin, and more.
+- Easily extensible: add new modules or configs as needed.
+
+## Setup
+
+1. Clone this repository:
+ ```sh
+ git clone https://github.com/yourusername/dotfiles.git ~/git/dotfiles
+ cd ~/git/dotfiles
+ ```
+2. Run the setup script:
+ ```sh
+ ./setup.sh
+ ```
+
+When you run `setup.sh`, you will be prompted to select your device profile (`laptop` or `desktop`).
+This ensures that device-specific configs (e.g., battery, backlight, touchpad, monitor layout) are applied correctly for your hardware.
+You can also set the environment variable `DOTFILES_DEVICE` to skip the prompt:
+```sh
+DOTFILES_DEVICE=desktop ./setup.sh
+```
+
+The script will install all required packages and symlink dotfiles and configs (including everything in `.config/`) to your home directory, using the correct device-specific fragments for Hyprland and Waybar.
+
+
+## Customization
+- Add new dotfiles to the repo root (e.g., `.zshrc`, `.tmux.conf`).
+- Place app configs in `.config/` (e.g., `.config/hypr/hyprland.conf`).
+- Add or edit modules in the `modules/` directory to automate more setup steps.
+- To add custom scripts, place them in `.local/bin/` in the repo; they will be symlinked to `~/.local/bin/`.
+- To add browsers, edit `modules/06-browsers.sh` (Chrome, Firefox, Brave supported out of the box).
+- To add devtools, edit `modules/50-devtools.sh` (includes VS Code, opencode-bin, lazygit, etc.).
+
+
+## Requirements
+- Arch Linux
+- [paru](https://github.com/Morganamilo/paru) (will be installed automatically if missing)
+- For TTY keymap: `kbd` package (should be present on most systems)
+
+
+## Notable Integrations & Tips
+- **Browsers:** Chrome, Firefox, and Brave are installed via the browser module. Brave autostarts and is always on workspace 10.
+- **Devtools:** Includes VS Code (`visual-studio-code-bin`), opencode-bin, lazygit, and more.
+- **Volume OSD:** Volume changes show a notification at the bottom center of the screen (Mako).
+- **Multi-monitor:** Workspace 1 is always on the laptop display, others on DP-1 if connected.
+- **TTY Keymap:** Console uses German nodeadkeys layout for all users (system-wide via `localectl`).
+- **No official Teams/Outlook client:** Use the web app or AUR wrappers for best compatibility.
+- **TortoiseGit alternative:** Use GitKraken, Sublime Merge, SmartGit, or lazygit for graphical Git workflows.
+
+## License
+MIT
diff --git a/modules/01-packages.sh b/modules/01-packages.sh
new file mode 100755
index 0000000..99eb989
--- /dev/null
+++ b/modules/01-packages.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+# Install paru if not present
+if ! command -v paru &>/dev/null; then
+ echo "paru not found. Installing paru..."
+ git clone https://aur.archlinux.org/paru.git /tmp/paru
+ (cd /tmp/paru && makepkg -si --noconfirm)
+fi
+
+# List of packages to install (edit as needed)
+PACKAGES=(
+ git
+ zsh
+ neovim
+ tmux
+ starship
+ fzf
+ ripgrep
+ bat
+ exa
+ zsh-autosuggestions
+ zsh-syntax-highlighting
+ zsh-completions
+ btop
+ pkgfile
+ # Add more packages here
+)
+
+paru -S --needed --noconfirm "${PACKAGES[@]}"
diff --git a/modules/02-symlinks.sh b/modules/02-symlinks.sh
new file mode 100755
index 0000000..f48d4b0
--- /dev/null
+++ b/modules/02-symlinks.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+# Ensure required directories exist
+mkdir -p "$HOME/.config"
+
+echo "Symlinking dotfiles..."
+# Get the dotfiles directory (parent of modules directory)
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+DOTFILES_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
+
+# Symlink regular dotfiles (excluding .config directory)
+for file in $(find "$DOTFILES_DIR" -maxdepth 1 -name ".*"); do
+ [ "$file" = "$DOTFILES_DIR/.git" ] && continue
+ [ "$file" = "$DOTFILES_DIR/.github" ] && continue
+ [ "$file" = "$DOTFILES_DIR/.vscode" ] && continue
+ [ "$file" = "$DOTFILES_DIR/.config" ] && continue # Handle .config separately
+ basefile="$(basename "$file")"
+ if [ -f "$file" ] || [ -d "$file" ]; then
+ ln -sf "$file" "$HOME/$basefile"
+ echo "Linked $basefile"
+ fi
+done
+
+# Symlink .config directory contents
+CONFIG_DIR="$DOTFILES_DIR/.config"
+if [ -d "$CONFIG_DIR" ]; then
+ echo "Symlinking .config contents..."
+ for item in "$CONFIG_DIR"/*; do
+ [ -e "$item" ] || continue
+ baseitem="$(basename "$item")"
+ target_dir="$HOME/.config/$baseitem"
+
+ # Remove existing symlink or directory to avoid conflicts
+ [ -L "$target_dir" ] && rm "$target_dir"
+ [ -d "$target_dir" ] && [ ! -L "$target_dir" ] && rm -rf "$target_dir"
+
+ ln -sf "$item" "$target_dir"
+ echo "Linked .config/$baseitem"
+ done
+
+ # Device-specific symlinks for Hyprland and Waybar
+ if [ -n "$DOTFILES_DEVICE" ]; then
+ # Hyprland monitors
+ ln -sf "$CONFIG_DIR/hypr/includes/monitors-$DOTFILES_DEVICE.conf" "$CONFIG_DIR/hypr/includes/monitors.conf"
+ echo "Linked monitors-$DOTFILES_DEVICE.conf as monitors.conf"
+ # Hyprland input
+ ln -sf "$CONFIG_DIR/hypr/includes/input-$DOTFILES_DEVICE.conf" "$CONFIG_DIR/hypr/includes/input.conf"
+ echo "Linked input-$DOTFILES_DEVICE.conf as input.conf"
+ # Waybar config
+ ln -sf "$CONFIG_DIR/waybar/config-$DOTFILES_DEVICE" "$CONFIG_DIR/waybar/config"
+ echo "Linked config-$DOTFILES_DEVICE as waybar config"
+ fi
+fi
+
+echo "Dotfiles setup complete!"
+
+# Symlink .local/bin scripts
+LOCAL_BIN_REPO="$DOTFILES_DIR/.local/bin"
+LOCAL_BIN_HOME="$HOME/.local/bin"
+if [ -d "$LOCAL_BIN_REPO" ]; then
+ mkdir -p "$LOCAL_BIN_HOME"
+ echo "Symlinking .local/bin scripts..."
+ for script in "$LOCAL_BIN_REPO"/*; do
+ [ -e "$script" ] || continue
+ base_script="$(basename "$script")"
+ ln -sf "$script" "$LOCAL_BIN_HOME/$base_script"
+ echo "Linked .local/bin/$base_script"
+ done
+fi
+
diff --git a/modules/03-shell.sh b/modules/03-shell.sh
new file mode 100755
index 0000000..ba7c6be
--- /dev/null
+++ b/modules/03-shell.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+# Set zsh as the default shell
+if [ "$SHELL" != "$(command -v zsh)" ]; then
+ echo "Setting zsh as the default shell..."
+ chsh -s "$(command -v zsh)"
+fi
+
+# Set German nodeadkeys layout for TTY/console
+if command -v localectl >/dev/null 2>&1; then
+ echo "Setting TTY keyboard layout to de-latin1-nodeadkeys..."
+ sudo localectl set-keymap de-latin1-nodeadkeys
+fi
+
diff --git a/modules/04-nvim.sh b/modules/04-nvim.sh
new file mode 100755
index 0000000..6ce7ab5
--- /dev/null
+++ b/modules/04-nvim.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+# Install AstroNvim if not already installed
+ASTRONVIM_DIR="$HOME/.config/nvim"
+mkdir -p "$HOME/.config"
+if [ ! -d "$ASTRONVIM_DIR" ] || [ -z "$(ls -A "$ASTRONVIM_DIR")" ]; then
+ echo "Installing AstroNvim..."
+ rm -rf "$ASTRONVIM_DIR"
+ git clone --depth 1 https://github.com/AstroNvim/template "$ASTRONVIM_DIR"
+ rm -rf "$ASTRONVIM_DIR/.git"
+ echo "AstroNvim installed in $ASTRONVIM_DIR"
+else
+ echo "AstroNvim already installed. Skipping."
+fi
diff --git a/modules/05-hyprland.sh b/modules/05-hyprland.sh
new file mode 100644
index 0000000..e69de29
diff --git a/modules/05-sound.sh b/modules/05-sound.sh
new file mode 100755
index 0000000..dc463c1
--- /dev/null
+++ b/modules/05-sound.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+# Install sound-related packages for Hyprland
+
+SOUND_PACKAGES=(
+ pipewire
+ pipewire-alsa
+ pipewire-pulse
+ pipewire-jack
+ wireplumber
+ pavucontrol
+ pamixer
+ playerctl
+ alsa-utils
+ sof-firmware
+)
+
+paru -S --needed --noconfirm "${SOUND_PACKAGES[@]}"
+
+# Enable and start PipeWire services
+systemctl --user enable --now pipewire pipewire-pulse wireplumber
+
+echo "Sound packages installed and services enabled."
diff --git a/modules/06-browsers.sh b/modules/06-browsers.sh
new file mode 100644
index 0000000..e69de29
diff --git a/modules/06-hyprland.sh b/modules/06-hyprland.sh
new file mode 100755
index 0000000..899961f
--- /dev/null
+++ b/modules/06-hyprland.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+# Install Hyprland and related software
+
+HYPR_PACKAGES=(
+ hyprland
+ hyprlock
+ hypridle
+ xdg-desktop-portal-hyprland
+ waybar
+ rofi-wayland
+ mako
+ wl-clipboard
+ wlogout
+ brightnessctl
+ alacritty
+ ttf-jetbrains-mono
+ ttf-nerd-fonts-symbols
+ noto-fonts
+)
+
+paru -S --needed --noconfirm "${HYPR_PACKAGES[@]}"
+
+echo "Hyprland and related tools installed and configured."
diff --git a/modules/06-sound.sh b/modules/06-sound.sh
new file mode 100644
index 0000000..e69de29
diff --git a/modules/07-browsers.sh b/modules/07-browsers.sh
new file mode 100755
index 0000000..9dad245
--- /dev/null
+++ b/modules/07-browsers.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+# 06-browsers.sh - Install web browsers (Chrome, Firefox, Brave)
+
+set -e
+
+# List of browser packages to install
+BROWSERS=(google-chrome firefox brave-bin)
+
+# Install browsers with paru (AUR helper)
+echo "Installing browsers: ${BROWSERS[*]}"
+paru -S --needed --noconfirm "${BROWSERS[@]}"
+
+echo "Browsers installed."
diff --git a/modules/50-devtools.sh b/modules/50-devtools.sh
new file mode 100755
index 0000000..5246611
--- /dev/null
+++ b/modules/50-devtools.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+# Install development tools and utilities
+
+DEVTOOLS_PACKAGES=(
+ git
+ python
+ nodejs
+ npm
+ docker
+ jq
+ ripgrep
+ fd
+ btop
+ htop
+ lazygit
+ visual-studio-code-bin
+ opencode-bin
+)
+
+paru -S --needed --noconfirm "${DEVTOOLS_PACKAGES[@]}"
+
+echo "Development tools installed."
diff --git a/modules/99-postinstall.sh b/modules/99-postinstall.sh
new file mode 100755
index 0000000..be08d6d
--- /dev/null
+++ b/modules/99-postinstall.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+# Post-install steps for dotfiles setup
+
+# Update pkgfile database for command-not-found suggestions
+if command -v pkgfile &>/dev/null; then
+ echo "Updating pkgfile database..."
+ sudo pkgfile --update
+fi
+
+# Rehash zsh command hash table so new executables are found
+if command -v zsh &>/dev/null; then
+ echo "Running zsh rehash..."
+ zsh -c 'rehash'
+fi
+
+# Add other post-install steps here as needed
+# Example: update icon cache, font cache, etc.
+# sudo fc-cache -fv
+# sudo gtk-update-icon-cache -f /usr/share/icons/hicolor
+
+echo "Post-install steps complete."
diff --git a/setup.sh b/setup.sh
new file mode 100755
index 0000000..995a8d6
--- /dev/null
+++ b/setup.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# Dotfiles setup script for Arch Linux using paru
+set -e
+
+#!/usr/bin/env bash
+# Dotfiles setup script for Arch Linux using paru
+set -e
+
+# Device profile detection
+if [ -z "$DOTFILES_DEVICE" ]; then
+ echo "Select device profile:"
+ select profile in "laptop" "desktop"; do
+ DOTFILES_DEVICE="$profile"
+ export DOTFILES_DEVICE
+ echo "Using device profile: $DOTFILES_DEVICE"
+ break
+ done
+else
+ echo "Using device profile from environment: $DOTFILES_DEVICE"
+fi
+
+# Find, sort, and run all modules in the modules directory
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+MODULES=( $(find "$SCRIPT_DIR/modules" -maxdepth 1 -type f -name "*.sh" | sort) )
+COUNT=${#MODULES[@]}
+for i in "${!MODULES[@]}"; do
+ MODULE="${MODULES[$i]}"
+ STEP=$((i+1))
+ BASENAME=$(basename "$MODULE")
+ echo "[$STEP/$COUNT] Running $BASENAME..."
+ source "$MODULE"
+done