Skip to content

ARCHITECTURE_OVERVIEW

snowarch edited this page Apr 25, 2026 · 1 revision

Architecture Overview

How iNiR is put together, from the highest level down to the part that matters for your question.

The 30-second version

iNiR is a single-process QML application that runs inside Quickshell. There's no backend daemon, no IPC server, no separate process for services. Everything (the bar, sidebars, notifications, audio control, compositor IPC, config management) lives in one QML runtime talking to system services through D-Bus, sockets, and subprocess calls.

Your apps
   |
iNiR shell (bar, panels, notifications, settings, everything)
   |
Quickshell (QML shell framework)
   |
Niri compositor (windows, rendering, input)
   |
Wayland protocol --> GPU

Entry point

shell.qml is the root. It's a ShellRoot (Quickshell-specific, not a regular QML Item). On load it:

  1. Force-instantiates critical singletons (Idle, PowerProfilePersistence)
  2. Waits for Config.ready (JSON config loaded from disk)
  3. Applies the current theme
  4. Loads either ShellIiPanels.qml or ShellWafflePanels.qml based on the panel family config
  5. Schedules deferred service loading after the first frame renders

Total cold start to panels visible: under 2 seconds on decent hardware.

Two panel families

The shell has two completely separate visual identities that share the same services layer:

Material ii uses Material Design language with 5 style variants (material, cards, aurora, inir, angel). Bar at the top. Sidebars from the edges. Overview launcher.

Waffle uses Windows 11 Fluent Design. Taskbar at the bottom. Start menu. Action center. Notification center.

They're mutually exclusive at runtime. Switch with Super+Shift+W. Both families read from the same Config singleton and the same services, but use completely different visual token systems (Appearance.* vs Looks.*), different panel definitions, and different settings UIs.

More details: Panel Families

Services layer

70+ QML singletons handle everything that isn't pure UI:

  • Compositor IPC: NiriService talks to Niri via socket, gets workspace/window/output state
  • System integration: Audio (PipeWire), Network (NetworkManager), Bluetooth (BlueZ), Battery (UPower)
  • Data management: Notifications, clipboard history, events, weather, calendar sync
  • Theming: MaterialThemeLoader watches colors.json, ThemeService orchestrates the pipeline
  • Content: AI chat (Gemini/OpenAI/Ollama), YT Music player, anime tracking, Reddit

Services are registered in services/qmldir and available everywhere as singletons.

Full catalog: Services Catalog

Config system

One JSON file, one QML schema, one write method:

  • Schema: modules/common/Config.qml (1385+ lines, 51 top-level sections)
  • User file: ~/.config/illogical-impulse/config.json
  • Defaults: defaults/config.json
  • Write: Config.setNestedValue("section.key", value) (the only way that persists)
  • Read: Config.options?.section?.key ?? fallback

Users configure everything through the graphical Settings UI. The JSON file is an implementation detail they shouldn't need to touch.

More details: Config System

Theming pipeline

Pick a wallpaper and the entire system follows:

Wallpaper image
   |
generate_colors_material.py (Material You color extraction)
   |
colors.json (full Material 3 palette)
   |
MaterialThemeLoader (QML file watcher)
   |
Appearance tokens (400+ color/size/animation properties)
   |
Every UI component
   |
External apps (GTK, terminals, Firefox, VS Code, Discord...)

The pipeline also supports 44 built-in theme presets (Catppuccin, Gruvbox, Nord, etc.) that bypass wallpaper extraction and inject colors directly.

More details: Theming Architecture

Directory structure

A simplified map of what lives where:

Directory What's in it Risk level
modules/common/ Config, Appearance, shared widgets Critical
services/ 70+ system integration singletons High
scripts/inir CLI launcher (2400+ lines of bash) High
sdata/ Install, update, migrations High
defaults/ Shipped default config and app configs Medium
modules/bar/ Top bar (ii family) Normal
modules/waffle/ Complete Windows 11 family Normal
modules/sidebarLeft/ AI chat, YT Music, widgets Normal
modules/sidebarRight/ Toggles, calendar, tools Normal
translations/ i18n strings (15+ languages) Low

Full breakdown: Project Map

Distribution

iNiR ships as a git repo with an interactive installer:

git clone https://github.com/snowarch/inir.git
cd inir
./setup install

Two install modes:

  • Repo-sync: ./setup install syncs the repo to ~/.config/quickshell/inir/
  • Package-managed: make install copies to /usr/share/quickshell/inir/

Updates: ./setup update or inir update (git pull + sync + migrate + restart).

The systemd service wires to the compositor via wants links, not graphical-session.target (which would also start on KDE/GNOME).

More details: Installation, Setup & Update

Clone this wiki locally