Blog

ARCH LINUX · HYPRLAND · WAYLAND · CATPPUCCIN MOCHA

I Left i3wm.
No Regrets.

Two weeks building Andromeda — a full Hyprland rice with floating pill bar, workspace overview, clipboard history, idle management, and one-script install. Here's everything, including what broke.

anuragdevon ~14 min read devon-rice Hyprland 0.54.3
Andromeda rice — full desktop screenshot
01

Why I Jumped

My old rice — archrice — was i3wm on X11. It was fast, muscle-memory-perfect, and entirely mine. I had no real reason to move. Then I saw ViegPhunt's dotfiles.

That blur. Those rounded corners. The way the notification center slid open like a UI concept that wasn't supposed to run on a real machine. I sat with my perfectly functional i3 setup and felt something I hadn't expected: envy.

So I switched. Two weeks of hyprctl reload and more journalctl -xe than I'd like to admit later — here's the result. Andromeda.

This isn't the "here's pretty screenshots, good luck" version. This is the real one — what I built, why I picked each tool, and the debugging I wish I'd skipped. If you're migrating from i3, you'll feel at home faster than you expect.

// REPO

All configs, scripts, and install automation: github.com/anuragdevon/devon-rice. Clone it, run one script, done.

02

Full Stack

RoleTool
Window managerHyprland 0.54.3
TerminalGhostty
ShellZsh + Starship
EditorNeovim
File manager (GUI)Nautilus (GTK4, Catppuccin) updated
File manager (TUI)Yazi
BrowserBrave / Thorium
Status barWaybar — floating pill updated
NotificationsSwaync
Lock screenHyprlock
Idle daemonHypridle new
WallpaperHyprpaper + random picker new
ScreenshotHyprshot new
Workspace overviewHyprexpo plugin new
ClipboardCliphist + wl-clipboard new
Audio toggleDynamic Rofi sink picker updated
Monitor toggletoggle-monitor.sh new
Font (terminal/UI)FiraCode Nerd Font
Font (browser/GTK)Noto Sans via fontconfig new
Icons / CursorPapirus-Dark / Bibata Modern Classic
Color schemeCatppuccin Mocha
Login managerSDDM catppuccin-mocha-blue

Hardware

MachineHP Laptop 15s — AMD Ryzen 3 3250U
GPUAMD Radeon Vega 3 (integrated)
RAM13.59 GiB
DisplayseDP-1 15" 1080p@60 · HDMI-A-1 21" 1080p@60
OS / KernelArch Linux x86_64 · 6.19.9-arch1-1
WMHyprland 0.54.3 (Wayland)
⚠ GPU NOTE

Vega 3 is integrated. Blur passes are capped at 3. Go higher and you will feel every frame drop.

03

Quick Start

bash
# 1. Install everything
yay -S hyprland ghostty waybar rofi-wayland swaync wlogout hyprlock hyprpaper \
       hypridle cava starship zsh-autosuggestions zsh-syntax-highlighting \
       ttf-firacode-nerd papirus-icon-theme bibata-cursor-theme noto-fonts noto-fonts-emoji \
       gnome-keyring libsecret neovim nautilus \
       catppuccin-gtk-theme-mocha kvantum qt6ct \
       cliphist wl-clipboard playerctl hyprshot \
       socat jq brightnessctl \
       bluez bluez-utils bluetuith sddm

# 2. Clone the dotfiles
git clone https://github.com/anuragdevon/devon-rice ~/devon-rice

# 3. Wire up symlinks (backs up your existing configs first)
cd ~/devon-rice && bash install.sh

# 4. Symlink GTK4 CSS for Nautilus (settings.ini alone won't work for GTK4)
ln -sf /usr/share/themes/catppuccin-mocha-blue-standard+default/gtk-4.0/gtk.css \
        ~/.config/gtk-4.0/gtk.css
ln -sf /usr/share/themes/catppuccin-mocha-blue-standard+default/gtk-4.0/gtk-dark.css \
        ~/.config/gtk-4.0/gtk-dark.css

