Replace swaylock with gtklock; centralise theme palette

- Replace swaylock with gtklock (username + password form lockscreen)
- Add gtklock/config.ini and gtklock/style.css (Tomorrow Night theme)
- Update niri keybindings and swayidle to invoke gtklock -d
- Update packages.txt: swaylock -> gtklock
- Update install.sh: add AUR helper detection (yay/paru), symlink gtklock configs
- Add theme/colors.css (CSS custom properties) and theme/colors.json
- Update waybar/style.css, wofi/style.css, gtklock/style.css to import shared palette
- Update README.md with project summary and component table
- Add ARCHITECTURE.md and CLAUDE.md
This commit is contained in:
funman300
2026-04-24 12:56:58 -07:00
parent 8c099437a4
commit 8be00bc273
12 changed files with 668 additions and 31 deletions
+286
View File
@@ -0,0 +1,286 @@
# ARCHITECTURE.md
## Overview
This system is a **Wayland-first desktop environment** built around the **Niri compositor**, designed for:
* Tiling workflow
* Keyboard-driven interaction
* Minimal background processes
* Clean separation between components
---
## High-Level Architecture
```
┌──────────────┐
│ greetd │
│ + regreet │
└──────┬───────┘
┌──────────────┐
│ Niri │
│ Compositor │
└──────┬───────┘
┌───────────────┼────────────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────┐
│ Waybar │ │ Mako │ │ Wofi │
└────────┘ └────────┘ └──────────┘
│ │ │
▼ ▼ ▼
Status UI Notifications App Launcher
┌────────────────────────────────────┐
▼ ▼
Alacritty GTK Apps / CLI
Fish + Starship
```
---
## Component Responsibilities
### Niri (Core)
* Window management
* Input handling
* Layout control
* Workspace logic
**Owns:**
* Keybindings
* Window rules
* Focus behavior
---
### Waybar (Status Layer)
* Displays system info (time, CPU, network, etc.)
* Acts as visual feedback layer
**Design constraints:**
* No heavy scripts
* Prefer event-driven updates
---
### Mako (Notifications)
* Handles all desktop notifications
**Rules:**
* Short timeouts
* Minimal visual noise
* No stacking chaos
---
### Wofi (Launcher)
* Application launcher + runner
**Usage modes:**
* drun (desktop apps)
* run (commands)
---
### Terminal Stack
#### Alacritty
* GPU-accelerated terminal
* No tabs (delegated to WM)
#### Fish
* Interactive shell
#### Starship
* Prompt renderer
---
### Session & Login
#### greetd + regreet
* Lightweight login manager
* Starts Niri session
---
### Lock Screen
#### gtklock
* Simple Wayland-native lockscreen
---
### Background Services
| Function | Tool |
| ----------- | ------------ |
| Wallpaper | swww |
| Screenshots | grim + slurp |
| Clipboard | cliphist |
---
## Data Flow
### Startup Sequence
1. greetd starts
2. regreet authenticates user
3. Niri session launches
4. Autostart:
* waybar
* mako
* swww
* cliphist (if enabled)
---
### User Interaction Flow
**Launching Apps**
```
Keybind → Wofi → Exec → Niri manages window
```
**Notifications**
```
App → DBus → Mako → Render
```
**Status Updates**
```
System → Waybar module → Display
```
---
## Configuration Strategy
### Centralized via Symlinks
```
~/.config/
├── niri/
├── waybar/
├── alacritty/
├── fish/
├── starship.toml
├── mako/
├── wofi/
└── gtklock/
```
All configs are sourced from the repo via:
```
install.sh → ln -s
```
---
## Theming Architecture
### Global Theme: Tomorrow Night
Applied consistently across:
* GTK (Materia-dark)
* Icons (Papirus)
* Terminal
* Waybar
* Wofi
### Recommended Structure
```
theme/
├── colors.json (optional future)
├── gtk.css
├── waybar.css
└── wofi.css
```
---
## Extensibility Model
### Safe Extensions
* Add Waybar modules (lightweight)
* Add Wofi modes
* Extend Niri keybindings
* Add CLI tools
### Risky Extensions
* Background daemons
* Polling scripts
* X11 compatibility layers
* Overly dynamic configs
---
## Performance Considerations
* Avoid blocking shell scripts
* Keep Waybar modules lightweight
* Minimize startup processes
* Prefer static config over runtime logic
---
## Failure Modes
| Issue | Likely Cause |
| --------------------- | ------------------- |
| Black screen on login | Niri config error |
| Missing bar | Waybar not launched |
| No notifications | Mako not running |
| Slow shell | Fish config bloat |
---
## Future Improvements
* Shared theme variables across all tools
* Config templating (optional, must stay transparent)
* Per-host overrides
* Optional feature flags (minimal)
---
## Guiding Philosophy
This system is:
* **Predictable**
* **Minimal**
* **Fast**
* **Keyboard-first**
Every addition must justify its existence.
If it adds complexity without clear benefit, it should not be included.
+204
View File
@@ -0,0 +1,204 @@
# CLAUDE.md
## Purpose
This repository defines a complete Wayland desktop environment built around **Niri**, with a focus on:
* Simplicity
* Reproducibility
* Fast startup
* Low cognitive overhead
* Clean separation of concerns
Claude should act as a **systems engineer**, not just a script generator.
---
## Core Principles
### 1. Single Source of Truth
* All configuration lives in `~/.config` via symlinks
* No duplication across tools
* Shared values (theme, fonts, gaps, etc.) should be centralized
### 2. Idempotent Setup
* `install.sh` must be safe to re-run
* No destructive operations without explicit flags
* Detect and skip existing correct state
### 3. Composability
* Each tool (waybar, mako, wofi, etc.) is independent
* No hidden coupling unless explicitly documented
### 4. Declarative > Imperative
* Prefer static config over runtime scripts
* Avoid background daemons unless required
---
## Expected Claude Behavior
When modifying this repo, Claude should:
### Configuration Changes
* Keep configs minimal and readable
* Avoid introducing magic or implicit behavior
* Prefer explicit keybindings and comments
### Adding Features
* Justify *why* the feature exists
* Ensure it fits Wayland + Niri workflow
* Avoid X11 dependencies unless unavoidable
### Refactoring
* Reduce duplication across configs
* Extract shared values (colors, fonts, spacing)
* Keep file structure intuitive
---
## Directory Expectations
```
dotfiles/
├── config/
│ ├── niri/
│ ├── waybar/
│ ├── alacritty/
│ ├── fish/
│ ├── starship/
│ ├── wofi/
│ ├── mako/
│ ├── gtklock/
│ └── ...
├── install.sh
├── packages.txt
└── README.md
```
---
## Tooling Rules
### Niri
* All keybindings must be defined here
* Window rules must be deterministic
* Avoid runtime scripting where possible
### Waybar
* Keep modules minimal
* Prefer JSON config over scripts
* Avoid polling when event-based is possible
### Fish + Starship
* Fast startup is critical
* No blocking operations
* Avoid heavy plugins
### Wofi
* Keep styling consistent with GTK theme
* Avoid unnecessary wrappers
### Mako
* Notifications should be minimal and non-intrusive
* Timeout defaults should be short
---
## Theming
Theme: **Tomorrow Night**
Ensure consistency across:
* GTK (Materia-dark)
* Icons (Papirus)
* Terminal (Alacritty)
* Waybar
* Wofi
Claude should:
* Reuse the same color palette everywhere
* Avoid hardcoding colors in multiple places
---
## Install Script Expectations
`install.sh` must:
1. Symlink configs into `~/.config`
2. Install packages from `packages.txt`
3. Detect distro (Arch-based assumed unless specified)
4. Fail fast on errors
5. Print clear status messages
---
## Anti-Patterns (DO NOT DO)
* ❌ Duplicate configs across tools
* ❌ Add large frameworks or dependencies
* ❌ Introduce race conditions in startup
* ❌ Use sleep-based timing hacks
* ❌ Hardcode machine-specific paths
---
## Safe Enhancements
Claude may suggest:
* Shared theme variables
* Config generation (if simple and transparent)
* Modular config structure
* Performance improvements (startup, memory)
---
## Testing Expectations
After changes:
* Niri starts without errors
* Waybar loads correctly
* No missing fonts/icons
* No broken keybindings
* No noticeable startup delay
---
## Output Style
When generating code:
* Provide complete files (not fragments)
* Keep formatting clean
* Avoid unnecessary comments
* Prefer clarity over cleverness
---
## Summary
This is a **minimal, fast, reproducible Wayland environment**.
Claudes role is to:
* Maintain clarity
* Prevent bloat
* Improve consistency
* Keep everything predictable
+19
View File
@@ -1,5 +1,24 @@
# Dotfiles (Niri + Wayland) # Dotfiles (Niri + Wayland)
A personal Wayland desktop configuration centered around the **Niri** tiling compositor.
| Area | Tool |
|---|---|
| Compositor | niri |
| Bar | waybar |
| Terminal | alacritty |
| Shell | fish + starship |
| Launcher | wofi |
| Notifications | mako |
| Lockscreen | gtklock |
| Login/greeter | greetd + regreet |
| Wallpaper | swww |
| Screenshots | grim + slurp |
| Clipboard | cliphist |
| Theme | Tomorrow Night (GTK: Materia-dark, icons: Papirus) |
Everything is symlinked into `~/.config` via `install.sh`, with packages listed in `packages.txt`.
## Setup ## Setup
```bash ```bash
+4
View File
@@ -0,0 +1,4 @@
[main]
gtk-theme=Materia-dark
style=/home/alex/.config/gtklock/style.css
follow-focus=true
+72
View File
@@ -0,0 +1,72 @@
@import url("../theme/colors.css");
/* gtklock style - Tomorrow Night theme */
window {
background-color: var(--tn-bg);
}
#body {
background-color: transparent;
}
#clock-label {
color: var(--tn-fg);
font-family: "JetBrainsMono Nerd Font";
font-size: 48px;
font-weight: bold;
margin-bottom: 8px;
}
#date-label {
color: var(--tn-fg-dim);
font-family: "JetBrainsMono Nerd Font";
font-size: 16px;
margin-bottom: 24px;
}
#username-label {
color: var(--tn-fg);
font-family: "JetBrainsMono Nerd Font";
font-size: 18px;
font-weight: bold;
margin-bottom: 12px;
}
#input-box {
background-color: var(--tn-bg-alt);
border: 2px solid var(--tn-bg-high);
border-radius: 6px;
color: var(--tn-fg);
font-family: "JetBrainsMono Nerd Font";
font-size: 14px;
padding: 8px 12px;
min-width: 280px;
}
#input-box:focus {
border-color: var(--tn-blue);
}
#error-label {
color: var(--tn-red);
font-family: "JetBrainsMono Nerd Font";
font-size: 13px;
margin-top: 8px;
}
#unlock-button {
background-color: var(--tn-bg-high);
border: none;
border-radius: 6px;
color: var(--tn-fg);
font-family: "JetBrainsMono Nerd Font";
font-size: 14px;
padding: 8px 20px;
margin-top: 12px;
}
#unlock-button:hover {
background-color: var(--tn-blue);
color: var(--tn-bg);
}
+15 -4
View File
@@ -2,11 +2,21 @@
set -e set -e
echo "==> Installing packages" echo "==> Detecting AUR helper"
sudo pacman -S --needed - < packages.txt if command -v yay &>/dev/null; then
AUR_HELPER=yay
elif command -v paru &>/dev/null; then
AUR_HELPER=paru
else
echo "ERROR: No AUR helper found. Install yay or paru first." >&2
exit 1
fi
echo "==> Installing packages (using $AUR_HELPER)"
$AUR_HELPER -S --needed - < packages.txt
echo "==> Creating config directories" echo "==> Creating config directories"
mkdir -p ~/.config/{niri,waybar,wofi,mako,alacritty,gtk-3.0,gtk-4.0,swaylock,fish} ~/.config/environment.d ~/.config/xdg-desktop-portal mkdir -p ~/.config/{niri,waybar,wofi,mako,alacritty,gtk-3.0,gtk-4.0,gtklock,fish} ~/.config/environment.d ~/.config/xdg-desktop-portal
echo "==> Linking configs" echo "==> Linking configs"
@@ -18,7 +28,8 @@ ln -sf "$(pwd)/waybar/style.css" ~/.config/waybar/style.css
ln -sf "$(pwd)/wofi/config" ~/.config/wofi/config ln -sf "$(pwd)/wofi/config" ~/.config/wofi/config
ln -sf "$(pwd)/wofi/style.css" ~/.config/wofi/style.css ln -sf "$(pwd)/wofi/style.css" ~/.config/wofi/style.css
ln -sf "$(pwd)/mako/config" ~/.config/mako/config ln -sf "$(pwd)/mako/config" ~/.config/mako/config
ln -sf "$(pwd)/swaylock/config" ~/.config/swaylock/config ln -sf "$(pwd)/gtklock/config.ini" ~/.config/gtklock/config
ln -sf "$(pwd)/gtklock/style.css" ~/.config/gtklock/style.css
ln -sf "$(pwd)/fish/config.fish" ~/.config/fish/config.fish ln -sf "$(pwd)/fish/config.fish" ~/.config/fish/config.fish
ln -sf "$(pwd)/starship/starship.toml" ~/.config/starship.toml ln -sf "$(pwd)/starship/starship.toml" ~/.config/starship.toml
ln -sf "$(pwd)/alacritty/alacritty.toml" ~/.config/alacritty/alacritty.toml ln -sf "$(pwd)/alacritty/alacritty.toml" ~/.config/alacritty/alacritty.toml
+2 -2
View File
@@ -36,7 +36,7 @@ spawn-at-startup "mako"
spawn-at-startup "swww-daemon" spawn-at-startup "swww-daemon"
spawn-at-startup "nm-applet" "--indicator" spawn-at-startup "nm-applet" "--indicator"
spawn-at-startup "polkit-gnome-authentication-agent-1" spawn-at-startup "polkit-gnome-authentication-agent-1"
spawn-at-startup "swayidle" "-w" "timeout" "300" "niri msg action power-off-monitors" "timeout" "600" "swaylock" "timeout" "1800" "systemctl suspend" "before-sleep" "swaylock" spawn-at-startup "swayidle" "-w" "timeout" "300" "niri msg action power-off-monitors" "timeout" "600" "gtklock" "-d" "timeout" "1800" "systemctl suspend" "before-sleep" "gtklock" "-d"
spawn-at-startup "wl-paste" "--watch" "cliphist" "store" spawn-at-startup "wl-paste" "--watch" "cliphist" "store"
spawn-at-startup "blueman-applet" spawn-at-startup "blueman-applet"
spawn-at-startup "wlsunset" "-l" "49.2" "-L" "-123.1" spawn-at-startup "wlsunset" "-l" "49.2" "-L" "-123.1"
@@ -88,7 +88,7 @@ binds {
Mod+M { move-window-to-workspace "minimized"; } Mod+M { move-window-to-workspace "minimized"; }
Mod+Shift+M { focus-workspace "minimized"; } Mod+Shift+M { focus-workspace "minimized"; }
Mod+Shift+E { spawn "swaylock"; } Mod+Shift+E { spawn "gtklock" "-d"; }
Mod+Shift+P { spawn "powermenu"; } Mod+Shift+P { spawn "powermenu"; }
Mod+Shift+C { spawn "clipboard-picker"; } Mod+Shift+C { spawn "clipboard-picker"; }
Mod+Shift+X { quit; } Mod+Shift+X { quit; }
+1 -1
View File
@@ -9,7 +9,7 @@ slurp
wl-clipboard wl-clipboard
brightnessctl brightnessctl
pamixer pamixer
swaylock gtklock
swayidle swayidle
ttf-jetbrains-mono-nerd ttf-jetbrains-mono-nerd
network-manager-applet network-manager-applet
+22
View File
@@ -0,0 +1,22 @@
/* Tomorrow Night - shared color palette */
/* @import this file from waybar, wofi, gtklock CSS */
* {
--tn-bg: #1d1f21;
--tn-bg-alt: #282a2e;
--tn-bg-high: #373b41;
--tn-fg: #c5c8c6;
--tn-fg-dim: #969896;
--tn-fg-muted: #707880;
--tn-blue: #81a2be;
--tn-green: #b5bd68;
--tn-yellow: #f0c674;
--tn-red: #cc6666;
--tn-magenta: #b294bb;
--tn-cyan: #8abeb7;
/* Alpha variants */
--tn-bg-a90: rgba(29, 31, 33, 0.90);
--tn-bg-a95: rgba(29, 31, 33, 0.95);
--tn-bg-a96: rgba(29, 31, 33, 0.96);
}
+15
View File
@@ -0,0 +1,15 @@
{
"name": "Tomorrow Night",
"background": "#1d1f21",
"background_alt": "#282a2e",
"background_high": "#373b41",
"foreground": "#c5c8c6",
"foreground_dim": "#969896",
"foreground_muted": "#707880",
"blue": "#81a2be",
"green": "#b5bd68",
"yellow": "#f0c674",
"red": "#cc6666",
"magenta": "#b294bb",
"cyan": "#8abeb7"
}
+14 -12
View File
@@ -1,20 +1,22 @@
@import url("../theme/colors.css");
* { * {
font-family: JetBrainsMono Nerd Font; font-family: JetBrainsMono Nerd Font;
font-size: 13px; font-size: 13px;
} }
window#waybar { window#waybar {
background: rgba(29,31,33,0.9); background: var(--tn-bg-a90);
color: #c5c8c6; color: var(--tn-fg);
} }
#workspaces button { #workspaces button {
padding: 0 8px; padding: 0 8px;
color: #707880; color: var(--tn-fg-muted);
} }
#workspaces button.focused { #workspaces button.focused {
color: #81a2be; color: var(--tn-blue);
} }
#clock, #battery, #network, #pulseaudio, #clock, #battery, #network, #pulseaudio,
@@ -24,33 +26,33 @@ window#waybar {
} }
#custom-power-profile.performance { #custom-power-profile.performance {
color: #f0c674; color: var(--tn-yellow);
} }
#custom-power-profile.power-saver { #custom-power-profile.power-saver {
color: #b5bd68; color: var(--tn-green);
} }
#battery.warning { #battery.warning {
color: #f0c674; color: var(--tn-yellow);
} }
#battery.critical { #battery.critical {
color: #cc6666; color: var(--tn-red);
} }
#cpu.warning { #cpu.warning {
color: #f0c674; color: var(--tn-yellow);
} }
#cpu.critical { #cpu.critical {
color: #cc6666; color: var(--tn-red);
} }
#temperature.warm { #temperature.warm {
color: #f0c674; color: var(--tn-yellow);
} }
#temperature.critical { #temperature.critical {
color: #cc6666; color: var(--tn-red);
} }
+14 -12
View File
@@ -1,29 +1,31 @@
@import url("../theme/colors.css");
* { * {
font-family: JetBrainsMono Nerd Font; font-family: JetBrainsMono Nerd Font;
font-size: 14px; font-size: 14px;
} }
window { window {
background-color: rgba(29, 31, 33, 0.96); background-color: var(--tn-bg-a96);
border: 1px solid #373b41; border: 1px solid var(--tn-bg-high);
border-radius: 12px; border-radius: 12px;
color: #c5c8c6; color: var(--tn-fg);
} }
#input { #input {
background-color: #282a2e; background-color: var(--tn-bg-alt);
color: #c5c8c6; color: var(--tn-fg);
border: 1px solid #373b41; border: 1px solid var(--tn-bg-high);
border-radius: 8px; border-radius: 8px;
padding: 10px 14px; padding: 10px 14px;
margin: 12px 12px 6px 12px; margin: 12px 12px 6px 12px;
outline: none; outline: none;
font-size: 15px; font-size: 15px;
caret-color: #81a2be; caret-color: var(--tn-blue);
} }
#input:focus { #input:focus {
border-color: #81a2be; border-color: var(--tn-blue);
} }
#inner-box { #inner-box {
@@ -46,17 +48,17 @@ window {
} }
#entry:selected { #entry:selected {
background-color: #282a2e; background-color: var(--tn-bg-alt);
border: 1px solid #81a2be; border: 1px solid var(--tn-blue);
outline: none; outline: none;
} }
#text { #text {
color: #c5c8c6; color: var(--tn-fg);
} }
#text:selected { #text:selected {
color: #81a2be; color: var(--tn-blue);
font-weight: bold; font-weight: bold;
} }