JustToThePoint English Website Version
JustToThePoint en español

Arch Linux Post-Installation: Niri Configuration

Without pain, without sacrifice, we would have nothing, Fight Club.

Cauchy-Goursat theorem

Introduction

With the core Wayland stack (Niri, greetd, and Noctalia) installed, the next step is tailoring the compositor to your specific workflow. Niri uses the KDL (KDL Document Language) syntax for its configuration file, typically located at ~/.config/niri/config.kdl. Unlike the INI-like syntax of i3 or Sway, KDL offers a structured, node-based format that clearly defines relationships between settings.

The configuration below sets up a productive environment by defining named workspaces (a, b, c, d), applying window rules —such as rounded corners and maximizing new windows— and integrating Noctalia Shell for status bars and notifications. It also includes comprehensive keybindings for navigation, media controls, and launching applications, ensuring a seamless transition from installation to daily use.

Niri configuration file

	// ── Niri config.kdl ──────────────────────────────────────────────────────────
	// Location (via symlink): ~/.config/niri/config.kdl
	// Source:                 ~/dotfiles/myArch/config/niri/config.kdl
	//
	// Niri uses KDL (https://kdl.dev) — not TOML, not YAML.
	// KDL syntax: node-name key=value { child-nodes }
	// Comments use //
	//
	// Niri concepts vs i3:
	//   i3:   fixed-size tiling, workspaces are full-screen containers
	//   Niri: windows tile HORIZONTALLY in an infinite scroll per workspace
	//         Workspaces are VERTICAL — Super+1/2/3 to switch, Super+Shift+1 to move
	//         Overview (Super+O) = bird's-eye of all workspaces on all monitors
	// ─────────────────────────────────────────────────────────────────────────────

    prefer-no-csd

	// ── Input ─────────────────────────────────────────────────────────────────────
	input {
	    keyboard {
        // XKB is the keyboard mapping system used by Wayland and X11.
        xkb {
            // Defines the keyboard layout (US English)
            layout "us"
            // Remaps Caps Lock to Escape (vim-friendly)
            options "caps:escape"
        }
        // Wait 300ms before repeating (milliseconds)
        repeat-delay 300
        // Repeat every 50ms (20 characters per second)
        repeat-rate 50
      }

      // Window gains focus when mouse enters it (sloppy focus).
	    focus-follows-mouse max-scroll-amount="0%"
	}

	// ── Output (monitors) ─────────────────────────────────────────────────────────
	// Run: niri msg outputs. List all outputs with their capabilities.
	output "eDP-1" {
      // Format: "widthxheight@refresh_rate"
	    mode "1920x1080@60"
      // Scaling factor for HiDPI displays, e.g., 1.0 = no scaling
	    scale 1.0
	    position x=0 y=0
	}

	output "HDMI-A-1" {
	    mode "1920x1080@60"
	    scale 1.0
	    position x=1920 y=0
	}

  // Named workspaces provide semantic meaning: a (Alacritty), b (browsing), c (code), d (miscellaneous)
  // Empty braces { } indicate no special configuration (using defaults).
	workspace "a" {
	}

	workspace "b" {
	}

	workspace "c" {
	}

  workspace "d" {
	}

	// ── Window rules and appearance ─────────────────────────────────────────────────────────
	window-rule {
	    // Rounded corners by 12 pixels for a modern look
	    geometry-corner-radius 12

	    // Clip window contents to rounded corner boundaries
	    // Without this, corners are rounded but contents overflow as rectangles
	    clip-to-geometry true

      // All windows start maximized (fill workspace width)
      open-maximized true
	}

  window-rule {
      match app-id="code"
      open-on-workspace "c"
  }

  // Application-Specific Rules
  // Finding App-IDs: niri msg windows,
  window-rule {
      match app-id="org.gnome.Nautilus"
      open-on-workspace "b"
  }

  window-rule {
      match app-id="google-chrome"
      open-on-workspace "d"
  }

  window-rule {
      match app-id="Alacritty"
      open-on-workspace "a"
  }

	// ── Layout ────────────────────────────────────────────────────────────────────
	layout {
	    // Adds 8 pixels of spacing around windows
	    gaps 8

	    // Always show borders (even for single window)
	    // Width of the window border in pixels
	    border {
		    width 2
		  }

   	  // Focus ring — shown when border is off, or in addition to border
    	focus-ring {
        	off // Disable additional focus ring (border is enough)
    	}

    	// Default column width — windows start at this fraction of screen width
    	// "proportion" means fraction of the usable width (0.0 to 1.0)
    	default-column-width { proportion 0.5; }
      // New windows start at 50% of screen width

    	// Better UX: keep focused column centered ("never" GNOME-like)
    	center-focused-column "on-overflow"

    	always-center-single-column
    }
    // ── Debug settings required by Noctalia ───────────────────────────────────────
    debug {
        // Required for Noctalia's notification actions and window activation.
        // Without this, clicking "Open" in a notification may not bring the
        // window to focus.
        honor-xdg-activation-with-invalid-serial
    }

    // ── Noctalia wallpaper / overview settings ────────────────────────────────────
    // Option 1: Blurred overview wallpaper (recommended).
    // Noctalia renders a blurred+dimmed copy of your wallpaper behind the overview.
    // Requires "Enable overview wallpaper" to be ON in Noctalia settings.
    layer-rule {
        match namespace="^noctalia-overview*"
        place-within-backdrop true
    }