# 5. Hyprexpo workspace overview plugin
hyprpm add https://github.com/hyprwm/hyprland-plugins
hyprpm enable hyprexpo

# 6. Update wallpaper paths — hyprpaper ignores ~/
nvim configs/hyprpaper/hyprpaper.conf
nvim configs/hypr/set-wallpaper.sh

# 7. Reload
hyprctl reload
// HOW SYMLINKS WORK

install.sh creates symlinks, not copies. Edit any config from anywhere — terminal, Neovim, Nautilus — and you're editing the repo file directly. git commit && git push whenever you want a checkpoint.

04

Step-by-Step Walkthrough

1. Base System

Fresh Arch install via archinstall. Get yay first:

bash
sudo pacman -S --needed git base-devel
git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si

2. Hyprland + Core

bash
yay -S hyprland ghostty waybar rofi-wayland swaync wlogout \
       hyprlock hypridle hyprpaper cava wl-clipboard nm-applet playerctl

3. Fonts, Icons, Cursor

bash
yay -S ttf-firacode-nerd papirus-icon-theme bibata-cursor-theme noto-fonts noto-fonts-emoji
fc-cache -fv

4. Shell

bash — ~/.zshrc
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
setopt APPEND_HISTORY SHARE_HISTORY HIST_IGNORE_DUPS HIST_IGNORE_SPACE

source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
eval "$(starship init zsh)"
05

Monitor Setup

ini — hyprland.conf
# Laptop — 15", HiDPI needs 1.5x for comfortable reading
monitor = eDP-1, 1920x1080@60, 0x0, 1.5

# External — 21", no scaling
# Offset = 1920 ÷ 1.5 = 1280 LOGICAL px (NOT 1920px)
monitor = HDMI-A-1, 1920x1080@60, 1280x0, 1.0

xwayland {
    force_zero_scaling = true  # fixes blurry XWayland apps on external monitor
}
env = GDK_SCALE, 1
env = XDG_SESSION_TYPE, wayland
⚠ THE OFFSET TRAP — READ THIS

Hyprland uses logical pixels for monitor positioning, not physical ones. At 1.5x scale the laptop's logical width is 1280px — not 1920px. Put the external at 1920x0 and you get a 640px invisible dead zone where your mouse just disappears. I spent an evening convinced I had a compositor bug. I did not.

// SINGLE MONITOR

Delete the HDMI-A-1 monitor line and the monitor focus/move keybinds. Everything else applies exactly the same.

06

Animations & Window Polish

The defaults are serviceable. These are better. Custom bezier curves inspired by Material Design 3 — much more expressive motion:

ini — animations
bezier = emphasizedDecel, 0.05, 0.7, 0.1, 1.0
bezier = menu_decel,      0.1,  1,   0.0, 1.0

animation = windowsIn,  1, 3, emphasizedDecel, popin 80%
animation = windowsOut, 1, 2, quick,           popin 90%
animation = workspaces, 1, 7, menu_decel,      slide
ini — decoration + general
decoration {
    rounding = 12
    dim_inactive = true    # unfocused windows darken slightly
    dim_strength = 0.07   # subtle — makes active window pop

    shadow {
        range = 20
        color = rgba(1a1a1a99)
        offset = 0 4
    }

    blur {
        enabled = true
        size = 6
        passes = 3         # HARD MAX on Vega 3
        vibrancy = 0.1696
    }
}

general {
    gaps_in = 5; gaps_out = 20; border_size = 2
    col.active_border   = rgba(33ccffee) rgba(00ff99ee) 45deg
    col.inactive_border = rgba(595959aa)

    snap { enabled = true; window_gap = 8; monitor_gap = 8 }
}

dim_inactive is the feature I didn't know I needed. Focus is visually obvious at a glance without any aggressive highlighting.

07

Keybindings

All i3-style. Coming from i3, your muscle memory settles in within 20 minutes.

