Introduce a new production desktop shell at `shells/desktop/shell` built with C++20, Qt Quick/QML, and LayerShellQt, including top bar, launcher, desktop surfaces, shell state, and mock app data. Add the shared `packages/nebula-ui` QML module (theme, controls, focus, icons) and wire it into the shell build. Retire the old GTK/WebKit native host by removing `shells/desktop/native`, move the React shell UI to `shells/desktop/prototype-react` as an archived design reference, and update root/compositor/session documentation to reflect the new Linux-only production architecture and temporary Sway role.
Nebula Desktop
Production shell for the mouse-and-keyboard NebulaOS desktop.
Architecture
Nebula Desktop is a Qt Quick / QML Wayland shell. It draws system chrome only. It does not host application or game windows.
Ubuntu
↓
Wayland
↓
Sway
temporary compositor
↓
Nebula Shell
C++20 + Qt 6 + Qt Quick/QML + LayerShellQt
Eventual target:
Ubuntu/Linux
↓
Wayland
↓
Nebula compositor
↓
Nebula Shell
Qt Quick/QML
Normal applications remain ordinary Wayland / XWayland clients of the compositor:
Normal Application
↓
Wayland / XWayland
↓
Compositor
↓
GPU
Nebula chrome:
QML
↓
Qt Quick
↓
Wayland Layer Shell
↓
Compositor
Games, browsers, terminals, and other apps never pass through Qt Quick.
Production stack
| Piece | Technology |
|---|---|
| Language | C++20 |
| UI | Qt 6, Qt Quick, QML |
| Layer surfaces | LayerShellQt |
| Build | CMake |
| Shared design system | packages/nebula-ui (import Nebula.UI) |
The executable is nebula-shell.
QML module URI: Nebula.Shell.
Surfaces
Independent Wayland layer-shell windows:
| Surface | Layer | Role |
|---|---|---|
| Desktop | BACKGROUND |
Wallpaper / desktop, no exclusive zone, no keyboard focus |
| Top Bar | TOP |
40px bar, exclusive zone, no keyboard focus by default |
| Launcher | OVERLAY |
Hidden until the Nebula button opens it |
Stacking:
OVERLAY
Nebula Launcher
TOP
Nebula Top Bar
NORMAL WAYLAND WINDOWS
Firefox, Steam, Blender, games, terminals, …
BACKGROUND
Nebula Desktop
Layout
shells/desktop/
├── README.md this file
├── shell/ production Qt/QML shell
│ ├── CMakeLists.txt
│ ├── src/main.cpp
│ └── qml/
└── prototype-react/ archived design reference only
Shared visual language lives in packages/nebula-ui, not in Desktop-specific chrome.
Linux build
This project will not compile on Windows. LayerShellQt is a Wayland API and is not stubbed.
On the Ubuntu NebulaOS VM:
sudo apt install \
qt6-base-dev \
qt6-declarative-dev \
qt6-wayland \
liblayershellqtinterface-dev \
qml6-module-org-kde-layershell \
qml6-module-qtquick \
qml6-module-qtquick-window \
cmake \
build-essential
Qt 6.4 or newer is required. loadFromModule is used on Qt 6.5+.
cd shells/desktop/shell
cmake -S . -B build
cmake --build build -j$(nproc)
./build/nebula-shell
Run inside a Wayland compositor such as Sway (compositor/sway/nebula-sway.conf). Sway must not show its own bar.
There is no npm server, Vite server, NEBULA_SHELL_DEV_URL, WebKitGTK, GTK4, or React involved in running the production shell.
QML lint
If the installed Qt provides qmllint:
qmllint \
shells/desktop/shell/qml/*.qml \
shells/desktop/shell/qml/surfaces/*.qml \
shells/desktop/shell/qml/components/*.qml \
shells/desktop/shell/qml/mock/*.qml \
packages/nebula-ui/qml/Nebula/UI/*.qml
Do not use ESLint or Oxlint on the production Qt shell.
Design reference
prototype-react/ is an archived React/Vite UI. It is not the production shell. Keep it until the Qt shell reaches visual and behavioural parity, then remove it in a later cleanup.
Out of scope
Not implemented in this milestone:
- PipeWire, NetworkManager, BlueZ, UPower
- D-Bus services
- real
.desktopdiscovery or app launching - Sway IPC, workspaces, notifications
- authentication, greetd, Gamescope
- a custom Nebula compositor
- Nebula Bigscreen
Those come later. Bigscreen is expected to reuse Nebula.UI and shared C++ services with a different interaction model.