splux-site · log · files · refs · tags · releases · people · languages · GitHub · commit
a878fa9
Add handbook docs for setup, manual tty install, and the slim ISO.
Parents
Stat
README.md | 7 + site/404.html | 2 +- site/assets/docs.js | 131 +++++++++++++ site/assets/style.css | 226 +++++++++++++++++++++ site/docs/first-boot/index.html | 76 ++++++++ site/docs/images/index.html | 78 ++++++++ site/docs/index.html | 56 +++++- site/docs/sps/index.html | 106 ++++++++++ site/download/index.html | 7 +- site/index.html | 9 +- site/install/index.html | 421 +++++++++++++++++++++++++++++++++++++--- tools/build-site.sh | 41 +++- tools/subst.awk | 5 + 13 files changed, 1123 insertions(+), 42 deletions(-)
Diff
diff --git a/README.md b/README.md
index e62a4b9..76673c8 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,13 @@ ISO names are stable:
The visible tag name is filled at build time from the GitHub Releases API
and refreshed from GitHub when you open the page.
+## Handbook
+
+`docs/` and `install/` are a static handbook (sidebar plus tabs). The
+install page covers guided `setup`, a full manual tty install without
+`setup`, and the slim ISO. New handbook HTML under `site/docs/` must be
+registered in `tools/build-site.sh` with the correct `../../../../` depth.
+
## News
`news/` is generated at build time from GitHub, not edited by hand:
diff --git a/site/404.html b/site/404.html
index addf7da..eb7a9c1 100644
--- a/site/404.html
+++ b/site/404.html
@@ -14,7 +14,7 @@
<h2>404</h2>
<hr class="rule">
<p>The requested page does not exist.</p>
-<p><a href="../../../../">home</a></p>
+<p><a href="../../../../">home</a> · <a href="../../../../docs/">handbook</a> · <a href="../../../../install/">install</a></p>
</main>
@@FOOTER@@
</div>
diff --git a/site/assets/docs.js b/site/assets/docs.js
new file mode 100644
index 0000000..bf62e13
--- /dev/null
+++ b/site/assets/docs.js
@@ -0,0 +1,131 @@
+// Handbook tabs. No framework. Hash URLs stay shareable.
+(function () {
+ function ready() {
+ var sets = document.querySelectorAll("[data-tabs]");
+ if (!sets.length)
+ return;
+ document.documentElement.classList.add("js-tabs");
+ for (var i = 0; i < sets.length; i++)
+ initSet(sets[i]);
+ applyHash();
+ window.addEventListener("hashchange", applyHash);
+ }
+
+ function tabsOf(set) {
+ var n = set.firstElementChild;
+ var list = null;
+ while (n) {
+ if (n.getAttribute && n.classList.contains("tablist")) {
+ list = n;
+ break;
+ }
+ n = n.nextElementSibling;
+ }
+ if (!list)
+ return [];
+ return list.querySelectorAll('[role="tab"]');
+ }
+
+ function initSet(set) {
+ var tabs = tabsOf(set);
+ var selected = null;
+ for (var i = 0; i < tabs.length; i++) {
+ bindTab(set, tabs, tabs[i], i);
+ if (!selected && tabs[i].getAttribute("aria-selected") === "true")
+ selected = tabs[i];
+ }
+ if (!selected && tabs.length)
+ selected = tabs[0];
+ if (selected)
+ selectTab(set, selected, false);
+ }
+
+ function bindTab(set, tabs, tab, index) {
+ tab.addEventListener("click", function () {
+ selectTab(set, tab, true);
+ });
+ tab.addEventListener("keydown", function (e) {
+ var next = -1;
+ if (e.key === "ArrowRight" || e.key === "ArrowDown")
+ next = (index + 1) % tabs.length;
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp")
+ next = (index - 1 + tabs.length) % tabs.length;
+ else if (e.key === "Home")
+ next = 0;
+ else if (e.key === "End")
+ next = tabs.length - 1;
+ else
+ return;
+ e.preventDefault();
+ tabs[next].focus();
+ selectTab(set, tabs[next], true);
+ });
+ }
+
+ function selectTab(set, tab, updateHash) {
+ var tabs = tabsOf(set);
+ for (var i = 0; i < tabs.length; i++) {
+ var on = tabs[i] === tab;
+ tabs[i].setAttribute("aria-selected", on ? "true" : "false");
+ tabs[i].tabIndex = on ? 0 : -1;
+ var id = tabs[i].getAttribute("aria-controls");
+ var panel = id ? document.getElementById(id) : null;
+ if (!panel)
+ continue;
+ if (on)
+ panel.removeAttribute("hidden");
+ else
+ panel.setAttribute("hidden", "");
+ }
+ if (updateHash) {
+ var hash = tab.getAttribute("data-hash");
+ if (hash && history.replaceState)
+ history.replaceState(null, "", "#" + hash);
+ else if (hash)
+ location.hash = hash;
+ }
+ }
+
+ function reveal(tab) {
+ var t = tab;
+ while (t) {
+ var set = t.closest("[data-tabs]");
+ if (!set)
+ break;
+ selectTab(set, t, false);
+ var panel = set.closest(".tabpanel");
+ if (!panel)
+ break;
+ t = document.querySelector(
+ '[role="tab"][aria-controls="' + panel.id + '"]'
+ );
+ }
+ }
+
+ function applyHash() {
+ var hash = (location.hash || "").replace(/^#/, "");
+ if (!hash)
+ return;
+ var tab = document.querySelector(
+ '[role="tab"][data-hash="' + hash + '"]'
+ );
+ if (!tab) {
+ var el = document.getElementById(hash);
+ if (el) {
+ var panel = el.closest(".tabpanel") ||
+ (el.classList.contains("tabpanel") ? el : null);
+ if (panel)
+ tab = document.querySelector(
+ '[role="tab"][aria-controls="' + panel.id + '"]'
+ );
+ }
+ }
+ if (tab)
+ reveal(tab);
+ }
+
+ if (document.readyState === "loading")
+ document.addEventListener("DOMContentLoaded", ready);
+ else
+ ready();
+})();
diff --git a/site/assets/style.css b/site/assets/style.css
index 8fee3fa..e67a4e5 100644
--- a/site/assets/style.css
+++ b/site/assets/style.css
@@ -400,3 +400,229 @@ footer p {
overflow-x: auto;
}
}
+
+/* Handbook: sidebar, tabs, callouts. Same black / gray / yellow. */
+
+.wrap.wide {
+ max-width: 1100px;
+}
+
+.handbook {
+ display: grid;
+ grid-template-columns: 13.5rem minmax(0, 1fr);
+ gap: 2rem;
+ align-items: start;
+}
+
+.docs-side {
+ position: sticky;
+ top: 1rem;
+ padding-top: 0.15rem;
+}
+
+.docs-kicker {
+ margin: 0 0 0.45rem;
+ color: var(--muted);
+ font-size: 0.8rem;
+}
+
+.docs-toc {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ border-top: 1px solid var(--rule);
+}
+
+.docs-toc li {
+ margin: 0;
+ max-width: none;
+}
+
+.docs-toc a {
+ display: block;
+ padding: 0.35rem 0;
+ border-bottom: 1px solid var(--rule);
+ color: var(--muted);
+}
+
+.docs-toc a:hover {
+ color: var(--accent);
+}
+
+.docs-toc a[aria-current="page"] {
+ color: var(--fg);
+ text-decoration: none;
+ border-bottom-color: var(--accent);
+}
+
+.handbook main h2:first-child {
+ margin-top: 0;
+}
+
+.handbook h3 {
+ margin: 1.5rem 0 0.35rem;
+ font-size: 0.95rem;
+ font-weight: 700;
+ color: var(--fg);
+}
+
+.handbook h4 {
+ margin: 1.15rem 0 0.3rem;
+ font-size: 0.9rem;
+ font-weight: 700;
+ color: var(--muted);
+}
+
+.local-toc {
+ list-style: none;
+ padding: 0;
+ margin: 0.5rem 0 1rem;
+}
+
+.local-toc li {
+ margin: 0.15rem 0;
+}
+
+.tabs {
+ margin: 0.85rem 0 1.25rem;
+}
+
+.tablist {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0;
+ border-bottom: 1px solid var(--rule);
+ margin: 0 0 1rem;
+}
+
+.tablist [role="tab"] {
+ font: inherit;
+ background: transparent;
+ color: var(--muted);
+ border: 1px solid transparent;
+ border-bottom: 0;
+ padding: 0.45rem 0.85rem;
+ cursor: pointer;
+ margin-bottom: -1px;
+}
+
+.tablist [role="tab"]:hover {
+ color: var(--fg);
+}
+
+.tablist [role="tab"][aria-selected="true"] {
+ color: var(--accent);
+ background: #111;
+ border-color: var(--rule);
+ border-bottom-color: var(--bg);
+}
+
+.tabpanel {
+ margin: 0;
+}
+
+html.js-tabs .tabpanel[hidden] {
+ display: none;
+}
+
+.callout {
+ border: 1px solid var(--rule);
+ border-left: 3px solid var(--accent);
+ padding: 0.65rem 0.85rem;
+ margin: 0.85rem 0 1rem;
+ color: var(--muted);
+}
+
+.callout strong {
+ color: var(--fg);
+ font-weight: 700;
+}
+
+.callout p {
+ margin: 0.35rem 0;
+}
+
+.callout p:first-child {
+ margin-top: 0;
+}
+
+.callout p:last-child {
+ margin-bottom: 0;
+}
+
+table.docs {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.9rem;
+ margin: 0.75rem 0 1rem;
+}
+
+table.docs th,
+table.docs td {
+ text-align: left;
+ vertical-align: top;
+ padding: 0.35rem 0.7rem 0.35rem 0;
+ border-bottom: 1px solid #1a1a1a;
+}
+
+table.docs th {
+ color: var(--muted);
+ font-weight: 400;
+ border-bottom: 1px solid var(--rule);
+}
+
+.steps {
+ list-style: none;
+ padding: 0;
+ margin: 0.75rem 0 1rem;
+ counter-reset: step;
+}
+
+.steps > li {
+ counter-increment: step;
+ position: relative;
+ padding-left: 2.4rem;
+ margin: 0.9rem 0;
+ max-width: none;
+}
+
+.steps > li::before {
+ content: counter(step, decimal-leading-zero);
+ position: absolute;
+ left: 0;
+ top: 0;
+ color: var(--accent);
+ font-weight: 700;
+}
+
+@media (max-width: 860px) {
+ .handbook {
+ grid-template-columns: 1fr;
+ gap: 1.25rem;
+ }
+
+ .docs-side {
+ position: static;
+ }
+
+ .docs-toc {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0 1rem;
+ border-top: 0;
+ }
+
+ .docs-toc li {
+ border: 0;
+ }
+
+ .docs-toc a {
+ border: 0;
+ padding: 0.15rem 0;
+ }
+
+ table.docs {
+ display: block;
+ overflow-x: auto;
+ }
+}
diff --git a/site/docs/first-boot/index.html b/site/docs/first-boot/index.html
new file mode 100644
index 0000000..0ba11a0
--- /dev/null
+++ b/site/docs/first-boot/index.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>After first boot - Splux Linux</title>
+<meta name="description" content="What to do after a Splux install: passwords, network, services, packages.">
+<link rel="icon" href="../../../../assets/favicon.png" type="image/png">
+<link rel="stylesheet" href="../../../../assets/style.css">
+</head>
+<body>
+<a class="skip" href="#main">Skip to content</a>
+<div class="wrap wide">
+@@HEADER@@
+<div class="handbook">
+@@DOCSNAV@@
+<main id="main">
+<h2>After first boot</h2>
+<hr class="rule">
+<p>This chapter assumes the machine booted the kernel you installed, with GRUB, and reached a getty. If it did not, go back to the <a href="../../../../install/">install chapter</a> and check the kernel package, <code>/etc/fstab</code>, and <code>grub-install</code>.</p>
+
+<h3>Passwords</h3>
+<p>If you did not set hashes during <code>setup</code>, root and the first user are locked. From a live root you can <code>chroot</code> and run <code>passwd</code>. After a successful boot:</p>
+<pre class="block">passwd
+passwd alex</pre>
+<p>Busybox <code>passwd</code> is on the live images. The installed <code>shadow</code> package provides it on the new system once <code>base-system</code> is in place.</p>
+
+<h3>Read the notes</h3>
+<p><code>setup</code> writes text files under <code>/root/</code>:</p>
+<ul>
+<li><code>sps-bootloader.txt</code> if GRUB was not installed during setup</li>
+<li><code>sps-user.txt</code> for the first account</li>
+<li><code>sps-init.txt</code> for the chosen PID 1</li>
+<li><code>sps-network.txt</code> (setup does not write DHCP or static network config)</li>
+<li><code>sps-fstab.txt</code> and <code>/etc/fstab</code></li>
+<li><code>sps-services.txt</code> when services were enabled</li>
+</ul>
+<p>A manual install does not create those files unless you write them yourself. The same facts still apply.</p>
+
+<h3>Network</h3>
+<p>On a console install, bring an interface up by hand. <code>dhcpcd</code> is in <code>base-system</code>:</p>
+<pre class="block">ip link
+dhcpcd eth0</pre>
+<p>On Plasma, use plasma-nm after graphical login. OpenSSH is present when you used the server profile or installed <code>openssh</code>.</p>
+
+<h3>Services</h3>
+<p>The file <code>/etc/sps/init</code> records which PID 1 was chosen. Known services (sshd, dbus, SDDM, NetworkManager, and others mapped by SPS) are enabled during <code>setup</code> unless you passed <code>--services no</code>. Later <code>sget install</code> of a mapped package enables it for that init too.</p>
+<table class="docs">
+<thead>
+<tr><th>Init</th><th>Enable a service</th></tr>
+</thead>
+<tbody>
+<tr><td>systemd</td><td><code>systemctl enable --now sshd</code> (unit names follow the package)</td></tr>
+<tr><td>OpenRC</td><td><code>rc-update add sshd default</code></td></tr>
+<tr><td>s6</td><td>symlink under <code>/etc/s6/enabled</code></td></tr>
+<tr><td>runit</td><td>symlink under <code>/etc/runit/runsvdir/default</code></td></tr>
+<tr><td>dinit</td><td>symlink under <code>/etc/dinit.d/boot.d</code></td></tr>
+<tr><td>Shepherd</td><td>Scheme files under <code>/etc/shepherd.d</code></td></tr>
+</tbody>
+</table>
+
+<h3>Next packages</h3>
+<pre class="block">src update
+sget install nano
+pkstat</pre>
+<p>Search the <a href="../../../../packages/">package browser</a> for names. Extra is where desktop, init, and most applications live. Core is the base system, toolchain pieces that exist as recipes, boot, filesystems, and networking.</p>
+
+<h3>Configuration files</h3>
+<p>Files under <code>etc</code> are preserved when you change them. On upgrade, SPS keeps the local file. If the new package also changed its copy, the new one is written beside it as <code>.sps-new</code>. SPS does not merge the two.</p>
+</main>
+</div>
+@@FOOTER@@
+</div>
+<script src="../../../../assets/docs.js?v=4c4f12c-20261019130111"></script>
+</body>
+</html>
diff --git a/site/docs/images/index.html b/site/docs/images/index.html
new file mode 100644
index 0000000..f702d12
--- /dev/null
+++ b/site/docs/images/index.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Live images - Splux Linux</title>
+<meta name="description" content="What is on sps-live-tty, sps-live-tty-slim, and sps-live-plasma.">
+<link rel="icon" href="../../../../assets/favicon.png" type="image/png">
+<link rel="stylesheet" href="../../../../assets/style.css">
+</head>
+<body>
+<a class="skip" href="#main">Skip to content</a>
+<div class="wrap wide">
+@@HEADER@@
+<div class="handbook">
+@@DOCSNAV@@
+<main id="main">
+<h2>Live images</h2>
+<hr class="rule">
+<p>Images are hybrid ISOs from <a href="https://github.com/RobertFlexx/SPS">RobertFlexx/SPS</a>. Filenames stay the same; the current tag is <a href="https://github.com/RobertFlexx/SPS/releases/latest">live-2026-09-06-1</a> (2026-09-06). Verify against <a href="https://github.com/RobertFlexx/SPS/releases/latest/download/SHA256SUMS">SHA256SUMS</a>.</p>
+<p>Every image includes SPS (<code>src</code>, <code>sget</code>, <code>mkpkg</code>, <code>pkin</code>, <code>setup</code>, <code>mkiso</code>, and the rest), <code>dialog</code>, disk tools, <code>dhcpcd</code>, <code>grub-install</code>, and <code>grub-mkconfig</code>. Live PID 1 is busybox init on published snapshots. <code>/bin/sh</code> is busybox. Login is <code>root</code> with an empty password.</p>
+
+<table class="docs">
+<thead>
+<tr><th></th><th>tty</th><th>slim</th><th>Plasma</th></tr>
+</thead>
+<tbody>
+<tr><td>File</td><td><code>sps-live-tty.iso</code></td><td><code>sps-live-tty-slim.iso</code></td><td><code>sps-live-plasma.iso</code></td></tr>
+<tr><td>Recipes</td><td>core and extra on the disc</td><td>none (git URLs in repos.conf)</td><td>core and extra on the disc</td></tr>
+<tr><td>Compiler</td><td>seed gcc, headers, startfiles</td><td>no</td><td>same as tty</td></tr>
+<tr><td>git / make / python / meson</td><td>yes</td><td>no</td><td>yes</td></tr>
+<tr><td>Kernel modules for the live kernel</td><td>yes</td><td>no</td><td>yes</td></tr>
+<tr><td>Source install with <code>setup</code> or <code>sget</code></td><td>yes</td><td>no</td><td>yes</td></tr>
+<tr><td>Session</td><td>console</td><td>console</td><td>Plasma / Wayland</td></tr>
+<tr><td>Use it for</td><td>install Splux</td><td>rescue, partition, network debug</td><td>install Splux from a graphical live session</td></tr>
+</tbody>
+</table>
+
+<div class="tabs" data-tabs>
+<div class="tablist" role="tablist" aria-label="Live image">
+<button type="button" role="tab" id="tab-img-tty" aria-controls="panel-img-tty" aria-selected="true" tabindex="0" data-hash="tty">tty</button>
+<button type="button" role="tab" id="tab-img-slim" aria-controls="panel-img-slim" aria-selected="false" tabindex="-1" data-hash="slim">slim</button>
+<button type="button" role="tab" id="tab-img-plasma" aria-controls="panel-img-plasma" aria-selected="false" tabindex="-1" data-hash="plasma">Plasma</button>
+</div>
+
+<section class="tabpanel" role="tabpanel" id="panel-img-tty" aria-labelledby="tab-img-tty">
+<h3>sps-live-tty.iso</h3>
+<p>This is the install disc. <code>make iso</code> copies sps-core and sps-extra into <code>/usr/src/sps/{core,extra}</code> and writes <code>dir</code> entries in <code>/etc/sps/repos.conf</code>. A host seed compiler, headers, glibc startfiles, and kernel modules come along so packages can be built offline.</p>
+<p>Seed tools include gcc, g++, make, cmake, ninja, meson, python3, perl, git, curl, wget, tar, xz, gzip, bzip2, zstd, nano, vim, pkg-config, and the binutils used to link. Partition tools, <code>dhcpcd</code>, <code>openssl</code>, <code>grub-install</code>, and <code>efibootmgr</code> (when the builder had it) are on this image too.</p>
+<p>Manual install: <a href="../../../../install/#manual">Install, Manual tab</a>. Guided: <a href="../../../../install/#setup">Install, setup tab</a>.</p>
+</section>
+
+<section class="tabpanel" role="tabpanel" id="panel-img-slim" aria-labelledby="tab-img-slim">
+<h3>sps-live-tty-slim.iso</h3>
+<p><code>make iso-slim</code> passes <code>--no-seed --no-modules</code> and does not copy core or extra. <code>repos.conf</code> falls back to git URLs. There is no gcc, no git, no make, no python, no meson, no recipes, and no live kernel modules.</p>
+<p>Busybox still provides <code>sh</code>, <code>vi</code>, <code>wget</code>, <code>udhcpc</code>, <code>ip</code>, <code>mount</code>, <code>chroot</code>, <code>tar</code>, <code>gzip</code>, <code>xz</code>, <code>passwd</code>, <code>sha256sum</code>, <code>ping</code>, and <code>modprobe</code>. Host copies of <code>dialog</code>, <code>lsblk</code>, <code>sfdisk</code>, <code>cfdisk</code>, <code>mkfs.ext4</code>, <code>mkfs.vfat</code>, <code>mkswap</code>, <code>dhcpcd</code>, <code>grub-install</code>, and <code>openssl</code> are still on the disc. There is no busybox <code>git</code> applet and no busybox <code>zstd</code> applet.</p>
+<p><code>setup</code> is installed (SPS is on every image) but it cannot complete a source install from slim. Full slim handbook: <a href="../../../../install/#slim">Install, slim tab</a>.</p>
+</section>
+
+<section class="tabpanel" role="tabpanel" id="panel-img-plasma" aria-labelledby="tab-img-plasma">
+<h3>sps-live-plasma.iso</h3>
+<p>Same installer, recipes, and seed compiler as tty, plus a host Plasma / Wayland stack. It needs a KMS device: virtio-gpu in QEMU, or a real GPU. NVIDIA on the live session is nouveau.</p>
+<p>Open Konsole and run <code>setup</code>, or follow the <a href="../../../../install/#manual">manual tty chapter</a>. The live graphical session is not the installed desktop. Installing Plasma still compiles Qt and KDE from source on the target.</p>
+</section>
+</div>
+
+<h3>Write a USB</h3>
+<pre class="block">dd if=sps-live-tty.iso of=/dev/sdX bs=4M status=progress conv=fsync</pre>
+<p>Replace <code>/dev/sdX</code> with the USB device, not a partition. That command erases the destination. Boot the "SPS Linux live (Splux)" entry.</p>
+<p>For QEMU, attach a writable second disk. The live image never runs <code>grub-install</code> on its own.</p>
+</main>
+</div>
+@@FOOTER@@
+</div>
+<script src="../../../../assets/live.js?v=4c4f12c-20261019130111" data-root="../../../../"></script>
+<script src="../../../../assets/docs.js?v=4c4f12c-20261019130111"></script>
+</body>
+</html>
diff --git a/site/docs/index.html b/site/docs/index.html
index 4dce92c..8bf2a3a 100644
--- a/site/docs/index.html
+++ b/site/docs/index.html
@@ -3,33 +3,73 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Documentation - Splux Linux</title>
-<meta name="description" content="Splux and SPS documentation.">
+<title>Handbook - Splux Linux</title>
+<meta name="description" content="Splux Linux handbook: live images, installation, and SPS.">
<link rel="icon" href="../../../../assets/favicon.png" type="image/png">
<link rel="stylesheet" href="../../../../assets/style.css">
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
-<div class="wrap">
+<div class="wrap wide">
@@HEADER@@
+<div class="handbook">
+@@DOCSNAV@@
<main id="main">
-<h2>Documentation</h2>
+<h2>Handbook</h2>
<hr class="rule">
+<p>This is the Splux Linux handbook. Splux is a source-based distribution. Packages are built on the machine that installs them, from recipes in <a href="https://github.com/RobertFlexx/sps-core">sps-core</a> and <a href="https://github.com/RobertFlexx/sps-extra">sps-extra</a>, using SPS.</p>
+<p>Live images are development snapshots, not a numbered stable release. Read the chapter that matches the ISO you booted.</p>
+
+<h3>Start here</h3>
+<table class="docs">
+<thead>
+<tr><th>Chapter</th><th>What it covers</th></tr>
+</thead>
+<tbody>
+<tr>
+<td><a href="../../../../docs/images/">Live images</a></td>
+<td>tty, slim, and Plasma: what is on each disc, and which one to download.</td>
+</tr>
+<tr>
+<td><a href="../../../../install/">Install</a></td>
+<td>Three paths in tabs: <code>setup</code>, a full manual install from the tty ISO without <code>setup</code>, and the slim image.</td>
+</tr>
+<tr>
+<td><a href="../../../../docs/sps/">SPS tools</a></td>
+<td><code>src</code>, <code>sget</code>, <code>mkpkg</code>, <code>pkin</code>, and the rest of the package system.</td>
+</tr>
+<tr>
+<td><a href="../../../../docs/first-boot/">After first boot</a></td>
+<td>Passwords, network, services, and the next packages.</td>
+</tr>
+</tbody>
+</table>
+
+<h3>Install paths</h3>
+<p>Use <a href="../../../../install/#setup">guided setup</a> on <code>sps-live-tty.iso</code> or <code>sps-live-plasma.iso</code> if you want dialog screens. Use the <a href="../../../../install/#manual">manual chapter</a> if you want the same work as shell commands, with only tools that exist on the tty disc. The <a href="../../../../install/#slim">slim chapter</a> is rescue, partitioning, and network debugging. Slim is not a source-install disc.</p>
+
+<h3>Architecture and status</h3>
+<p>Published images are x86_64 hybrid ISOs. Live PID 1 is busybox init with gettys on tty1 and ttyS0 (or systemd when the machine that built the ISO had it). The login is <code>root</code> with an empty password.</p>
+<p>SPS 1.0 is usable. Official recipe trees are still being built out. A console install compiles for a long time. A Plasma install compiles Qt and KDE and takes much longer.</p>
+
+<h3>Reference trees</h3>
<ul class="plain">
-<li><a href="../../../../install/">Installation</a></li>
-<li><a href="../../../../packages/">Package browser</a></li>
+<li><a href="../../../../packages/">Package browser</a> (1474 packages)</li>
<li><a href="https://github.com/RobertFlexx/SPS/blob/main/README.md">SPS README</a></li>
<li><a href="https://github.com/RobertFlexx/SPS/blob/main/DESIGN.md">SPS 1.0 formats and behavior</a></li>
+<li><a href="https://github.com/RobertFlexx/SPS/blob/main/man/setup.1">setup(1)</a></li>
<li><a href="https://github.com/RobertFlexx/SPS/blob/main/PACKAGE-MAINTAINER.md">Package maintainer guide</a></li>
-<li><a href="https://github.com/RobertFlexx/SPS/blob/main/MANIFESTO.md">SPS manifesto</a></li>
<li><a href="https://github.com/RobertFlexx/sps-core/blob/main/README.md">core collection</a></li>
<li><a href="https://github.com/RobertFlexx/sps-extra/blob/main/README.md">extra collection</a></li>
<li><a href="../../../../source/">Source repositories</a></li>
</ul>
-<p>SPS stores package definitions in ordinary Git repositories. The core tree contains the base system and toolchain. Extra contains packages outside the base installation.</p>
+
+<h3>Fastfetch</h3>
<p>Fastfetch is a native SPS package. On a Splux install it counts SPS packages in its Packages module and still reports Flatpak, Homebrew, Nix, and other managers when they are present. The system default is gray labels and a yellow P in the SPS logo. A user config in <code>~/.config/fastfetch/</code> overrides that default. Fastfetch is not started from shell profiles.</p>
</main>
+</div>
@@FOOTER@@
</div>
+<script src="../../../../assets/docs.js?v=4c4f12c-20261019130111"></script>
</body>
</html>
diff --git a/site/docs/sps/index.html b/site/docs/sps/index.html
new file mode 100644
index 0000000..b746272
--- /dev/null
+++ b/site/docs/sps/index.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>SPS tools - Splux Linux</title>
+<meta name="description" content="SPS package tools used on Splux: src, sget, mkpkg, pkin, and setup.">
+<link rel="icon" href="../../../../assets/favicon.png" type="image/png">
+<link rel="stylesheet" href="../../../../assets/style.css">
+</head>
+<body>
+<a class="skip" href="#main">Skip to content</a>
+<div class="wrap wide">
+@@HEADER@@
+<div class="handbook">
+@@DOCSNAV@@
+<main id="main">
+<h2>SPS tools</h2>
+<hr class="rule">
+<p>SPS is a set of small POSIX shell and AWK programs, not one large front end. Splux uses them for the installer, live images, and official collections. The same tools can manage a tree that is not Splux.</p>
+<p>On a live image they live on <code>PATH</code> under <code>/usr</code>. Package database, cache, and build directories are under <code>SPS_ROOT</code> (default <code>/</code>).</p>
+
+<table class="docs">
+<thead>
+<tr><th>Tool</th><th>Role</th></tr>
+</thead>
+<tbody>
+<tr><td><code>src</code></td><td>Repository handling. <code>src update</code> clones or indexes trees from <code>/etc/sps/repos.conf</code>.</td></tr>
+<tr><td><code>sget</code></td><td>Dependency-aware frontend. Resolves a graph, then calls <code>mkpkg</code> and <code>pkin</code>.</td></tr>
+<tr><td><code>mkpkg</code></td><td>Builds one recipe into a <code>.pkg.tar.zst</code> (or gz/xz when compression says so).</td></tr>
+<tr><td><code>pkin</code></td><td>Installs a built package into <code>SPS_ROOT</code>.</td></tr>
+<tr><td><code>pkdel</code></td><td>Removes an installed package.</td></tr>
+<tr><td><code>pkstat</code></td><td>Queries the installed database.</td></tr>
+<tr><td><code>pkcheck</code></td><td>Verifies files against recorded checksums.</td></tr>
+<tr><td><code>pkmark</code></td><td>Marks why a package is installed (explicit / as-needed).</td></tr>
+<tr><td><code>setup</code></td><td>Splux installer. Dialog screens, or the same choices from flags. Not required to use SPS.</td></tr>
+<tr><td><code>mkiso</code></td><td>Builds Splux live images. Maintainer tool.</td></tr>
+</tbody>
+</table>
+
+<h3>Configuration</h3>
+<p><code>/etc/sps/sps.conf</code> must exist before the first <code>sget</code>. Live images already have one. Default keys:</p>
+<pre class="block">db /var/lib/sps
+cache /var/cache/sps
+build /var/tmp/sps
+repo_root /usr/src/sps
+makejobs auto
+cflags -O2 -pipe
+cxxflags -O2 -pipe
+march native
+compression auto
+preserve etc</pre>
+<p>Paths in that file are relative to <code>SPS_ROOT</code> unless you override them with environment variables. For an install into <code>/mnt</code>:</p>
+<pre class="block">export SPS_ROOT=/mnt
+unset SPS_DB SPS_CACHE SPS_BUILD SPS_CONFIG SPS_REPOS_CONFIG SPS_REPO_ROOT</pre>
+<p>Leaving those unset is required so they resolve under the target, not under the live root.</p>
+
+<h3>Repositories</h3>
+<p><code>/etc/sps/repos.conf</code> lists trees. Higher priority wins.</p>
+<pre class="block">dir core /usr/src/sps/core 100
+dir extra /usr/src/sps/extra 80
+git core https://github.com/RobertFlexx/sps-core.git 100
+git extra https://github.com/RobertFlexx/sps-extra.git 80</pre>
+<p>On tty and Plasma images the live <code>repos.conf</code> uses <code>dir</code> entries pointing at the bundled trees. Slim images have no recipes, so they use the git lines. <code>src update</code> for a git repo needs <code>git</code>, which slim does not ship.</p>
+<p>During a target install, <code>setup</code> writes <code>dir</code> paths prefixed with the target (<code>/mnt/usr/src/sps/core</code>) so <code>src update</code> can index them from the live system, then rewrites them to <code>/usr/src/sps/...</code> for the booted machine. The <a href="../../../../install/#manual">manual install</a> does the same.</p>
+
+<h3>Install a package</h3>
+<pre class="block">src update
+sget install curl</pre>
+<p>That resolves dependencies, builds each recipe with the live compiler, and installs into <code>SPS_ROOT</code>. Builds take as long as compiling that software usually takes. Plasma graphs compile Qt and KDE.</p>
+
+<h3>Init packages</h3>
+<p>These conflict. <code>sget</code> will not install more than one. Write the choice to <code>$SPS_ROOT/etc/sps/init</code> before the first package so service hooks see it.</p>
+<table class="docs">
+<thead>
+<tr><th>File</th><th>Package</th><th>PID 1</th></tr>
+</thead>
+<tbody>
+<tr><td><code>systemd</code></td><td><code>init-systemd</code></td><td>systemd (udev, logind)</td></tr>
+<tr><td><code>openrc</code></td><td><code>init-openrc</code></td><td>OpenRC, eudev, elogind</td></tr>
+<tr><td><code>s6</code></td><td><code>init-s6</code></td><td>s6, eudev, elogind</td></tr>
+<tr><td><code>runit</code></td><td><code>init-runit</code></td><td>runit, eudev, elogind</td></tr>
+<tr><td><code>dinit</code></td><td><code>init-dinit</code></td><td>dinit, eudev, elogind</td></tr>
+<tr><td><code>shepherd</code></td><td><code>init-shepherd</code></td><td>GNU Shepherd, eudev, elogind, Guile</td></tr>
+<tr><td><code>none</code></td><td>(no init package)</td><td>the installed tree has no PID 1 from SPS</td></tr>
+</tbody>
+</table>
+<p>Init packages live in extra. A bootable console needs extra recipes on the disc (tty or Plasma), not slim.</p>
+
+<h3>Kernels</h3>
+<p><code>linux-desktop</code> is the Splux daily-driver config (DRM, NVMe, virtio, filesystems). It installs <code>/boot/vmlinuz-desktop-7.2.2</code>. <code>linux</code> is upstream defconfig and installs <code>/boot/vmlinuz-7.2.2</code>. Neither package runs <code>grub-install</code>. <code>none</code> will not boot a new disk.</p>
+
+<h3>Further reading</h3>
+<ul class="plain">
+<li><a href="https://github.com/RobertFlexx/SPS/blob/main/README.md">SPS README</a></li>
+<li><a href="https://github.com/RobertFlexx/SPS/blob/main/DESIGN.md">DESIGN.md</a></li>
+<li><a href="https://github.com/RobertFlexx/SPS/blob/main/PACKAGE-MAINTAINER.md">Recipe format</a></li>
+<li><a href="../../../../packages/">Package browser</a></li>
+</ul>
+</main>
+</div>
+@@FOOTER@@
+</div>
+<script src="../../../../assets/docs.js?v=4c4f12c-20261019130111"></script>
+</body>
+</html>
diff --git a/site/download/index.html b/site/download/index.html
index 2c45c8c..806be2d 100644
--- a/site/download/index.html
+++ b/site/download/index.html
@@ -22,11 +22,12 @@
<h2>Images</h2>
<hr class="rule">
<p><a href="https://github.com/RobertFlexx/SPS/releases/latest/download/sps-live-tty.iso">sps-live-tty.iso</a><br>
-Console live image with sps-core, sps-extra, and a seed compiler so <code>setup</code> can build packages.</p>
+Console live image with sps-core, sps-extra, and a seed compiler so <code>setup</code> or a manual source install can build packages. This is the install disc.</p>
<p><a href="https://github.com/RobertFlexx/SPS/releases/latest/download/sps-live-tty-slim.iso">sps-live-tty-slim.iso</a><br>
-Small console image without the seed compiler. <code>setup</code> needs the network to fetch recipes and a toolchain.</p>
+Small console image without recipes, git, or a compiler. Rescue, partitioning, and network debugging. Not a source-install disc. See the <a href="../../../../install/#slim">slim handbook</a>.</p>
<p><a href="https://github.com/RobertFlexx/SPS/releases/latest/download/sps-live-plasma.iso">sps-live-plasma.iso</a><br>
-Plasma/Wayland live session plus the same installer path. Needs a KMS device (virtio-gpu or a real GPU).</p>
+Plasma/Wayland live session plus the same installer path as tty. Needs a KMS device (virtio-gpu or a real GPU).</p>
+<p><a href="../../../../docs/images/">What is on each image</a> · <a href="../../../../install/">Install handbook</a></p>
<h2>Checksums</h2>
<hr class="rule">
<p><a href="https://github.com/RobertFlexx/SPS/releases/latest/download/SHA256SUMS">SHA256SUMS</a> is produced from the uploaded ISOs. Verify on the machine that downloads the image:</p>
diff --git a/site/index.html b/site/index.html
index 55b2761..df23376 100644
--- a/site/index.html
+++ b/site/index.html
@@ -34,13 +34,13 @@
<a href="https://github.com/RobertFlexx/SPS/releases/latest/download/sps-live-tty.iso">sps-live-tty.iso</a>
(console image with recipes and a compiler)<br>
<a href="https://github.com/RobertFlexx/SPS/releases/latest/download/sps-live-tty-slim.iso">sps-live-tty-slim.iso</a>
-(small console image; setup needs the network)<br>
+(rescue console; no compiler, no recipes)<br>
<a href="https://github.com/RobertFlexx/SPS/releases/latest/download/sps-live-plasma.iso">sps-live-plasma.iso</a>
(Plasma/Wayland live session)<br>
<a href="https://github.com/RobertFlexx/SPS/releases/latest/download/SHA256SUMS">SHA256SUMS</a><br>
<a href="https://github.com/RobertFlexx/SPS/releases/latest">release notes</a>
</p>
-<p class="note">These are development live snapshots, not a numbered stable distro release. Installation still compiles packages from source. A Plasma install takes a long time. See <a href="../../../../install/">install</a>.</p>
+<p class="note">These are development live snapshots, not a numbered stable distro release. Installation still compiles packages from source. A Plasma install takes a long time. See the <a href="../../../../install/">install handbook</a>.</p>
<h2 id="packages"><span class="num">[003]</span> Package system</h2>
<hr class="rule">
@@ -77,8 +77,9 @@ Desktop software, graphics, multimedia, development tools, and other packages. @
<h2 id="docs"><span class="num">[005]</span> Documentation</h2>
<hr class="rule">
-<p><a href="../../../../install/">Installation</a><br>
-<a href="../../../../docs/">Documentation index</a><br>
+<p><a href="../../../../docs/">Handbook</a><br>
+<a href="../../../../install/">Install</a> (setup, manual tty, slim)<br>
+<a href="../../../../docs/images/">Live images</a><br>
<a href="https://github.com/RobertFlexx/SPS/blob/main/README.md">SPS README</a><br>
<a href="https://github.com/RobertFlexx/SPS/blob/main/DESIGN.md">SPS 1.0 formats</a></p>
diff --git a/site/install/index.html b/site/install/index.html
index 8a8b0d0..0c19273 100644
--- a/site/install/index.html
+++ b/site/install/index.html
@@ -4,42 +4,419 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Install - Splux Linux</title>
-<meta name="description" content="How to boot a Splux live image and run setup.">
+<meta name="description" content="Install Splux: guided setup, a full manual tty install without setup, and the slim image.">
<link rel="icon" href="../../../../assets/favicon.png" type="image/png">
<link rel="stylesheet" href="../../../../assets/style.css">
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
-<div class="wrap">
+<div class="wrap wide">
@@HEADER@@
+<div class="handbook">
+@@DOCSNAV@@
<main id="main">
<h2>Install</h2>
<hr class="rule">
-<p>The installation procedure is still being finalized. The path that exists today is: boot a live ISO, mount a target filesystem, and run <code>setup</code>.</p>
-<p><code>setup</code> is the Splux installer. It is not a generic SPS or LFS installer. It uses dialog screens, or the same choices from flags for scripts.</p>
-<h2>1. Download and verify</h2>
-<hr class="rule">
-<p>Get an image from <a href="../../../../download/">download</a>. For a source install use <code>sps-live-tty.iso</code>, not the slim image. Check it against <a href="https://github.com/RobertFlexx/SPS/releases/latest/download/SHA256SUMS">SHA256SUMS</a>.</p>
-<h2>2. Write the image</h2>
-<hr class="rule">
+<p>Splux is installed from a live ISO. Packages are compiled on that live system into a target root. Pick a tab. Hash URLs stay on the method: <code>#setup</code>, <code>#manual</code>, <code>#slim</code>.</p>
+<ul class="local-toc">
+<li><a href="#setup">Guided setup</a> on tty or Plasma</li>
+<li><a href="#manual">Manual install</a> from the tty ISO, without <code>setup</code></li>
+<li><a href="#slim">Slim image</a> (rescue, not a source install)</li>
+</ul>
+<div class="callout">
+<p><strong>Which ISO.</strong> Source install needs <code>sps-live-tty.iso</code> or <code>sps-live-plasma.iso</code>. Those discs carry sps-core, sps-extra, and a seed compiler. <code>sps-live-tty-slim.iso</code> does not. Compare images in the <a href="../../../../docs/images/">live images</a> chapter.</p>
+</div>
+
+<div class="tabs" data-tabs>
+<div class="tablist" role="tablist" aria-label="Install method">
+<button type="button" role="tab" id="tab-setup" aria-controls="panel-setup" aria-selected="true" tabindex="0" data-hash="setup">setup</button>
+<button type="button" role="tab" id="tab-manual" aria-controls="panel-manual" aria-selected="false" tabindex="-1" data-hash="manual">Manual (tty)</button>
+<button type="button" role="tab" id="tab-slim" aria-controls="panel-slim" aria-selected="false" tabindex="-1" data-hash="slim">Slim ISO</button>
+</div>
+
+<section class="tabpanel" role="tabpanel" id="panel-setup" aria-labelledby="tab-setup">
+<h3>Guided setup</h3>
+<p><code>setup</code> is the Splux installer. It is not a generic SPS or LFS installer. Dialog screens collect the same choices you can pass as flags. It never guesses a disk for <code>grub-install</code>.</p>
+
+<h4>1. Download and verify</h4>
+<p>Get <a href="../../../../download/">sps-live-tty.iso</a> (or the Plasma image). Check it on the machine that downloaded it:</p>
+<pre class="block">sha256sum -c SHA256SUMS</pre>
+<p>Current published tag: <a href="https://github.com/RobertFlexx/SPS/releases/latest">live-2026-09-06-1</a> (2026-09-06). Signatures are not published yet.</p>
+
+<h4>2. Write the image</h4>
<pre class="block">dd if=sps-live-tty.iso of=/dev/sdX bs=4M status=progress conv=fsync</pre>
<p>Replace <code>/dev/sdX</code> with the USB device. That command erases the destination.</p>
-<h2>3. Boot and target disk</h2>
-<hr class="rule">
-<p>Boot the "SPS Linux live (Splux)" entry. The live system comes up on the console (or Plasma on the Plasma image). For QEMU, give the guest a writable second disk in addition to the CD. The live image never runs <code>grub-install</code> on its own.</p>
-<h2>4. Run setup</h2>
-<hr class="rule">
-<pre class="block">setup
-setup --plan --profile plasma-desktop --target /mnt --user alex
-setup --non-interactive --profile minimal --target /mnt --hostname darkstar</pre>
-<p>Profiles are <code>minimal</code>, <code>server</code>, <code>plasma-desktop</code>, and <code>plasma-full</code>. Init is a choice: systemd (default) or OpenRC. Those packages conflict. Guided partitioning is optional. <code>grub-install</code> still needs <code>--install-bootloader</code> and <code>--disk</code>.</p>
-<p>The installer writes hostname, timezone, keymap, and a first user, copies bundled recipe trees when present, runs <code>src update</code>, and <code>sget install</code>. Packages are built from source on the target. A Plasma install compiles Qt and KDE and takes a long time.</p>
-<h2>More</h2>
-<hr class="rule">
-<p><a href="https://github.com/RobertFlexx/SPS/blob/main/README.md">SPS README</a> and <a href="https://github.com/RobertFlexx/SPS/blob/main/man/setup.1">setup(1)</a> are the current command references.</p>
+
+<h4>3. Boot</h4>
+<p>Boot the "SPS Linux live (Splux)" entry. Login is <code>root</code> with an empty password. On Plasma, open Konsole. Live PATH often omits <code>/sbin</code>:</p>
+<pre class="block">export PATH=/sbin:/usr/sbin:/usr/bin:/bin:$PATH</pre>
+<p>For QEMU, give the guest a writable second disk. The live image never runs <code>grub-install</code> on its own.</p>
+
+<h4>4. Run setup</h4>
+<pre class="block">setup</pre>
+<p>Profiles: <code>minimal</code>, <code>server</code>, <code>plasma-desktop</code>, <code>plasma-full</code>. Init: systemd, OpenRC, s6, runit, dinit, or Shepherd. Those packages conflict. Guided partitioning waits until the last confirmation. Kernel <code>none</code> is the interactive default for a console profile; a disk that must boot itself needs <code>linux-desktop</code> or <code>linux</code>.</p>
+<p>Non-interactive examples:</p>
+<pre class="block">setup --plan --profile plasma-desktop --target /mnt --user alex
+
+setup --non-interactive \
+ --profile minimal \
+ --target /mnt \
+ --hostname darkstar \
+ --timezone UTC \
+ --keymap us \
+ --locale C.UTF-8 \
+ --init systemd \
+ --kernel linux-desktop \
+ --partition efi-swap-root \
+ --disk /dev/sda \
+ --format yes \
+ --bootloader grub \
+ --install-bootloader \
+ --user alex</pre>
+<p><code>--plan</code> and <code>--non-interactive</code> never touch a disk unless you pass <code>--disk</code> and <code>--format yes</code> together. <code>grub-install</code> still needs <code>--install-bootloader</code> and <code>--disk</code>.</p>
+
+<h4>Profiles and kernels</h4>
+<table class="docs">
+<thead>
+<tr><th>Profile</th><th>Packages (plus init and kernel you select)</th></tr>
+</thead>
+<tbody>
+<tr><td><code>minimal</code></td><td><code>base-system dialog splux-base fastfetch</code></td></tr>
+<tr><td><code>server</code></td><td>minimal, plus <code>openssh gnupg rsync sudo</code></td></tr>
+<tr><td><code>plasma-desktop</code></td><td>minimal, plus Plasma, SDDM, Mesa, PipeWire, portals</td></tr>
+<tr><td><code>plasma-full</code></td><td>plasma-desktop, plus <code>kde-apps firefox flatpak</code></td></tr>
+</tbody>
+</table>
+<p><code>setup --list-profiles</code> and <code>setup --list-sets</code> print the catalog. Optional sets cover SSH, printing, Flatpak, NVIDIA, firmware, and more. <code>--kernel</code> is <code>none</code>, <code>linux</code>, <code>linux-desktop</code>, or <code>custom</code>.</p>
+
+<h4>Partition layouts</h4>
+<table class="docs">
+<thead>
+<tr><th>Layout</th><th>GPT map</th></tr>
+</thead>
+<tbody>
+<tr><td><code>efi-root</code></td><td>512MiB ESP, rest root</td></tr>
+<tr><td><code>efi-swap-root</code></td><td>ESP, swap (default 8GiB), rest root</td></tr>
+<tr><td><code>efi-swap-root-home</code></td><td>ESP, swap, 48GiB root, rest home</td></tr>
+<tr><td><code>bios-root</code></td><td>1MiB BIOS boot, rest root</td></tr>
+<tr><td><code>existing</code> / <code>manage</code></td><td>you mount or name partitions</td></tr>
+</tbody>
+</table>
+<p>Formats match the installer: ESP is FAT32 labeled <code>SPS_EFI</code>, root is ext4 labeled <code>sps-root</code>, swap is labeled <code>sps-swap</code>. <code>/etc/fstab</code> is written from <code>blkid</code> UUIDs when setup partitioned the disk.</p>
+
+<h4>What setup does</h4>
+<p>It writes hostname, timezone, keymap, locale, and <code>/etc/sps/init</code>, copies bundled recipe trees when they exist, writes <code>sps.conf</code>, runs <code>src update</code>, then <code>sget install</code>. Users land after packages so <code>filesystem</code>'s passwd file is already there. If you passed <code>--install-bootloader</code>, it runs live <code>grub-install</code> (EFI removable <code>EFI/BOOT/BOOTX64.EFI</code>, then NVRAM via <code>efibootmgr</code> when that binary exists; BIOS uses <code>i386-pc</code>). It does not run <code>grub-mkconfig</code>. See <code>/root/sps-bootloader.txt</code> on the target.</p>
+<p>A Plasma install compiles Qt and KDE and takes a long time. See <a href="https://github.com/RobertFlexx/SPS/blob/main/man/setup.1">setup(1)</a> for every flag.</p>
+</section>
+
+<section class="tabpanel" role="tabpanel" id="panel-manual" aria-labelledby="tab-manual">
+<h3>Manual install (no setup)</h3>
+<p>This is the same work <code>setup</code> does, written as shell commands. It uses tools that exist on <code>sps-live-tty.iso</code> (the Plasma ISO has the same installer stack). Do not follow this chapter on slim.</p>
+<div class="callout">
+<p><strong>Tools on the tty disc.</strong> SPS (<code>src</code>, <code>sget</code>, <code>mkpkg</code>, <code>pkin</code>, and the rest), gcc/g++, make, cmake, ninja, meson, python3, perl, git, curl, wget, tar, xz, gzip, zstd, nano, vim, <code>dialog</code>, <code>openssl</code>, <code>lsblk</code>, <code>blkid</code>, <code>sfdisk</code>, <code>cfdisk</code>, <code>fdisk</code>, <code>wipefs</code>, <code>mkfs.ext4</code>, <code>mkfs.vfat</code>, <code>mkswap</code>, <code>partprobe</code>, <code>dhcpcd</code>, <code>grub-install</code>, <code>grub-mkconfig</code>, <code>efibootmgr</code> (when the builder had it), plus busybox <code>sh</code>, <code>mount</code>, <code>chroot</code>, <code>passwd</code>. Recipes are at <code>/usr/src/sps/core</code> and <code>/usr/src/sps/extra</code>.</p>
+</div>
+
+<ol class="steps">
+<li>
+<p><strong>Boot tty and fix PATH.</strong> Login is <code>root</code> with an empty password.</p>
+<pre class="block">export PATH=/sbin:/usr/sbin:/usr/bin:/bin:$PATH
+lsblk -o NAME,SIZE,TYPE,TRAN,MODEL</pre>
+<p>Pick a writable disk that is not the live USB. On QEMU that is the second disk. Optional DHCP: <code>dhcpcd</code>.</p>
+</li>
+<li>
+<p><strong>Partition and format.</strong> Use the firmware tabs. Names: <code>/dev/sda1</code> versus <code>/dev/nvme0n1p1</code>. These layouts match <code>setup</code>.</p>
+<div class="tabs" data-tabs>
+<div class="tablist" role="tablist" aria-label="Firmware">
+<button type="button" role="tab" id="tab-uefi" aria-controls="panel-uefi" aria-selected="true" tabindex="0" data-hash="uefi">UEFI (GPT)</button>
+<button type="button" role="tab" id="tab-bios" aria-controls="panel-bios" aria-selected="false" tabindex="-1" data-hash="bios">BIOS (GPT)</button>
+</div>
+<section class="tabpanel" role="tabpanel" id="panel-uefi" aria-labelledby="tab-uefi">
+<p>ESP (type EFI System), swap, then Linux root. Default swap size is 8GiB, same as setup.</p>
+<pre class="block">DISK=/dev/sda
+wipefs -a "$DISK"
+sfdisk --wipe always --wipe-partitions always "$DISK" <<'EOF'
+label: gpt
+size=512MiB, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=EFI
+size=8GiB, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, name=swap
+type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name=root
+EOF
+partprobe "$DISK"
+
+EFI=${DISK}1
+SWAP=${DISK}2
+ROOT=${DISK}3
+# nvme: EFI=${DISK}p1 and so on
+
+mkfs.vfat -F 32 -n SPS_EFI "$EFI"
+mkswap -L sps-swap "$SWAP"
+mkfs.ext4 -F -L sps-root "$ROOT"
+
+mount "$ROOT" /mnt
+mount -o remount,rw,exec,suid,dev /mnt
+mkdir -p /mnt/boot/efi
+mount "$EFI" /mnt/boot/efi
+swapon "$SWAP"</pre>
+<p>No swap: omit the swap line in the sfdisk script (setup layout <code>efi-root</code>) and skip <code>mkswap</code> / <code>swapon</code>. Separate <code>/home</code>: setup layout <code>efi-swap-root-home</code> uses a 48GiB root then the rest as home; format that partition ext4 labeled <code>sps-home</code> and mount it on <code>/mnt/home</code>.</p>
+<p><code>cfdisk "$DISK"</code> is on the disc if you want a TUI instead of a script. Types: EFI System, Linux swap, Linux filesystem.</p>
+</section>
+<section class="tabpanel" role="tabpanel" id="panel-bios" aria-labelledby="tab-bios">
+<p>1MiB BIOS boot partition (GRUB GPT), then Linux root. No ESP.</p>
+<pre class="block">DISK=/dev/sda
+wipefs -a "$DISK"
+sfdisk --wipe always --wipe-partitions always "$DISK" <<'EOF'
+label: gpt
+size=1MiB, type=21686148-6449-6E6F-744E-656564454649, name=BIOS
+type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name=root
+EOF
+partprobe "$DISK"
+
+ROOT=${DISK}2
+mkfs.ext4 -F -L sps-root "$ROOT"
+mount "$ROOT" /mnt
+mount -o remount,rw,exec,suid,dev /mnt</pre>
+<p>The remount matters. Autoconf runs conftests on this mount; a <code>noexec</code> or <code>nodev</code> root fails those builds.</p>
+</section>
+</div>
+</li>
+<li>
+<p><strong>Target directories and sps.conf.</strong> <code>sget</code> will not run without a config.</p>
+<pre class="block">mkdir -p /mnt/etc/sps /mnt/usr/src/sps /mnt/root
+if [ -f /etc/sps/live ] && [ -f /etc/sps/sps.conf ]; then
+ cp /etc/sps/sps.conf /mnt/etc/sps/sps.conf
+else
+ cat > /mnt/etc/sps/sps.conf <<'EOF'
+db /var/lib/sps
+cache /var/cache/sps
+build /var/tmp/sps
+repo_root /usr/src/sps
+makejobs auto
+cflags -O2 -pipe
+cxxflags -O2 -pipe
+march native
+compression auto
+preserve etc
+EOF
+fi</pre>
+</li>
+<li>
+<p><strong>Copy bundled recipes.</strong> tty and Plasma already have them. Copying avoids a git clone during <code>src update</code>.</p>
+<pre class="block">cp -a /usr/src/sps/core/. /mnt/usr/src/sps/core/
+cp -a /usr/src/sps/extra/. /mnt/usr/src/sps/extra/
+rm -rf /mnt/usr/src/sps/core/.git /mnt/usr/src/sps/extra/.git
+
+cat > /mnt/etc/sps/repos.conf <<'EOF'
+dir core /mnt/usr/src/sps/core 100
+dir extra /mnt/usr/src/sps/extra 80
+EOF</pre>
+<p>Those paths are for indexing from the live system. After packages you rewrite them to <code>/usr/src/sps/...</code> for the booted machine.</p>
+</li>
+<li>
+<p><strong>Point SPS at /mnt and record init.</strong> Write <code>/etc/sps/init</code> before the first package so service hooks see it. The init packages conflict.</p>
+<pre class="block">export SPS_ROOT=/mnt
+unset SPS_DB SPS_CACHE SPS_BUILD SPS_CONFIG SPS_REPOS_CONFIG SPS_REPO_ROOT</pre>
+<div class="tabs" data-tabs>
+<div class="tablist" role="tablist" aria-label="Init system">
+<button type="button" role="tab" id="tab-systemd" aria-controls="panel-init-systemd" aria-selected="true" tabindex="0" data-hash="systemd">systemd</button>
+<button type="button" role="tab" id="tab-openrc" aria-controls="panel-init-openrc" aria-selected="false" tabindex="-1" data-hash="openrc">OpenRC</button>
+<button type="button" role="tab" id="tab-s6" aria-controls="panel-init-s6" aria-selected="false" tabindex="-1" data-hash="s6">s6</button>
+<button type="button" role="tab" id="tab-runit" aria-controls="panel-init-runit" aria-selected="false" tabindex="-1" data-hash="runit">runit</button>
+<button type="button" role="tab" id="tab-dinit" aria-controls="panel-init-dinit" aria-selected="false" tabindex="-1" data-hash="dinit">dinit</button>
+<button type="button" role="tab" id="tab-shepherd" aria-controls="panel-init-shepherd" aria-selected="false" tabindex="-1" data-hash="shepherd">Shepherd</button>
+</div>
+<section class="tabpanel" role="tabpanel" id="panel-init-systemd" aria-labelledby="tab-systemd">
+<pre class="block">printf '%s\n' systemd > /mnt/etc/sps/init
+# later: sget install init-systemd</pre>
+<p>PID 1 is systemd, with udev and logind. Interactive <code>setup</code> defaults to systemd when the live disc recorded that init.</p>
+</section>
+<section class="tabpanel" role="tabpanel" id="panel-init-openrc" aria-labelledby="tab-openrc">
+<pre class="block">printf '%s\n' openrc > /mnt/etc/sps/init
+# later: sget install init-openrc</pre>
+<p>OpenRC plus eudev and elogind. Enable services with <code>rc-update</code> after boot.</p>
+</section>
+<section class="tabpanel" role="tabpanel" id="panel-init-s6" aria-labelledby="tab-s6">
+<pre class="block">printf '%s\n' s6 > /mnt/etc/sps/init
+# later: sget install init-s6</pre>
+<p>s6 plus eudev and elogind. Enabled longruns live in <code>/etc/s6/enabled</code>.</p>
+</section>
+<section class="tabpanel" role="tabpanel" id="panel-init-runit" aria-labelledby="tab-runit">
+<pre class="block">printf '%s\n' runit > /mnt/etc/sps/init
+# later: sget install init-runit</pre>
+<p>runit plus eudev and elogind. Enable with a symlink in <code>/etc/runit/runsvdir/default</code>.</p>
+</section>
+<section class="tabpanel" role="tabpanel" id="panel-init-dinit" aria-labelledby="tab-dinit">
+<pre class="block">printf '%s\n' dinit > /mnt/etc/sps/init
+# later: sget install init-dinit</pre>
+<p>dinit plus eudev and elogind. Enable by linking into <code>/etc/dinit.d/boot.d</code>.</p>
+</section>
+<section class="tabpanel" role="tabpanel" id="panel-init-shepherd" aria-labelledby="tab-shepherd">
+<pre class="block">printf '%s\n' shepherd > /mnt/etc/sps/init
+# later: sget install init-shepherd</pre>
+<p>GNU Shepherd plus eudev, elogind, and Guile. Services are Scheme files under <code>/etc/shepherd.d</code>.</p>
+</section>
+</div>
+</li>
+<li>
+<p><strong>Probe the live compiler, then install packages.</strong> Fail here rather than inside the first autoconf package.</p>
+<pre class="block">printf '%s\n' 'int main(void){return 0;}' | gcc -x c - -o /tmp/sps-cc-probe
+rm -f /tmp/sps-cc-probe
+meson --version
+
+src update
+
+sget install base-system dialog splux-base fastfetch
+sget install init-systemd
+sget install linux-desktop
+sget install grub</pre>
+<p>Replace <code>init-systemd</code> with the package from the init tab. <code>base-system</code> is a metapackage (shell, coreutils, curl, git, e2fsprogs, busybox, shadow, tzdata, and the rest of the essential userland). <code>splux-base</code> is branding and os-release. <code>linux-desktop</code> is the Splux daily-driver kernel and installs <code>/boot/vmlinuz-desktop-7.2.2</code>. <code>linux</code> is upstream defconfig (<code>/boot/vmlinuz-7.2.2</code>). Skipping a kernel package will not boot a new disk.</p>
+<p>Server add-ons: <code>sget install openssh gnupg rsync sudo</code>. Plasma add-ons are the plasma-desktop profile set (Plasma, SDDM, Mesa, PipeWire, portals) and compile for a long time.</p>
+</li>
+<li>
+<p><strong>Rewrite repos.conf for the booted system.</strong></p>
+<pre class="block">cat > /mnt/etc/sps/repos.conf <<'EOF'
+dir core /usr/src/sps/core 100
+dir extra /usr/src/sps/extra 80
+EOF</pre>
+</li>
+<li>
+<p><strong>Hostname, locale, keymap, timezone, fstab.</strong> Do this after packages so <code>filesystem</code> has already laid down passwd and a stub fstab. <code>tzdata</code> is in <code>base-system</code>; the live disc also has <code>/usr/share/zoneinfo</code> from the seed.</p>
+<pre class="block">printf '%s\n' darkstar > /mnt/etc/hostname
+printf '%s\n' UTC > /mnt/etc/timezone
+printf 'KEYMAP=%s\n' us > /mnt/etc/vconsole.conf
+printf 'keymap %s\n' us > /mnt/etc/sps/keymap
+printf 'LANG=%s\n' C.UTF-8 > /mnt/etc/locale.conf
+cp /usr/share/zoneinfo/UTC /mnt/etc/localtime
+
+ROOT_UUID=$(blkid -s UUID -o value "$ROOT")
+{
+ printf '%s\n' '# /etc/fstab'
+ printf 'UUID=%s / ext4 defaults 1 1\n' "$ROOT_UUID"
+ if [ -n "$EFI" ]; then
+ printf 'UUID=%s /boot/efi vfat umask=0077 0 2\n' \
+ "$(blkid -s UUID -o value "$EFI")"
+ fi
+ if [ -n "$SWAP" ]; then
+ printf 'UUID=%s none swap defaults 0 0\n' \
+ "$(blkid -s UUID -o value "$SWAP")"
+ fi
+} > /mnt/etc/fstab</pre>
+</li>
+<li>
+<p><strong>Users.</strong> After <code>shadow</code> / <code>filesystem</code> exist. setup uses uid 1000 and groups wheel, audio, video, input, kvm, users. Busybox <code>passwd</code> can set a hash in the live tree; <code>openssl passwd -6</code> is on the disc too.</p>
+<pre class="block"># example: lock root until you set a password, add user alex
+# edit /mnt/etc/passwd /mnt/etc/group /mnt/etc/shadow, or:
+mkdir -p /mnt/home/alex
+printf '%s\n' 'alex:x:1000:1000:alex:/home/alex:/bin/sh' >> /mnt/etc/passwd
+printf '%s\n' 'alex:x:1000:' >> /mnt/etc/group
+printf '%s\n' 'alex:!:0:0:99999:7:::' >> /mnt/etc/shadow
+chown -R 1000:1000 /mnt/home/alex
+chmod 0750 /mnt/home/alex
+# add alex to wheel,audio,video,input,kvm,users in /mnt/etc/group
+chroot /mnt passwd root
+chroot /mnt passwd alex</pre>
+<p>A full chroot for <code>passwd</code> needs a working target userland (after <code>base-system</code>). If chroot cannot run the target <code>passwd</code>, set hashes from the live system with <code>openssl passwd -6</code> and put the hash in the shadow field.</p>
+</li>
+<li>
+<p><strong>Bootloader.</strong> Explicit, same as setup. Run it after <code>grub</code> and a kernel are installed. Use the live <code>grub-install</code> pointed at the mounted tree.</p>
+<p>UEFI (writes <code>\EFI\BOOT\BOOTX64.EFI</code>, no NVRAM required):</p>
+<pre class="block">grub-install --target=x86_64-efi \
+ --efi-directory=/mnt/boot/efi \
+ --boot-directory=/mnt/boot \
+ --removable --no-nvram \
+ "$DISK"
+if command -v efibootmgr >/dev/null 2>&1; then
+ grub-install --target=x86_64-efi \
+ --efi-directory=/mnt/boot/efi \
+ --bootloader-id=SPS \
+ --boot-directory=/mnt/boot \
+ "$DISK" || printf '%s\n' 'NVRAM update failed; removable path is in place'
+fi</pre>
+<p>BIOS:</p>
+<pre class="block">grub-install --target=i386-pc --boot-directory=/mnt/boot "$DISK"</pre>
+<p><code>setup</code> does not run <code>grub-mkconfig</code>. After the kernel is in <code>/mnt/boot</code>:</p>
+<pre class="block">mount --bind /dev /mnt/dev
+mount --bind /proc /mnt/proc
+mount --bind /sys /mnt/sys
+chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg</pre>
+</li>
+<li>
+<p><strong>Unmount and reboot.</strong></p>
+<pre class="block">umount /mnt/dev /mnt/proc /mnt/sys 2>/dev/null || :
+swapoff -a
+umount /mnt/boot/efi 2>/dev/null || :
+umount /mnt
+reboot</pre>
+<p>Continue in <a href="../../../../docs/first-boot/">After first boot</a>.</p>
+</li>
+</ol>
+
+<h4>Time and limits</h4>
+<p>Source install compiles on the live compiler into <code>SPS_ROOT</code>. <code>linux-desktop</code> is a kernel build. Plasma is Qt and KDE. Leave it running.</p>
+<p>Packages are linked against the live C library. There is no glibc recipe in sps-core yet. That is the same for <code>setup</code> and this chapter. Splux is still under testing; a first boot needs the kernel, an init, GRUB, and a userland that can actually start.</p>
+</section>
+
+<section class="tabpanel" role="tabpanel" id="panel-slim" aria-labelledby="tab-slim">
+<h3>Slim ISO</h3>
+<p><code>sps-live-tty-slim.iso</code> is the small console image from <code>make iso-slim</code> (<code>--no-seed --no-modules</code>, no <code>--core</code>, no <code>--extra</code>). It is a rescue and disk tool. It is not a Splux source-install disc.</p>
+<div class="callout">
+<p><strong>What slim cannot do.</strong> No gcc, no make, no git, no python, no meson, no recipes, no live kernel modules. <code>repos.conf</code> lists git URLs, but <code>git</code> is not on the image, so <code>src update</code> cannot clone sps-core. <code>setup</code> is present because SPS is installed on every live root; it still cannot build packages here.</p>
+</div>
+
+<h4>What is on the disc</h4>
+<table class="docs">
+<thead>
+<tr><th>Class</th><th>Commands</th></tr>
+</thead>
+<tbody>
+<tr><td>SPS</td><td><code>src sget mkpkg pkin pkdel pkstat pkcheck pkmark setup mkiso</code></td></tr>
+<tr><td>Disk</td><td><code>lsblk blkid sfdisk cfdisk fdisk wipefs mkfs.ext4 mke2fs mkfs.vfat mkswap partprobe</code></td></tr>
+<tr><td>Boot</td><td><code>grub-install grub-mkconfig</code>, and <code>efibootmgr</code> when the builder had it</td></tr>
+<tr><td>Network</td><td>host <code>dhcpcd</code>; busybox <code>udhcpc</code>, <code>wget</code>, <code>ip</code>, <code>ifconfig</code>, <code>ping</code></td></tr>
+<tr><td>Crypto / linker</td><td><code>openssl ldd ldconfig</code></td></tr>
+<tr><td>Busybox</td><td><code>sh vi mount umount chroot tar gzip xz passwd sha256sum modprobe fdisk mkswap</code> and the rest of the applet list. No <code>git</code>. No <code>zstd</code> applet. No <code>nano</code> / <code>vim</code>.</td></tr>
+</tbody>
+</table>
+
+<h4>Boot and PATH</h4>
+<pre class="block">export PATH=/sbin:/usr/sbin:/usr/bin:/bin:$PATH
+lsblk -o NAME,SIZE,TYPE,TRAN,MODEL</pre>
+<p>Login is <code>root</code> with an empty password. Edit files with busybox <code>vi</code>.</p>
+
+<h4>Network</h4>
+<pre class="block">ip link
+dhcpcd
+# if dhcpcd is missing or the interface needs busybox:
+udhcpc -i eth0
+ping -c 1 1.1.1.1
+wget -O - https://splux.robertflexx.dev/ > /dev/null</pre>
+<p><code>wget</code> can fetch SHA256SUMS or another ISO. It cannot replace git for <code>src update</code>.</p>
+
+<h4>Partition and filesystems</h4>
+<p>The same <code>sfdisk</code> / <code>mkfs.ext4</code> / <code>mkfs.vfat</code> / <code>mkswap</code> commands as the <a href="#manual">manual tty chapter</a> work here. That only prepares disks. It does not install Splux. Typical rescue:</p>
+<pre class="block">lsblk
+# mount an existing Splux or other Linux root
+mount /dev/sda2 /mnt
+mount /dev/sda1 /mnt/boot/efi
+mount --bind /dev /mnt/dev
+mount --bind /proc /mnt/proc
+mount --bind /sys /mnt/sys
+chroot /mnt /bin/sh</pre>
+<p>Reinstall GRUB from slim onto a disk that already has a <code>/boot</code> tree, using live <code>grub-install</code> the same way the tty chapter does. You still need a kernel and userland on that disk already.</p>
+
+<h4>Why setup fails here</h4>
+<p><code>setup</code> copies recipes from <code>/usr/src/sps/{core,extra}</code> when those trees exist. On slim they do not, so it would try git clones. <code>git</code> is missing. Even with recipes, the live gcc probe fails because there is no compiler. Use tty or Plasma for install.</p>
+<p>Download the install disc from another machine, or from slim if you have network and a place to write it, then reboot into tty:</p>
+<pre class="block"># on a machine that can download:
+# sps-live-tty.iso from https://github.com/RobertFlexx/SPS/releases/latest</pre>
+<p>Full install: <a href="#setup">setup tab</a> or <a href="#manual">manual tab</a>.</p>
+</section>
+</div>
+
+<p class="note">Splux is under active development. These snapshots track installer and live-session work. They are not a numbered stable release.</p>
</main>
+</div>
@@FOOTER@@
</div>
<script src="../../../../assets/live.js?v=4c4f12c-20261019130111" data-root="../../../../"></script>
+<script src="../../../../assets/docs.js?v=4c4f12c-20261019130111"></script>
</body>
</html>
diff --git a/tools/build-site.sh b/tools/build-site.sh
index d13be05..ea15d4c 100755
--- a/tools/build-site.sh
+++ b/tools/build-site.sh
@@ -44,7 +44,8 @@ fi
rm -rf "$OUT"
mkdir -p "$OUT/assets" "$OUT/data" "$OUT/download" "$OUT/packages" \
- "$OUT/install" "$OUT/docs" "$OUT/source" "$OUT/news"
+ "$OUT/install" "$OUT/docs" "$OUT/docs/images" "$OUT/docs/sps" \
+ "$OUT/docs/first-boot" "$OUT/source" "$OUT/news"
cp -a site/assets/. "$OUT/assets/"
if [ -f CNAME ]; then
@@ -85,6 +86,32 @@ write_footer() {
EOF
}
+write_docs_nav() {
+ root=$1
+ cur=$2
+ printf '%s\n' '<nav class="docs-side" aria-label="Handbook">'
+ printf '%s\n' '<p class="docs-kicker">Handbook</p>'
+ printf '%s\n' '<ul class="docs-toc">'
+ set -- \
+ overview "${root}docs/" "Overview" \
+ images "${root}docs/images/" "Live images" \
+ install "${root}install/" "Install" \
+ sps "${root}docs/sps/" "SPS tools" \
+ firstboot "${root}docs/first-boot/" "After first boot"
+ while [ "$#" -ge 3 ]
+ do
+ if [ "$cur" = "$1" ]; then
+ printf '<li><a href="%s" aria-current="page">%s</a></li>\n' \
+ "$2" "$3"
+ else
+ printf '<li><a href="%s">%s</a></li>\n' "$2" "$3"
+ fi
+ shift 3
+ done
+ printf '%s\n' '</ul>'
+ printf '%s\n' '</nav>'
+}
+
tmp=$(mktemp -d "${TMPDIR:-/tmp}/splux-site.XXXXXX") || exit 1
trap 'rm -rf "$tmp"' 0 HUP INT TERM
@@ -196,7 +223,7 @@ if command -v gh >/dev/null 2>&1; then
fi
if [ "$tag" = unknown ] || [ -z "$tag" ]; then
tag=latest
- date=see GitHub
+ date="see GitHub"
published=
fi
generated=$(date -u '+%Y-%m-%d %H:%M UTC' 2>/dev/null || date)
@@ -263,12 +290,15 @@ subst() {
src=$1
dest=$2
root=$3
+ docscurrent=${4-}
write_header "$root" >"$tmp/header.html"
write_footer "$root" >"$tmp/footer.html"
+ write_docs_nav "$root" "$docscurrent" >"$tmp/docsnav.html"
mkdir -p "$(dirname "$dest")"
awk -f tools/subst.awk \
-v headerfile="$tmp/header.html" \
-v footerfile="$tmp/footer.html" \
+ -v docsnavfile="$tmp/docsnav.html" \
-v rowsfile="$tmp/rows.html" \
-v newsfile="$tmp/news.html" \
-v brieffile="$tmp/news-brief.html" \
@@ -291,8 +321,11 @@ subst() {
subst site/index.html "$OUT/index.html" "./"
subst site/download/index.html "$OUT/download/index.html" "../"
subst site/packages/index.html "$OUT/packages/index.html" "../"
-subst site/install/index.html "$OUT/install/index.html" "../"
-subst site/docs/index.html "$OUT/docs/index.html" "../"
+subst site/install/index.html "$OUT/install/index.html" "../" install
+subst site/docs/index.html "$OUT/docs/index.html" "../" overview
+subst site/docs/images/index.html "$OUT/docs/images/index.html" "../../" images
+subst site/docs/sps/index.html "$OUT/docs/sps/index.html" "../../" sps
+subst site/docs/first-boot/index.html "$OUT/docs/first-boot/index.html" "../../" firstboot
subst site/source/index.html "$OUT/source/index.html" "../"
awk -f tools/news.awk -v mode=html -v page=1 -v per="$news_per" \
diff --git a/tools/subst.awk b/tools/subst.awk
index 1507da0..9ab025f 100644
--- a/tools/subst.awk
+++ b/tools/subst.awk
@@ -63,6 +63,11 @@ $0 == "@@PAGER@@" {
next
}
+$0 == "@@DOCSNAV@@" {
+ dump_file(docsnavfile)
+ next
+}
+
{
gsub(/../../../..//, root)
gsub(/live-2026-09-06-1/, tag)