Terminal
Super
Close window
SuperQ
App launcher
SuperD
File manager
SuperE
Workspace overview
SuperTab
Clipboard picker
SuperV
Screenshot region
SuperS
Active window shot
Print
Full monitor shot
SuperPrint
Lock screen
SuperL
Notifications
SuperN
Audio visualizer
SuperC
Calculator
Super=
Audio sink picker
SuperA
Toggle monitor
SuperM
Random wallpaper
SuperW
Power menu
SuperE
Reload config
SuperR
Focus window
Superh/j/k/l
Switch workspace
Super1–0

Plus Super+Shift+hjkl to move windows, Super+Ctrl+hjkl to resize, and Super+,/. to focus monitors.

08

Components

Waybar — Floating Pill Bar

Waybar floating pill bar on display 1
Waybar floating pill bar on display 2

Waybar on both displays with the floating pill layout.

Floats 10px above the top edge with margins on both sides — three sections: CPU · RAM · Battery · active window title on the left, workspace pills center (blue when active), media · volume · network · clock right.

jsonc — waybar config
{
    "layer":        "top",
    "height":       40,
    "margin-top":   10,
    "margin-left":  14,
    "margin-right": 14,
    "modules-left":   ["cpu", "memory", "battery", "hyprland/window"],
    "modules-center": ["hyprland/workspaces"],
    "modules-right":  ["custom/media", "pulseaudio", "network", "clock", "tray"]
}
css — floating pill style
window#waybar {
    background:    rgba(30, 30, 46, 0.82);
    border-radius: 14px;
    border:        1px solid rgba(137, 180, 250, 0.10);
}
⚠ SILENT SHADOW BUG

Old ~/.config/waybar/config file from a previous setup? Waybar loads it before config.jsonc, silently ignoring your new config. Nothing works, no error. Fix: rm ~/.config/waybar/config.

Screenshot — Hyprshot, Not grim+slurp

ini — 6 screenshot keybinds
# Region → clipboard (most used — drag to select)
bind = $mainMod SHIFT, S, exec, hyprshot -m region --clipboard-only
# Active window → clipboard
bind = , Print,            exec, hyprshot -m window -m active --clipboard-only
# Full monitor → clipboard
bind = $mainMod, Print,    exec, hyprshot -m output --clipboard-only
# Region → save file
bind = $mainMod CTRL, S,   exec, hyprshot -m region -o ~/Pictures/Screenshots/
# Active window → save file
bind = SHIFT, Print,       exec, hyprshot -m window -m active -o ~/Pictures/Screenshots/
# Full monitor → save file
bind = CTRL, Print,        exec, hyprshot -m output -o ~/Pictures/Screenshots/
⚠ WHY NOT grim+slurp?

grim -g "$(slurp)" - | wl-copy grabs input before the compositor releases it. Windows stop responding — workspaces freeze — until you click something. You'll think your rice is broken. Switch to Hyprshot, which handles the Wayland input grab correctly.

Workspace Overview — Hyprexpo

Hyprexpo workspace overview grid (Super+Tab)
bash — install + config
# Install build deps FIRST — hyprpm fails silently without these
yay -S cmake cpio pkgconf

hyprpm add https://github.com/hyprwm/hyprland-plugins
hyprpm enable hyprexpo

Clipboard History

ini — hyprland.conf
# Autostart — must be running or history won't accumulate
exec-once = wl-paste --watch cliphist store

# Keybind — searchable Rofi picker
bind = $mainMod SHIFT, V, exec, cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy

Audio Sink Picker (Dynamic — No Hardcoded MACs)

The old toggle script had a hardcoded Bluetooth MAC. Every new device broke it. The new version uses pactl list sinks to discover all outputs dynamically and presents them in Rofi. Select any device, all active streams follow automatically.

rofi picker — example output
󰍹  HDMI Monitor
   USB Headset
   Bluetooth Headphones  ✓ current

File Manager — Nautilus + GTK4

Nautilus file manager themed with Catppuccin Mocha (GTK4)
⚠ GTK4 IGNORES gtk-theme-name