// Startup Applications
// ── Startup: launch Noctalia Shell ────────────────────────────────────────────
// Provides: Status bar, launcher, notifications, control center
spawn-at-startup "qs" "-c" "noctalia-shell"

// ── Startup: XWayland satellite ───────────────────────────────────────────────
// xwayland-satellite starts XWayland on-demand for X11 applications.
// Remove this line if you have no X11 apps.
spawn-at-startup "xwayland-satellite"

// ── Startup: polkit agent ─────────────────────────────────────────────────────
// Required for GUI privilege escalation dialogs
spawn-at-startup "systemd-run" "--user" "--scope" "/usr/lib/polkit-kde-authentication-agent-1"

// ── Startup: clipboard history ────────────────────────────────────────────────
// cliphist watches the clipboard and stores history.
// Noctalia's clipboard widget reads from cliphist.
spawn-at-startup "wl-paste" "--watch" "cliphist" "store"

// Network applet. NetworkManager system tray icon
// Shows WiFi status and connections
spawn-at-startup "nm-applet"

// Application Autostart
spawn-at-startup "code" "/mnt/data/justtothepoint/"
spawn-at-startup "nautilus"
spawn-at-startup "google-chrome-stable"
spawn-at-startup "alacritty"

// ── Keybindings ───────────────────────────────────────────────────────────────
// Mod = Super (Windows key)
// Syntax: binds { key { action; } }
binds {

    // ── Noctalia IPC keybindings ──────────────────────────────────────────────
    // App launcher (like rofi -show drun)
    Mod+Space { spawn "qs" "-c" "noctalia-shell" "ipc" "call" "launcher" "toggle"; }

    // Rofi launcher (FAST, minimal)
    Mod+D {
        spawn-sh "rofi -show drun";
    }

    // Overview: bird's-eye view of all workspaces
    Mod+O { toggle-overview; }

    // Control centre (wifi, volume, etc.)
    Mod+C { spawn "qs" "-c" "noctalia-shell" "ipc" "call" "controlCenter" "toggle"; }

    // Notification centre
    Mod+N { spawn "noctalia-shell" "ipc" "call" "notificationCenter" "toggle"; }

    // Lock screen
    Mod+L { spawn "noctalia-shell" "ipc" "call" "lockScreen" "lock"; }

    // ── Applications ──────────────────────────────────────────────────────────
    Mod+Return { spawn "alacritty"; }
    Mod+B      { spawn "firefox"; }
    Mod+E      { spawn "thunar"; }

    // ── Screenshots (Niri built-in) ───────────────────────────────────────────
    // Screenshots saved to ~/Pictures/Screenshots/ by default
    Mod+S             { screenshot; }                // interactive region picker
    Ctrl+Print        { screenshot-screen; }         // full screen
    Alt+Print         { screenshot-window; }         // focused window only

    // ── Window management ─────────────────────────────────────────────────────
    Mod+Q             { close-window; }
    Mod+F             { maximize-column; } // Maximize column (fills screen width)
    Mod+Shift+F       { fullscreen-window; } // Fullscreen window (no borders, covers entire screen)

    // Focus movement (vim keys and arrows)
    Mod+H             { focus-column-left; }
    Mod+L             { focus-column-right; }
    Mod+J             { focus-window-down; }
    Mod+K             { focus-window-up; }
    Mod+Left          { focus-column-left; }
    Mod+Right         { focus-column-right; }
    Mod+Down          { focus-window-down; }
    Mod+Up            { focus-window-up; }

    // Move windows
    Mod+Shift+Left    { move-column-left; }
    Mod+Shift+Right   { move-column-right; }
    Mod+Shift+Down    { move-window-down; }
    Mod+Shift+Up      { move-window-up; }

    // Column width
    Mod+Minus         { set-column-width "-10%"; }
    Mod+Equal         { set-column-width "+10%"; }

    // Window height
    Mod+Shift+Minus   { set-window-height "-10%"; }
    Mod+Shift+Equal   { set-window-height "+10%"; }

    // Floating
    Mod+V             { toggle-window-floating; }

    // ── Workspaces ────────────────────────────────────────────────────────────
    // Switch to workspace N
    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+Shift+1       { move-column-to-workspace 1; }
    Mod+Shift+2       { move-column-to-workspace 2; }
    Mod+Shift+3       { move-column-to-workspace 3; }
    Mod+Shift+4       { move-column-to-workspace 4; }
    Mod+Shift+5       { move-column-to-workspace 5; }
    Mod+Shift+6       { move-column-to-workspace 6; }
    Mod+Shift+7       { move-column-to-workspace 7; }
    Mod+Shift+8       { move-column-to-workspace 8; }
    Mod+Shift+9       { move-column-to-workspace 9; }

    // Scroll workspaces
    Mod+Page_Down     { focus-workspace-down; }
    Mod+Page_Up       { focus-workspace-up; }
    Mod+Shift+Page_Down { move-column-to-workspace-down; }
    Mod+Shift+Page_Up   { move-column-to-workspace-up; }

    // ── Volume / brightness ───────────────────────────────────────────────────
    XF86AudioRaiseVolume  allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "5%+"; }
    XF86AudioLowerVolume  allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "5%-"; }
    XF86AudioMute         allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
    XF86AudioMicMute      allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
    XF86MonBrightnessUp   allow-when-locked=true { spawn "brightnessctl" "s" "5%+"; }
    XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "s" "5%-"; }
    XF86AudioPlay   { spawn "playerctl" "play-pause"; }
    XF86AudioNext   { spawn "playerctl" "next"; }
    XF86AudioPrev   { spawn "playerctl" "previous"; }

    // ── Niri system ───────────────────────────────────────────────────────────
    // Cycle to a random wallpaper (swww with fade transition)
    // Mod+W             { spawn "sh" "-c" "swww img $(find ~/wallpaper -type f \( -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' -o -name '*.webp' \) | shuf -n1) --transition-type fade --transition-duration 1"; }
    Mod+Shift+E       { quit; }    // Exit Niri (returns to greetd login)
    // Power off system
    Mod+Shift+D     { spawn "systemctl" "poweroff"; }
    // Reload Niri config without restart
    Mod+Shift+R       { spawn "niri" "msg" "reload-config"; }
}

Check Configuration Syntax: niri --validate-config

Bitcoin donation

JustToThePoint Copyright © 2011 - 2026 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.