diff --git a/audit/internal/webui/server.go b/audit/internal/webui/server.go
index e25697b..46bda52 100644
--- a/audit/internal/webui/server.go
+++ b/audit/internal/webui/server.go
@@ -221,6 +221,11 @@ func NewHandler(opts HandlerOptions) http.Handler {
// ── Infrastructure ──────────────────────────────────────────────────────
mux.HandleFunc("GET /healthz", h.handleHealthz)
mux.HandleFunc("GET /api/ready", h.handleReady)
+ mux.HandleFunc("GET /loading", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Cache-Control", "no-store")
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ _, _ = w.Write([]byte(loadingPageHTML))
+ })
// ── Existing read-only endpoints (preserved for compatibility) ──────────
mux.HandleFunc("GET /audit.json", h.handleAuditJSON)
@@ -1207,37 +1212,106 @@ const loadingPageHTML = `
-EASY-BEE
+EASY-BEE — Starting
-
+
███████╗ █████╗ ███████╗██╗ ██╗ ██████╗ ███████╗███████╗
██╔════╝██╔══██╗██╔════╝╚██╗ ██╔╝ ██╔══██╗██╔════╝██╔════╝
█████╗ ███████║███████╗ ╚████╔╝ █████╗██████╔╝█████╗ █████╗
██╔══╝ ██╔══██║╚════██║ ╚██╔╝ ╚════╝██╔══██╗██╔══╝ ██╔══╝
███████╗██║ ██║███████║ ██║ ██████╔╝███████╗███████╗
╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝
-
-
Starting up...
+
Hardware Audit LiveCD
+
+
Connecting to bee-web...
+
+
`
diff --git a/iso/builder/config/bootloaders/grub-pc/grub.cfg b/iso/builder/config/bootloaders/grub-pc/grub.cfg
index a6de856..3af572c 100644
--- a/iso/builder/config/bootloaders/grub-pc/grub.cfg
+++ b/iso/builder/config/bootloaders/grub-pc/grub.cfg
@@ -7,6 +7,7 @@ echo " █████╗ ███████║███████╗ ╚
echo " ██╔══╝ ██╔══██║╚════██║ ╚██╔╝ ╚════╝██╔══██╗██╔══╝ ██╔══╝"
echo " ███████╗██║ ██║███████║ ██║ ██████╔╝███████╗███████╗"
echo " ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝"
+echo " Hardware Audit LiveCD"
echo ""
menuentry "EASY-BEE" {
diff --git a/iso/builder/config/hooks/normal/9000-bee-setup.hook.chroot b/iso/builder/config/hooks/normal/9000-bee-setup.hook.chroot
index fc5fbca..c1b38ed 100755
--- a/iso/builder/config/hooks/normal/9000-bee-setup.hook.chroot
+++ b/iso/builder/config/hooks/normal/9000-bee-setup.hook.chroot
@@ -31,6 +31,7 @@ systemctl enable bee-audit.service
systemctl enable bee-web.service
systemctl enable bee-sshsetup.service
systemctl enable bee-selfheal.timer
+systemctl enable bee-boot-status.service
systemctl enable ssh.service
systemctl enable lightdm.service 2>/dev/null || true
systemctl enable qemu-guest-agent.service 2>/dev/null || true
@@ -59,7 +60,8 @@ chmod +x /usr/local/bin/bee-sshsetup 2>/dev/null || true
chmod +x /usr/local/bin/bee-smoketest 2>/dev/null || true
chmod +x /usr/local/bin/bee 2>/dev/null || true
chmod +x /usr/local/bin/bee-log-run 2>/dev/null || true
-chmod +x /usr/local/bin/bee-selfheal 2>/dev/null || true
+chmod +x /usr/local/bin/bee-selfheal 2>/dev/null || true
+chmod +x /usr/local/bin/bee-boot-status 2>/dev/null || true
if [ "$GPU_VENDOR" = "nvidia" ]; then
chmod +x /usr/local/bin/bee-nvidia-load 2>/dev/null || true
chmod +x /usr/local/bin/bee-gpu-burn 2>/dev/null || true
diff --git a/iso/overlay/etc/systemd/system/bee-boot-status.service b/iso/overlay/etc/systemd/system/bee-boot-status.service
new file mode 100644
index 0000000..39ccf04
--- /dev/null
+++ b/iso/overlay/etc/systemd/system/bee-boot-status.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Bee: boot status display
+DefaultDependencies=no
+After=systemd-user-sessions.service
+Before=getty@tty1.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/local/bin/bee-boot-status
+TTYPath=/dev/tty1
+StandardInput=tty
+StandardOutput=tty
+StandardError=tty
+
+[Install]
+WantedBy=multi-user.target
diff --git a/iso/overlay/etc/systemd/system/getty@tty1.service.d/wait-bee.conf b/iso/overlay/etc/systemd/system/getty@tty1.service.d/wait-bee.conf
new file mode 100644
index 0000000..3229111
--- /dev/null
+++ b/iso/overlay/etc/systemd/system/getty@tty1.service.d/wait-bee.conf
@@ -0,0 +1,2 @@
+[Unit]
+After=bee-boot-status.service
diff --git a/iso/overlay/etc/systemd/system/lightdm.service.d/bee-display-mode.conf b/iso/overlay/etc/systemd/system/lightdm.service.d/bee-display-mode.conf
index 530ee6f..ab5c259 100644
--- a/iso/overlay/etc/systemd/system/lightdm.service.d/bee-display-mode.conf
+++ b/iso/overlay/etc/systemd/system/lightdm.service.d/bee-display-mode.conf
@@ -1,6 +1,4 @@
[Unit]
-Wants=bee-preflight.service
-After=bee-preflight.service
[Service]
ExecStartPre=/usr/local/bin/bee-display-mode
diff --git a/iso/overlay/usr/local/bin/bee-boot-status b/iso/overlay/usr/local/bin/bee-boot-status
new file mode 100644
index 0000000..083793d
--- /dev/null
+++ b/iso/overlay/usr/local/bin/bee-boot-status
@@ -0,0 +1,56 @@
+#!/bin/sh
+# bee-boot-status — boot progress display on tty1.
+# Shows live service status until all bee services are done or failed,
+# then exits so getty can show the login prompt.
+# GUI (lightdm) starts independently without waiting for this.
+
+# Services to wait for before handing off to login prompt.
+CRITICAL="bee-preflight bee-nvidia bee-audit"
+# Additional services shown for information only.
+ALL="bee-preflight bee-network bee-nvidia bee-audit bee-web"
+
+svc_icon() {
+ case "$(systemctl is-active "$1.service" 2>/dev/null)" in
+ active) printf '\033[32m[ OK ]\033[0m' ;;
+ failed) printf '\033[31m[ FAIL ]\033[0m' ;;
+ activating) printf '\033[33m[ .. ]\033[0m' ;;
+ *) printf '[ ]' ;;
+ esac
+}
+
+all_critical_done() {
+ for svc in $CRITICAL; do
+ case "$(systemctl is-active "$svc.service" 2>/dev/null)" in
+ active|failed|inactive) ;;
+ *) return 1 ;;
+ esac
+ done
+ return 0
+}
+
+while true; do
+ printf '\033[H\033[2J'
+ printf '\n'
+ printf ' \033[33m███████╗ █████╗ ███████╗██╗ ██╗ ██████╗ ███████╗███████╗\033[0m\n'
+ printf ' \033[33m██╔════╝██╔══██╗██╔════╝╚██╗ ██╔╝ ██╔══██╗██╔════╝██╔════╝\033[0m\n'
+ printf ' \033[33m█████╗ ███████║███████╗ ╚████╔╝ █████╗██████╔╝█████╗ █████╗\033[0m\n'
+ printf ' \033[33m██╔══╝ ██╔══██║╚════██║ ╚██╔╝ ╚════╝██╔══██╗██╔══╝ ██╔══╝\033[0m\n'
+ printf ' \033[33m███████╗██║ ██║███████║ ██║ ██████╔╝███████╗███████╗\033[0m\n'
+ printf ' \033[33m╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝\033[0m\n'
+ printf ' Hardware Audit LiveCD\n'
+ printf '\n'
+ for svc in $ALL; do
+ printf ' %s %s\n' "$(svc_icon $svc)" "$svc"
+ done
+ printf '\n'
+
+ if all_critical_done; then
+ printf ' \033[1mSystem ready.\033[0m Audit is running in the background.\n'
+ printf ' Web UI will be available at \033[1mhttp://
/\033[0m when done.\n'
+ printf '\n'
+ sleep 2
+ break
+ fi
+
+ sleep 1
+done
diff --git a/iso/overlay/usr/local/bin/bee-openbox-session b/iso/overlay/usr/local/bin/bee-openbox-session
index 6e9c4fe..4952fa8 100755
--- a/iso/overlay/usr/local/bin/bee-openbox-session
+++ b/iso/overlay/usr/local/bin/bee-openbox-session
@@ -9,22 +9,14 @@ xset s noblank
tint2 &
-# Wait up to 120s for bee-web to bind. The web server starts immediately now
-# (audit is deferred), so this should succeed in a few seconds on most hardware.
-i=0
-while [ $i -lt 120 ]; do
- if curl -sf http://localhost/healthz >/dev/null 2>&1; then break; fi
- sleep 1
- i=$((i+1))
-done
-
chromium \
--disable-infobars \
--disable-translate \
--no-first-run \
--disable-session-crashed-bubble \
--disable-features=TranslateUI \
+ --user-data-dir=/tmp/bee-chrome \
--start-maximized \
- http://localhost/ &
+ http://localhost/loading &
exec openbox