settings.ini alone does nothing for GTK4 apps. You must symlink the CSS directly into ~/.config/gtk-4.0/gtk.css. Skip this and Nautilus looks completely default, regardless of what settings.ini says.

Calculator — Python via Rofi

rofi-calc needs the X11 build. The Wayland fork strips plugin support entirely and fails silently. Replaced with a 15-line bash script using Python's math module:

bash — rofi-calc.sh
#!/bin/bash
expr=$(rofi -dmenu -p "  " -l 0 -theme-str 'window {width: 420px;}')
[ -z "$expr" ] && exit

result=$(python3 -c "from math import *; print($expr)" 2>/dev/null || echo "Error")

selected=$(echo "$result" | rofi -dmenu -p "  $expr =" -l 1 \
    -theme-str 'window {width: 420px;}' \
    -theme-str 'element-text {text-color: #a6e3a1;}')

[ -n "$selected" ] && echo -n "$selected" | wl-copy
Rofi calculator showing expression and result

Hyprlock — Lock Screen

Hyprlock lock screen with blurred wallpaper and clock (Super+L)
ini — hyprlock.conf
background {
    path = /home/anurag/wallpapers/1.jpg  # absolute path — no ~/
    blur_passes = 4; blur_size = 8; brightness = 0.4
}
label {
    text = cmd[update:1000] echo "<b>$(date +"%H:%M")</b>"
    font_size = 80; font_family = FiraCode Nerd Font Bold
    position = 0, 40; halign = center; valign = center
}
input-field {
    size = 300, 52
    outer_color = rgb(89b4fa); inner_color = rgb(1e1e2e)
    rounding = 12; position = 0, -190
    halign = center; valign = center
}

Swaync · Wlogout · Cava · SDDM

Swaync notification center (Super+N)
Wlogout power menu (Super+Shift+E)
Cava audio visualizer in Ghostty (Super+C)
SDDM login screen with Catppuccin Mocha theme
09

Idle Management + Wallpaper

Hypridle — Auto Dim → Lock → Suspend

ini — hypridle.conf
general {
    lock_cmd         = pidof hyprlock || hyprlock
    before_sleep_cmd = loginctl lock-session
    after_sleep_cmd  = hyprctl dispatch dpms on
}

# 2.5 min → dim screen
listener { timeout = 150;  on-timeout = brightnessctl -s set 20%; on-resume = brightnessctl -r }
# 5 min → lock
listener { timeout = 300;  on-timeout = loginctl lock-session }
# 5.5 min → display off
listener { timeout = 330;  on-timeout = hyprctl dispatch dpms off; on-resume = hyprctl dispatch dpms on }
# 30 min → suspend
listener { timeout = 1800; on-timeout = systemctl suspend }

Random Wallpaper Picker

Drop images in ~/wallpapers/. On boot, a random one is picked and applied to both monitors. Super+Shift+W re-rolls it live without reloading Hyprland.

bash — set-wallpaper.sh
WALLPAPER_DIR="/home/anurag/wallpapers"
[ "$1" = "--startup" ] && sleep 3  # wait for Wayland socket to be ready

wall=$(find "$WALLPAPER_DIR" -type f \
    \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.webp" \) \
    | shuf -n 1)

hyprctl hyprpaper preload "$wall"
hyprctl hyprpaper wallpaper "eDP-1,$wall"
hyprctl hyprpaper wallpaper "HDMI-A-1,$wall"
⚠ CRITICAL — ABSOLUTE PATHS ONLY

Hyprpaper does not expand ~/. The script uses full absolute paths — /home/anurag/... always. Never ~/.... This one took hours to figure out from useless error output.

Monitor Toggle

bash — toggle-monitor.sh
HDMI="HDMI-A-1"
status=$(hyprctl monitors | grep -c "$HDMI")

if [ "$status" -gt 0 ]; then
    hyprctl keyword monitor "$HDMI,disabled"
    notify-send "Monitor" "Switched to laptop only"
else
    hyprctl keyword monitor "$HDMI,1920x1080@60,1280x0,1.0"
    notify-send "Monitor" "Dual monitor enabled"
fi
10

Colors + Fonts

One Color File, Everything in Sync

Waybar, Swaync, Wlogout, Rofi — all import from a single shared file. Change one hex, every component updates.

css — configs/colors/colors.css
@define-color background #1e1e2e;
@define-color foreground #cdd6f4;
@define-color blue       #89b4fa;  /* primary accent */
@define-color pink       #f38ba8;
@define-color green      #a6e3a1;
@define-color yellow     #f9e2af;
@define-color orange     #fab387;
@define-color purple     #cba6f7;
@define-color gray       #313244;
@define-color surface    #181825;

Two Fonts, One Job Each

FiraCode Nerd Font for terminal and UI. Noto Sans for browsers and GTK apps. FiraCode looks great in a terminal at 12px. It does not look great in browser tabs at 11px.

xml — fontconfig/fonts.conf
<alias>
    <family>sans-serif</family>
    <prefer><family>Noto Sans</family></prefer>
</alias>
<alias>
    <family>monospace</family>
    <prefer><family>FiraCode Nerd Font</family></prefer>
</alias>
11

The Gotchas

These cost me real time. Read before you start.

#01
hyprpaper ignores ~/
Always use /home/username/. The wallpaper silently doesn't load and the error messages give you nothing useful. Hours lost.
#02
rofi-wayland strips plugin support
rofi-calc needs the X11 build. The Wayland fork drops it and fails silently. The Python bash script replacement is genuinely better.
#03
External monitor offset gap
At 1.5x scale the laptop logical width is 1280px. External at 1920x0 = 640px dead zone. Use 1280x0. Hyprland uses logical pixels for positioning.
#04
grim+slurp freezes workspaces
grim -g "$(slurp)" - | wl-copy grabs input before the compositor releases it. Windows stop responding until you click. Use Hyprshot — it handles the input grab correctly.
#05
Waybar dies when terminal closes
Running waybar & in a terminal ties the process to that shell session. Always launch via exec-once in hyprland.conf only.
#06
Hyprexpo needs build deps first
yay -S cmake cpio pkgconf before hyprpm update. Skip them and hyprpm fails silently with no useful error about what's missing.
#07
GTK4 ignores gtk-theme-name
settings.ini alone does nothing for GTK4. Symlink the CSS directly into ~/.config/gtk-4.0/gtk.css. Nautilus looks completely default otherwise.
#08
cliphist needs wl-paste running
exec-once = wl-paste --watch cliphist store in autostart. Without it the clipboard picker opens empty every single time.
#09
FiraCode looks bad in browser tabs
Use Noto Sans as the system sans-serif via fontconfig. Terminal stays FiraCode. Browsers and GTK apps get Noto Sans. Everything renders at its intended size.
#10
Waybar config shadows config.jsonc
Old config file from a previous setup? Waybar loads it first and silently ignores your new config.jsonc. Nothing works. No error. rm ~/.config/waybar/config.
#11
Brave signs out every restart
gnome-keyring not starting. Add exec-once = gnome-keyring-daemon --start --components=secrets,pkcs11 to autostart.
#12
yay -S swww installed awww
yay matched a completely different package with a similar name. Ran with it for 20 minutes. Always verify what yay actually installed. Switched to Hyprpaper entirely.
12

Was It Worth It?

Yes. Completely.

i3 was great. If it's working for you on X11, there's no urgency to move. But Hyprland gives you everything i3 gave you plus things that simply aren't possible on X11: real compositor blur, smooth animations that feel native, per-monitor fractional scaling that actually works, and a genuinely active development community pushing the project forward fast.

The two weeks debugging were time well spent. I understand the Wayland stack better now than I did going in, and the setup I landed on is exactly what I wanted.

// andromeda · anuragdevon

Clone It. Break It. Make It Yours.

Every config, script, and install automation in one repo. Star it if it helped — drop a comment if you've hit a gotcha I missed.

What's your setup? Still on i3, or have you made the jump? 👇

Contact