diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81f7dfca..af7a20ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- feat: automated documentation pipeline with Mintlify sync
- feat: CI job to auto-refresh doc screenshots on every develop push
+- docs: bootstrap user-facing documentation from codebase audit — added configuration, stack management, editor, multi-node, and alerts & notifications pages; updated introduction, quickstart, and features overview; restructured mint.json navigation with Getting Started / Features / Reference / Operations groups
+- docs: add Tier 2 feature pages — dashboard, resources hub, app store, global observability, and host console
+- docs: add Tier 3 reference and operations pages — settings reference, troubleshooting, and backup & restore
### Fixed
- fix(ci): YAML syntax error in update-screenshots `if:` condition (`!` tag and `: ` in plain scalar); wrapped in `${{ }}`
diff --git a/docs/features/alerts-notifications.mdx b/docs/features/alerts-notifications.mdx
new file mode 100644
index 00000000..b1900516
--- /dev/null
+++ b/docs/features/alerts-notifications.mdx
@@ -0,0 +1,95 @@
+---
+title: Alerts & Notifications
+description: Set threshold-based alerts on container metrics and route them to Discord, Slack, or any webhook.
+---
+
+Sencho can watch your containers for resource anomalies and notify you when thresholds are breached. Alerts are defined per stack, and notifications are delivered through external agents you configure.
+
+
+
+
+
+## How alerts work
+
+Sencho's monitoring service samples container metrics every minute and evaluates all defined alert rules. When a rule's condition holds true for the configured duration, a notification is dispatched. A cooldown period prevents the same alert from firing repeatedly.
+
+## Setting up a notification agent
+
+At least one agent must be enabled before alerts can be delivered. Go to **Settings → Notifications**.
+
+### Discord
+
+1. In Discord, go to your server's **Settings → Integrations → Webhooks**
+2. Click **New Webhook**, choose a channel, and copy the webhook URL
+3. In Sencho, open **Settings → Notifications → Discord**, paste the URL, enable the toggle, and click **Save**
+4. Click **Test** to send a test message
+
+### Slack
+
+1. In Slack, go to **api.slack.com/apps**, create an app, and add the **Incoming Webhooks** feature
+2. Activate it and copy the generated webhook URL for your chosen channel
+3. In Sencho, open **Settings → Notifications → Slack**, paste the URL, enable the toggle, and click **Save**
+
+### Generic Webhook
+
+Any HTTP endpoint that accepts a POST with a JSON body can receive Sencho alerts. Go to **Settings → Notifications → Webhook**, enter the URL, and click **Save**.
+
+The payload format is:
+```json
+{
+ "level": "warning",
+ "message": "cpu_percent exceeded 90% for 5 minutes on stack my-app",
+ "timestamp": "2026-03-22T10:00:00.000Z"
+}
+```
+
+## Creating stack alerts
+
+Stack alerts are configured per-stack. Right-click a stack in the sidebar (or click the **⋮** button) and select **Alerts**.
+
+
+
+
+
+The alerts sheet shows existing rules for the stack and a form to create new ones.
+
+### Alert fields
+
+| Field | Description |
+|-------|-------------|
+| **Metric** | The container metric to watch |
+| **Operator** | Comparison operator: `>`, `>=`, `<`, `<=`, `==` |
+| **Threshold** | The value to compare against |
+| **Duration (minutes)** | How long the condition must hold before firing |
+| **Cooldown (minutes)** | Minimum time between repeated notifications for this rule |
+
+### Available metrics
+
+| Metric | Unit | Description |
+|--------|------|-------------|
+| `cpu_percent` | % | CPU usage relative to total host cores |
+| `memory_mb` | MB | RSS memory used by the container |
+| `memory_percent` | % | Memory used as a fraction of the host total |
+| `net_rx` | bytes/s | Inbound network rate |
+| `net_tx` | bytes/s | Outbound network rate |
+| `restart_count` | count | Number of times the container has restarted |
+
+### Example: alert on high CPU
+
+To alert when any container in a stack uses more than 80% CPU for over 5 consecutive minutes, with a 30-minute cooldown:
+
+| Field | Value |
+|-------|-------|
+| Metric | `cpu_percent` |
+| Operator | `>` |
+| Threshold | `80` |
+| Duration | `5` |
+| Cooldown | `30` |
+
+## Notification history
+
+All dispatched notifications appear in the **notification bell** (top-right of the nav bar). Click it to see recent alerts with their level, message, and timestamp. Mark all as read or clear individual entries from there.
+
+
+ Notifications only reach external agents (Discord, Slack, Webhook) if at least one agent is enabled. Dashboard notifications appear regardless.
+
diff --git a/docs/features/app-store.mdx b/docs/features/app-store.mdx
new file mode 100644
index 00000000..ebb90546
--- /dev/null
+++ b/docs/features/app-store.mdx
@@ -0,0 +1,71 @@
+---
+title: App Store
+description: Browse and deploy pre-configured application templates in one click.
+---
+
+The **App Store** tab lets you browse a curated catalogue of Docker Compose templates and deploy any of them as a new stack with environment-specific configuration — no YAML required.
+
+
+
+
+
+## Browsing templates
+
+Templates are loaded from a remote registry (configurable in **Settings → App Store**). The default registry provides 190+ self-hosted application templates.
+
+**Search:** Type in the search bar to filter templates by name or description in real-time.
+
+**Categories:** Click any category pill to narrow the list:
+`Automation` · `Books` · `Development` · `Documentation` · `Downloaders` · `Media` · `Monitoring` · `Networking` · `Other` · `Product`
+
+Each template card shows:
+- Application logo
+- Name and short description
+- Category tags
+- Links to the GitHub repo and documentation (where available)
+
+## Deploying a template
+
+Click any template card to open the **deployment sheet** on the right side of the screen. Fill in the fields and click **Deploy**.
+
+### Stack name
+
+Pre-filled with the template name in lowercase. You can change it — the same [naming rules](/features/stack-management#creating-a-stack) apply (lowercase, hyphens, no spaces).
+
+### Environment variables
+
+Each template declares the variables it needs. Sencho pre-fills sensible defaults where available (e.g. `PUID=1000`, `PGID=1000`, `TZ` from your browser locale).
+
+Edit any value before deploying. You can also click **Custom Env** to add arbitrary key-value pairs not defined by the template.
+
+### Volumes
+
+For each container mount point, enter the **host path** where that data should be stored. Suggested defaults (e.g. `./config`, `./data`) are shown as placeholders.
+
+
+ Relative paths like `./config` are resolved relative to the stack directory inside your `COMPOSE_DIR`. Absolute paths map directly to the host filesystem.
+
+
+### Ports
+
+For each exposed port, edit the **host port** (left side). The container port (right side) is fixed by the template and cannot be changed here — edit the compose file after deployment if needed.
+
+### What happens on Deploy
+
+1. Sencho creates a new stack directory in `COMPOSE_DIR`
+2. Writes the generated `compose.yaml` and `.env` file
+3. Runs `docker compose up -d`
+4. On success: switches you to the Editor view for that stack
+5. On failure: rolls back by running `docker compose down` and deleting the stack directory
+
+A toast notification confirms success or shows the error message.
+
+## Custom template registry
+
+By default Sencho uses the LinuxServer.io template registry. To use your own:
+
+1. Open **Settings → App Store**
+2. Enter your registry URL (must serve a JSON array of template objects in Portainer v2 format)
+3. Click **Save**
+
+To force a refresh of the cached templates, click **Refresh Cache** in the same settings panel.
diff --git a/docs/features/dashboard.mdx b/docs/features/dashboard.mdx
new file mode 100644
index 00000000..2869e351
--- /dev/null
+++ b/docs/features/dashboard.mdx
@@ -0,0 +1,60 @@
+---
+title: Dashboard
+description: Real-time system stats, historical metrics, and a quick-start converter for your host machine.
+---
+
+The **Home** tab is the first thing you see after logging in. It shows a live snapshot of your host's health alongside container activity across all stacks.
+
+
+
+
+
+## Container stats
+
+The top row summarises container state at a glance:
+
+| Card | What it shows |
+|------|---------------|
+| **Active Containers** | Running containers — broken down as `N managed · N external` |
+| **Exited Containers** | Stopped or crashed containers |
+| **Docker Network** | Current inbound/outbound network throughput across all containers |
+
+**Managed** means the container belongs to a stack in your `COMPOSE_DIR`. **External** means it exists on the Docker host but was started outside Sencho (e.g. by another Compose project or `docker run`).
+
+## System stats
+
+The second row shows host-level resource usage, polled every few seconds:
+
+| Card | What it shows |
+|------|---------------|
+| **Host CPU** | Current CPU usage percentage and core count |
+| **Host RAM** | Used / total memory in GB and percentage |
+| **Host Disk** | Used / total disk space for the primary mount point |
+
+When any value exceeds configured thresholds (set in **Settings → System Limits**), the card changes colour as a visual warning.
+
+## Historical metrics charts
+
+Two area charts display time-series data sampled at one-minute intervals, retained for up to 24 hours (configurable in **Settings → Developer**):
+
+- **Normalized CPU Usage** — total CPU percentage across all managed containers, normalised over all host cores
+- **Normalized RAM Usage** — total memory allocated by managed containers, in GB
+
+The x-axis shows time labels. Hover over a data point to see the exact value at that moment.
+
+
+ Charts only show data from the moment Sencho started. If you just installed Sencho, they will be mostly empty until metrics accumulate.
+
+
+## Convert `docker run` to Compose
+
+The bottom panel provides a quick converter: paste any `docker run` command and Sencho transforms it into a valid `docker-compose.yaml` snippet.
+
+```bash
+# Example input
+docker run -d --name myapp -p 8080:80 -e TZ=UTC -v /data:/app/data nginx:latest
+```
+
+Click **Convert** and the output YAML appears ready to copy. You can then create a new stack and paste it into the editor.
+
+This is useful when migrating existing containers to managed Compose stacks without having to write YAML by hand.
diff --git a/docs/features/editor.mdx b/docs/features/editor.mdx
new file mode 100644
index 00000000..4ebfbd4e
--- /dev/null
+++ b/docs/features/editor.mdx
@@ -0,0 +1,64 @@
+---
+title: Editor
+description: Edit compose files and environment variables, and manage containers directly from the dashboard.
+---
+
+Selecting a stack opens the editor view — a split-pane layout with container management on the left and a full Monaco code editor on the right.
+
+
+
+
+
+## Compose file editor
+
+The right panel shows your `compose.yaml` with full syntax highlighting. By default the editor is **read-only** to prevent accidental changes.
+
+Click **Edit** to enter edit mode. Your changes are unsaved until you explicitly save them.
+
+### Save options
+
+| Button | What it does |
+|--------|--------------|
+| **Save** | Writes the file to disk. Does not restart any containers. |
+| **Save & Deploy** | Writes the file, then immediately runs `docker compose up -d`. Use this to apply compose changes in one step. |
+| **Discard** | Reverts the editor to the last saved version. Unsaved changes are lost. |
+
+## Environment file editor
+
+Click the **.env** tab to switch to the environment file editor. If your `compose.yaml` references multiple env files (via `env_file:`), a dropdown lets you select which file to edit.
+
+The `.env` editor has the same save/discard controls as the compose editor. Changes take effect the next time the stack is deployed.
+
+
+ Sencho reads the `env_file:` paths from your `compose.yaml` to discover available env files. If no `env_file:` is declared, a default `.env` in the stack directory is used.
+
+
+## Container panel
+
+The left panel lists all containers that belong to the selected stack. Each container shows:
+
+- **Status badge** — `running`, `exited`, `starting`, or `unhealthy`
+- **Live stats** — CPU %, RAM usage, and network I/O updated every 1–2 seconds
+- **Port mappings** — host:container port pairs (if any)
+
+### Container actions
+
+Each container row has three action buttons:
+
+| Button | What it does |
+|--------|--------------|
+| **Logs** (external link icon) | Opens a live log stream modal for that container |
+| **Terminal** (terminal icon) | Opens an interactive bash session inside the container |
+| **Copy ID** | Copies the container ID to the clipboard |
+
+### Log viewer
+
+The log viewer streams output from a single container in real-time using Server-Sent Events. Logs auto-scroll to the bottom as new lines arrive. Close the modal to stop the stream.
+
+### Container terminal (exec)
+
+The terminal modal gives you an interactive bash shell inside the running container — equivalent to `docker exec -it bash`. It uses a full xterm.js emulator with color support and tab completion.
+
+
+ The container terminal requires the container to have `bash` (or `sh`) installed. Minimal images (e.g. Alpine-based) may need `sh` instead.
+
diff --git a/docs/features/global-observability.mdx b/docs/features/global-observability.mdx
new file mode 100644
index 00000000..4e396666
--- /dev/null
+++ b/docs/features/global-observability.mdx
@@ -0,0 +1,58 @@
+---
+title: Global Observability
+description: A unified, searchable log stream from every container across all your stacks.
+---
+
+The **Logs** tab aggregates output from all running containers into a single scrollable view. Instead of tailing logs one container at a time, you see everything in one place — with filtering to focus on what matters.
+
+
+
+
+
+## Log format
+
+Each line shows:
+
+- **Timestamp** — when the log line was emitted
+- **Stack name** — the Compose stack the container belongs to (colour-coded)
+- **Container name** — the specific container
+- **Level** — `INFO`, `WARN`, or `ERROR` (where detectable)
+- **Message** — the raw log output
+
+## Streaming modes
+
+Sencho supports two modes for fetching logs, switchable via the **Developer mode** toggle:
+
+| Mode | How it works | Best for |
+|------|-------------|----------|
+| **Standard** (default) | Polls all containers every N seconds (configurable in Settings → Developer) | General use; lower overhead |
+| **Developer mode** | Server-Sent Events stream; logs arrive as they are emitted | Debugging; watching a specific event in real-time |
+
+The default polling interval is 5 seconds. You can change it to 1, 3, 5, or 10 seconds in **Settings → Developer → Global Logs Refresh Rate**.
+
+## Filtering logs
+
+Use the controls above the log panel to narrow what you see:
+
+| Control | What it does |
+|---------|-------------|
+| **Stack filter** | Multi-select dropdown — show only logs from chosen stacks |
+| **Stream** | `ALL` / `STDOUT` / `STDERR` — filter by output stream |
+| **Search** | Full-text filter on the message field (case-insensitive) |
+
+Filters combine — you can show only `STDERR` from a specific stack while searching for a keyword.
+
+## Controls
+
+| Button | What it does |
+|--------|-------------|
+| **Clear** | Clears the current log buffer in the UI (does not delete logs from Docker) |
+| **Auto-scroll** toggle | When enabled, the view scrolls to the bottom as new lines arrive |
+
+## Capacity limits
+
+To avoid browser memory issues, the log view keeps a maximum of **2,000 entries** in memory at a time. Older entries are dropped as new ones arrive. For deeper investigation, use the [per-container log viewer](/features/editor#log-viewer) in the Editor tab, or `docker compose logs` directly from the [Host Console](/features/host-console).
+
+
+ Log retention on the backend is controlled by **Settings → Developer → Log Retention Days** (default: 30 days). This affects historical logs stored in Sencho's database, not the live stream.
+
diff --git a/docs/features/host-console.mdx b/docs/features/host-console.mdx
new file mode 100644
index 00000000..6108b2e3
--- /dev/null
+++ b/docs/features/host-console.mdx
@@ -0,0 +1,54 @@
+---
+title: Host Console
+description: An interactive terminal on your host OS, directly in the browser — no SSH required.
+---
+
+The **Console** tab opens a full interactive terminal session on the machine running Sencho. It behaves exactly like an SSH session, but without needing an SSH server, client, or key management.
+
+
+
+
+
+## What it is
+
+The host console spawns a real PTY (pseudo-terminal) process on the Sencho host using `node-pty`. Your keystrokes are sent over a WebSocket and the terminal output is streamed back in real-time. The terminal emulator is [xterm.js](https://xtermjs.org/), the same engine used by VS Code's built-in terminal.
+
+Features:
+- Full colour and cursor support
+- Tab completion (via the host shell)
+- Scrollback buffer (10,000 lines)
+- Automatic terminal resizing when you resize the browser window
+- Copy and paste
+
+## Opening the console
+
+Click **Console** in the top navigation bar. The session starts immediately in the stack's working directory if a stack is selected, otherwise in the `COMPOSE_DIR` root.
+
+The header shows the connection status (**Connected** in green) and which node the console is attached to.
+
+Click **Close Console** to end the session and terminate the shell process on the host.
+
+## Shell type
+
+The shell depends on the host OS:
+- **Linux/macOS hosts:** `bash` or `sh`
+- **Windows hosts (Docker Desktop):** PowerShell (as shown in the screenshot — the console opens inside the Sencho container's Windows environment)
+
+## Security model
+
+The host console has a stricter authentication requirement than other features:
+
+- Requires a valid **browser session** (httpOnly cookie). Node-proxy tokens used for multi-node communication are explicitly blocked.
+- Each session is issued a short-lived **console token** (60-second TTL) before the WebSocket is established.
+- Because the console gives full shell access to the host, you should secure your Sencho instance with HTTPS and a strong password if it is exposed to a network.
+
+
+ The host console provides unrestricted shell access to the machine running Sencho. Do not expose Sencho on a public network without HTTPS and strong authentication.
+
+
+## Common uses
+
+- Inspecting files in your `COMPOSE_DIR` without leaving the browser
+- Running `docker compose logs --follow` or `docker ps` directly
+- Editing files with `nano` or `vim` for quick fixes
+- Running maintenance scripts or one-off commands on the host
diff --git a/docs/features/multi-node.mdx b/docs/features/multi-node.mdx
new file mode 100644
index 00000000..17d44373
--- /dev/null
+++ b/docs/features/multi-node.mdx
@@ -0,0 +1,80 @@
+---
+title: Multi-Node Management
+description: Connect multiple Sencho instances and manage all your servers from a single dashboard.
+---
+
+Sencho's multi-node feature lets you manage Docker Compose stacks on multiple servers — all from the same browser tab. Each server runs its own Sencho instance, and your primary instance acts as a transparent proxy to the others.
+
+
+
+
+
+## How it works
+
+There is no central server. Each Sencho instance manages its own host independently. When you select a remote node, your browser's API calls are proxied through your local Sencho instance to the remote one, authenticated by a long-lived Bearer token. No SSH. No shared Docker sockets.
+
+## The local node
+
+Your primary Sencho installation is always listed as **Local**. It is the default node, marked with a star, and cannot be deleted. All operations on the local node run directly against the host's Docker socket.
+
+## Adding a remote node
+
+### Step 1: Generate a token on the remote machine
+
+On the **remote** Sencho instance (the server you want to add), open **Settings → Nodes** and click **Generate Token**. Copy the generated token — you'll only see it once.
+
+
+ The token is a long-lived JWT scoped to `node_proxy`. Anyone with this token can fully control that Sencho instance, so treat it like a password.
+
+
+### Step 2: Add the node on your primary instance
+
+On your **primary** Sencho instance, open **Settings → Nodes** and click **+ Add Node**. Fill in:
+
+| Field | Description |
+|-------|-------------|
+| **Name** | A display name (e.g. `prod-server`, `media-box`) |
+| **Type** | Select **Remote** |
+| **Sencho API URL** | The full HTTP/HTTPS URL of the remote instance (e.g. `http://192.168.1.20:3001`) |
+| **API Token** | The token you generated in Step 1 |
+
+Click **Create**. Sencho immediately tests the connection and shows the result.
+
+### Step 3: Verify connectivity
+
+A successful connection shows the remote node as **Online** with a green badge. If it shows **Offline** or **Unknown**, check:
+- The remote Sencho instance is running and reachable from your primary host
+- The API URL is correct (include the port if non-standard)
+- The token was copied correctly without extra whitespace
+
+Click the **wifi icon** (test connection) on any node row at any time to re-check status.
+
+## The 1:1 path rule for remote nodes
+
+The Compose directory path matters on remote nodes too. When you register a remote node, its `COMPOSE_DIR` is whatever that remote instance was configured with. Make sure the remote Sencho's `COMPOSE_DIR` follows the [1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule) on that remote host.
+
+## Switching between nodes
+
+The **node switcher** dropdown in the top-left of the sidebar shows the currently active node. Click it to switch to any registered node. All views — dashboard stats, stack list, editor, resources, logs — immediately reflect the selected node.
+
+
+
+
+
+Node status indicators:
+
+| Indicator | Meaning |
+|-----------|---------|
+| Green dot | Node is reachable and responding |
+| Red dot | Node is unreachable |
+| Gray dot | Status not yet checked |
+
+## Editing and deleting nodes
+
+Click the **pencil icon** on any remote node row to edit its name, URL, or token. Click the **trash icon** to remove it. The local node cannot be edited or deleted.
+
+## Security considerations
+
+- Node tokens grant full control over the remote Sencho instance. Rotate them if compromised via Settings → Nodes → Generate Token (the old token is invalidated).
+- Use HTTPS between instances in production to prevent token interception.
+- The host console and container exec terminals are blocked for node-proxy tokens — interactive shell access always requires a real browser session on that instance.
diff --git a/docs/features/overview.mdx b/docs/features/overview.mdx
index 5aba4f55..04fc698d 100644
--- a/docs/features/overview.mdx
+++ b/docs/features/overview.mdx
@@ -5,15 +5,23 @@ description: A high-level tour of everything Sencho can do.
## Stack management
-Deploy, start, stop, restart, and remove Docker Compose stacks through a point-and-click interface. Edit `docker-compose.yml` files directly in the built-in Monaco editor.
+Deploy, start, stop, restart, and remove Docker Compose stacks through a point-and-click interface. Edit `compose.yaml` and `.env` files directly in the built-in Monaco editor with syntax highlighting. [Learn more →](/features/stack-management)
+
+## Editor
+
+Full in-browser code editor for your Compose and environment files. Toggle edit mode, save to disk, or save and deploy in one step. Per-container live stats and an interactive bash exec terminal live alongside the editor. [Learn more →](/features/editor)
## Multi-node support
-Add remote Sencho instances as nodes. All dashboard operations — stack management, logs, stats — work identically whether you're targeting your local machine or a server on the other side of the world.
+Add remote Sencho instances as nodes. All dashboard operations — stack management, logs, stats — work identically whether you're targeting your local machine or a server on the other side of the world. Uses a transparent HTTP proxy model; no SSH or shared Docker sockets required. [Learn more →](/features/multi-node)
## Real-time logs & stats
-Stream container logs and resource metrics (CPU, memory, network I/O) live in the browser via WebSocket connections.
+Stream container logs and resource metrics (CPU, memory, network I/O) live in the browser via WebSocket and Server-Sent Events connections. The Home dashboard shows historical CPU and RAM charts over the last 24 hours.
+
+## Global observability
+
+The **Logs** view aggregates output from all containers across all stacks into a single scrollable stream. Filter by stack, log level (stdout/stderr), or search for keywords. Switch to developer mode for real-time SSE streaming.
## Resources hub
@@ -23,10 +31,18 @@ View and manage all Docker images, volumes, and networks. Resources are classifi
|-------|---------|
| **Managed** | Owned by a Sencho stack |
| **External** | Part of another Compose project |
-| **Unused / System** | Reclaimable or Docker-internal |
+| **Unused / Reclaimable** | Safe to prune |
Run scoped prune operations to clean up Sencho-managed resources only, or target all Docker resources when needed.
-## Notifications & alerts
+## App Store
-Configure threshold-based alerts for CPU and memory usage. Notifications surface in the dashboard and can be dismissed or cleared in bulk.
+Browse 190+ pre-configured application templates. Filter by category (Media, Automation, Development, etc.), configure environment variables, volumes, and ports, and deploy with a single click.
+
+## Host console
+
+Open an interactive terminal on the host OS directly in the browser — full xterm.js emulation with color support. No SSH client required.
+
+## Alerts & notifications
+
+Configure threshold-based alerts (CPU, memory, network, restart count) per stack. Route notifications to Discord, Slack, or any generic webhook endpoint. [Learn more →](/features/alerts-notifications)
diff --git a/docs/features/resources.mdx b/docs/features/resources.mdx
new file mode 100644
index 00000000..96c305c0
--- /dev/null
+++ b/docs/features/resources.mdx
@@ -0,0 +1,75 @@
+---
+title: Resources Hub
+description: Browse, filter, and clean up Docker images, volumes, networks, and unmanaged containers.
+---
+
+The **Resources** tab gives you a full view of everything Docker is storing on your host, broken down by type and ownership.
+
+
+
+
+
+## Docker disk footprint
+
+The stacked bar at the top visualises how your Docker disk usage is distributed:
+
+| Segment | Meaning |
+|---------|---------|
+| **Sencho Managed** (green) | Images used by stacks in your `COMPOSE_DIR` |
+| **External Projects** (orange) | Images used by Docker projects outside Sencho |
+| **Reclaimable** (gray) | Unused images and dangling layers safe to delete |
+
+Click any segment to automatically filter the tabs below to that category.
+
+## Quick Clean panel
+
+Four prune buttons let you reclaim disk space immediately. By default they operate on **Sencho-managed resources only** — they will not touch external Docker projects.
+
+| Button | What it removes |
+|--------|----------------|
+| **Prune Unused Images** | Images with no running containers in Sencho stacks |
+| **Prune Unused Volumes** | Volumes not attached to any Sencho container |
+| **Prune Dead Networks** | Networks not connected to any Sencho container |
+| **Purge Unmanaged Containers** | Containers Sencho doesn't recognise (started outside it) |
+
+Each button has a **⋮ More options** menu that lets you target **all Docker resources** instead of Sencho-only. Use this carefully — it can affect other Compose projects running on the same host.
+
+A confirmation dialog appears before any destructive operation, showing a summary of what will be removed.
+
+## Resource tabs
+
+### Images
+
+Lists all Docker images on the host with their ID, repository tag, size, and status.
+
+**Filter buttons:** `All` · `Managed` · `External`
+
+**Status badges:**
+- `In Use` + stack name — image is actively used by a running container
+- `Unused` — image has no running containers; safe to delete
+
+Click the trash icon on any row to delete an individual image. Sencho will warn you if the image is in use.
+
+### Volumes
+
+Lists all Docker volumes. Columns: name, driver, mount point, size, and managed status.
+
+**Filter buttons:** `All` · `Managed` · `External`
+
+
+ Deleting a volume is permanent. Any data stored in it will be lost. Always back up important volume data before pruning.
+
+
+### Networks
+
+Lists all Docker networks. Columns: name, driver, scope (`local`, `global`, `swarm`), and managed status.
+
+**Filter buttons:** `All` · `Managed` · `External` · `System`
+
+System networks (like `bridge`, `host`, `none`) are shown but cannot be deleted.
+
+### Unmanaged
+
+Lists containers running on the host that are not part of any Sencho-managed stack. This includes containers started with `docker run`, or Compose projects outside your `COMPOSE_DIR`.
+
+This view is useful for identifying orphaned containers after a failed deployment or after moving stacks in and out of `COMPOSE_DIR`.
diff --git a/docs/features/stack-management.mdx b/docs/features/stack-management.mdx
new file mode 100644
index 00000000..c91c5661
--- /dev/null
+++ b/docs/features/stack-management.mdx
@@ -0,0 +1,71 @@
+---
+title: Stack Management
+description: Create, deploy, control, and remove Docker Compose stacks.
+---
+
+A **stack** in Sencho is a Docker Compose project: a directory inside your `COMPOSE_DIR` that contains at least a `compose.yaml` (or `docker-compose.yml`) file. Sencho automatically discovers every subdirectory as a stack.
+
+
+
+
+
+## Creating a stack
+
+Click **Create Stack** in the left sidebar. Enter a name and click **Create**.
+
+**Naming rules:**
+- Lowercase letters, numbers, and hyphens only (e.g. `my-app`, `nextcloud`)
+- No spaces or special characters
+- Must be unique — duplicates are rejected
+
+Sencho creates a new directory inside `COMPOSE_DIR` with a blank `compose.yaml` file. You'll land in the editor automatically.
+
+## The stack list
+
+All discovered stacks appear in the left sidebar. Each shows a color-coded status dot:
+
+| Color | Meaning |
+|-------|---------|
+| Green | All containers running |
+| Red | One or more containers exited |
+| Gray | No containers / status unknown |
+
+Use the **search box** above the list to filter stacks by name.
+
+## Deploying a stack
+
+Select a stack and click **Deploy** in the stack header. This runs `docker compose up -d` — pulling images if needed and creating or recreating containers.
+
+
+
+
+
+## Controlling a running stack
+
+The stack header exposes four actions:
+
+| Button | Command | What it does |
+|--------|---------|--------------|
+| **Stop** | `docker compose stop` | Stops containers without removing them. State is preserved. |
+| **Restart** | `docker compose restart` | Restarts all containers in the stack. |
+| **Update** | `docker compose pull` + `up -d` | Pulls the latest image tags and recreates containers. |
+| **Delete** | `down` + removes files | Stops and removes containers, then deletes the stack directory. |
+
+
+ **Delete** is irreversible. It removes the stack directory — including `compose.yaml`, `.env`, and any bind-mounted files stored there. Back up important files before deleting.
+
+
+## Stack context menu
+
+Right-click or use the **⋮** button on any stack in the sidebar to access:
+
+
+
+
+
+- **Alerts** — configure metric-based alerting rules for this stack
+- **Check for updates** — manually trigger an image update check
+
+## Converting a `docker run` command
+
+If you have an existing `docker run` command and want to turn it into a Compose stack, go to the **Home** tab and paste it into the "Convert Docker Run to Compose" field. Sencho converts it to YAML that you can save as a new stack.
diff --git a/docs/getting-started/configuration.mdx b/docs/getting-started/configuration.mdx
new file mode 100644
index 00000000..751e4ffc
--- /dev/null
+++ b/docs/getting-started/configuration.mdx
@@ -0,0 +1,161 @@
+---
+title: Configuration
+description: Environment variables, volume mounts, and the 1:1 path rule.
+---
+
+Sencho is configured entirely through environment variables and Docker volume mounts. There is no config file to edit inside the container.
+
+## Required environment variables
+
+| Variable | Description |
+|----------|-------------|
+| `JWT_SECRET` | Secret key used to sign session tokens. Use a long, random string (32+ characters). Changing this invalidates all active sessions. |
+| `COMPOSE_DIR` | Absolute path to the directory that contains your Compose stacks. Every subdirectory inside becomes a stack in Sencho. |
+
+## Optional environment variables
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `PORT` | `3000` | Port the Sencho HTTP server listens on. |
+| `DATA_DIR` | `/app/data` | Directory where Sencho stores its SQLite database, node registry, and cached metrics. |
+| `NODE_ENV` | `production` | Set automatically in the Docker image. Only change this for local development. |
+
+## Required volume mounts
+
+### Docker socket
+
+Sencho needs access to the Docker daemon to manage containers:
+
+```yaml
+volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+```
+
+### Data directory
+
+Sencho's database persists all your settings, nodes, alerts, and metrics history. Mount a named volume or host path so it survives container restarts:
+
+```yaml
+volumes:
+ - ./sencho-data:/app/data
+```
+
+
+ Without a persistent data mount, Sencho will lose all configuration — including registered nodes, alerts, and settings — every time the container restarts.
+
+
+### Compose directory — the 1:1 path rule
+
+
+ This is the most common source of deployment problems. Read carefully.
+
+
+When Sencho runs `docker compose up`, it does so on your **host machine**. Docker resolves relative volume paths in your Compose files relative to the **host** path of the stack directory — not the path inside the Sencho container.
+
+**The rule:** Mount your Compose directory at the **exact same path** inside the container as it exists on your host.
+
+```yaml
+# ✅ Correct — host path matches container path
+volumes:
+ - /home/boris/docker:/home/boris/docker
+environment:
+ - COMPOSE_DIR=/home/boris/docker
+```
+
+```yaml
+# ❌ Wrong — paths differ, relative volumes will break
+volumes:
+ - /home/boris/docker:/app/compose
+environment:
+ - COMPOSE_DIR=/app/compose
+```
+
+If you use a simple path like `/opt/compose` on your host, mount it at `/opt/compose` in the container:
+
+```yaml
+volumes:
+ - /opt/compose:/opt/compose
+environment:
+ - COMPOSE_DIR=/opt/compose
+```
+
+## Full docker-compose.yml example
+
+```yaml
+services:
+ sencho:
+ image: saelix/sencho:latest
+ restart: unless-stopped
+ ports:
+ - "3000:3000"
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - ./sencho-data:/app/data
+ - /opt/compose:/opt/compose # 1:1 path rule
+ environment:
+ - JWT_SECRET=your-long-random-secret-here
+ - COMPOSE_DIR=/opt/compose
+ - DATA_DIR=/app/data
+```
+
+## Optional: global environment file
+
+If your Compose stacks share common variables (e.g. `PUID`, `PGID`, `TZ`), you can pass an `env_file` to the Sencho container so those variables are available in the host environment when `docker compose` runs:
+
+```yaml
+services:
+ sencho:
+ image: saelix/sencho:latest
+ env_file:
+ - /opt/compose/globals.env # shared vars for all stacks
+ environment:
+ - JWT_SECRET=your-secret
+ - COMPOSE_DIR=/opt/compose
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - /opt/compose:/opt/compose
+ - ./sencho-data:/app/data
+```
+
+## Reverse proxy setup
+
+Sencho works behind any reverse proxy. The only requirement is that WebSocket connections are forwarded correctly (used for live logs, container terminals, and the host console).
+
+### Nginx
+
+```nginx
+server {
+ listen 80;
+ server_name sencho.yourdomain.com;
+
+ location / {
+ proxy_pass http://localhost:3000;
+ proxy_http_version 1.1;
+
+ # WebSocket support
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_read_timeout 3600s;
+ }
+}
+```
+
+### Traefik (Docker labels)
+
+```yaml
+labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.sencho.rule=Host(`sencho.yourdomain.com`)"
+ - "traefik.http.services.sencho.loadbalancer.server.port=3000"
+```
+
+
+ Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends. No extra configuration needed.
+
+
+## First boot
+
+After starting Sencho, open it in your browser. If no admin account exists yet, you'll be taken to a setup screen to create one. This only appears once — subsequent visits go directly to the login page.
diff --git a/docs/getting-started/introduction.mdx b/docs/getting-started/introduction.mdx
index 68511a48..8e719c6d 100644
--- a/docs/getting-started/introduction.mdx
+++ b/docs/getting-started/introduction.mdx
@@ -5,6 +5,10 @@ description: What Sencho is and why you might want it.
Sencho is a self-hosted Docker Compose management dashboard. It gives you a clean web UI to deploy, manage, and monitor your Docker Compose stacks — locally or across multiple remote servers — without touching a terminal.
+
+
+
+
## Key concepts
- **Stacks** — a Docker Compose project living in your `COMPOSE_DIR`. Sencho treats each subdirectory as a stack.
@@ -14,3 +18,15 @@ Sencho is a self-hosted Docker Compose management dashboard. It gives you a clea
Sencho never accesses remote servers directly via SSH or Docker TCP. Remote management works by proxying API requests to another running Sencho instance.
+
+## What you can do
+
+- **Deploy and control stacks** — create, start, stop, restart, and delete Compose stacks with one click
+- **Edit files in-browser** — full Monaco editor for `compose.yaml` and `.env` files
+- **Monitor in real-time** — live CPU, RAM, disk, and network stats with historical charts
+- **Stream logs** — tail container logs individually or aggregate all stacks in one view
+- **Manage resources** — browse, filter, and prune Docker images, volumes, and networks
+- **Deploy from the App Store** — one-click deployment from a curated template registry
+- **Run a host console** — interactive terminal on the host OS directly in the browser
+- **Set alerts** — threshold-based notifications via Discord, Slack, or any webhook
+- **Manage multiple servers** — add remote Sencho instances as nodes and switch between them seamlessly
diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx
index a786b867..a498cdaf 100644
--- a/docs/getting-started/quickstart.mdx
+++ b/docs/getting-started/quickstart.mdx
@@ -27,7 +27,12 @@ Open `http://localhost:3000` in your browser. On first boot you'll be prompted t
Replace `/opt/compose` with the path to your Compose projects directory. Every subdirectory inside it becomes a stack in Sencho.
+## Important: the 1:1 path rule
+
+The `-v /opt/compose:/app/compose` mount above uses a simplified path for illustration. In practice, you must mount your compose directory at the **same path** inside and outside the container. See the [Configuration guide](/getting-started/configuration#compose-directory-the-11-path-rule) for details — this is the most common setup mistake.
+
## Next steps
-- [Add a remote node](/features/overview) to manage another server from the same dashboard
-- Browse your stacks, start/stop services, and tail logs from the dashboard
+- [Configuration](/getting-started/configuration) — full environment variable reference, reverse proxy setup
+- [Stack Management](/features/stack-management) — create and deploy your first stack
+- [Multi-Node](/features/multi-node) — add a remote server to manage from this dashboard
diff --git a/docs/images/alerts-notifications/notifications-settings.png b/docs/images/alerts-notifications/notifications-settings.png
new file mode 100644
index 00000000..776d9315
Binary files /dev/null and b/docs/images/alerts-notifications/notifications-settings.png differ
diff --git a/docs/images/app-store/app-store-overview.png b/docs/images/app-store/app-store-overview.png
new file mode 100644
index 00000000..9cfb6cdf
Binary files /dev/null and b/docs/images/app-store/app-store-overview.png differ
diff --git a/docs/images/dashboard/dashboard-overview.png b/docs/images/dashboard/dashboard-overview.png
new file mode 100644
index 00000000..bd3d2121
Binary files /dev/null and b/docs/images/dashboard/dashboard-overview.png differ
diff --git a/docs/images/editor/editor-overview.png b/docs/images/editor/editor-overview.png
new file mode 100644
index 00000000..cc1a2105
Binary files /dev/null and b/docs/images/editor/editor-overview.png differ
diff --git a/docs/images/global-observability/global-observability-overview.png b/docs/images/global-observability/global-observability-overview.png
new file mode 100644
index 00000000..82e6ca2f
Binary files /dev/null and b/docs/images/global-observability/global-observability-overview.png differ
diff --git a/docs/images/host-console/host-console-overview.png b/docs/images/host-console/host-console-overview.png
new file mode 100644
index 00000000..5d776562
Binary files /dev/null and b/docs/images/host-console/host-console-overview.png differ
diff --git a/docs/images/multi-node/node-manager.png b/docs/images/multi-node/node-manager.png
new file mode 100644
index 00000000..e8dbb496
Binary files /dev/null and b/docs/images/multi-node/node-manager.png differ
diff --git a/docs/images/resources/resources-overview.png b/docs/images/resources/resources-overview.png
new file mode 100644
index 00000000..77189b2d
Binary files /dev/null and b/docs/images/resources/resources-overview.png differ
diff --git a/docs/images/settings/settings-overview.png b/docs/images/settings/settings-overview.png
new file mode 100644
index 00000000..898686dc
Binary files /dev/null and b/docs/images/settings/settings-overview.png differ
diff --git a/docs/images/stack-management/create-stack-dialog.png b/docs/images/stack-management/create-stack-dialog.png
new file mode 100644
index 00000000..029b246e
Binary files /dev/null and b/docs/images/stack-management/create-stack-dialog.png differ
diff --git a/docs/images/stack-management/stack-context-menu.png b/docs/images/stack-management/stack-context-menu.png
new file mode 100644
index 00000000..4464e345
Binary files /dev/null and b/docs/images/stack-management/stack-context-menu.png differ
diff --git a/docs/mint.json b/docs/mint.json
index 97ada4a9..ba9fa041 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -16,13 +16,36 @@
"group": "Getting Started",
"pages": [
"getting-started/introduction",
- "getting-started/quickstart"
+ "getting-started/quickstart",
+ "getting-started/configuration"
]
},
{
"group": "Features",
"pages": [
- "features/overview"
+ "features/overview",
+ "features/dashboard",
+ "features/stack-management",
+ "features/editor",
+ "features/resources",
+ "features/app-store",
+ "features/global-observability",
+ "features/host-console",
+ "features/multi-node",
+ "features/alerts-notifications"
+ ]
+ },
+ {
+ "group": "Reference",
+ "pages": [
+ "reference/settings"
+ ]
+ },
+ {
+ "group": "Operations",
+ "pages": [
+ "operations/troubleshooting",
+ "operations/backup"
]
}
]
diff --git a/docs/operations/backup.mdx b/docs/operations/backup.mdx
new file mode 100644
index 00000000..a42041cf
--- /dev/null
+++ b/docs/operations/backup.mdx
@@ -0,0 +1,139 @@
+---
+title: Backup & Restore
+description: What to back up, how to restore it, and how to migrate Sencho to a new host.
+---
+
+Sencho stores all its state in two places: the **data directory** (SQLite database) and your **compose directory** (your actual stack files). Both need to be backed up for a complete recovery.
+
+---
+
+## What to back up
+
+### 1. Data directory (`DATA_DIR`)
+
+Default path: `/app/data` inside the container, mapped to wherever you mounted it on the host (e.g. `./sencho-data`).
+
+Contains:
+- `sencho.db` — SQLite database with all settings, nodes, alerts, metrics history, and notification history
+
+This single file is everything Sencho knows about itself. Back it up and you can fully restore any Sencho installation.
+
+### 2. Compose directory (`COMPOSE_DIR`)
+
+The directory containing your stack subdirectories — your `compose.yaml` files, `.env` files, and any bind-mounted config files stored there.
+
+This is your actual application data. It lives entirely outside Sencho and you almost certainly already have it on a schedule, but include it in any Sencho backup plan.
+
+---
+
+## Backing up
+
+### Simple file copy
+
+```bash
+# Stop Sencho to ensure the SQLite WAL is flushed (recommended but not strictly required)
+docker stop sencho
+
+# Copy the data directory
+cp -r /path/to/sencho-data /path/to/backup/sencho-data-$(date +%Y%m%d)
+
+# Copy compose stacks
+cp -r /opt/compose /path/to/backup/compose-$(date +%Y%m%d)
+
+# Restart
+docker start sencho
+```
+
+### SQLite online backup (without stopping)
+
+SQLite supports hot backups via its `.backup` command. This is safe to run while Sencho is running:
+
+```bash
+sqlite3 /path/to/sencho-data/sencho.db ".backup '/path/to/backup/sencho.db'"
+```
+
+### Automated daily backup (cron example)
+
+```cron
+0 3 * * * sqlite3 /path/to/sencho-data/sencho.db ".backup '/backups/sencho-$(date +\%Y\%m\%d).db'" && find /backups -name "sencho-*.db" -mtime +30 -delete
+```
+
+This backs up the database at 3 AM daily and deletes backups older than 30 days.
+
+---
+
+## Restoring
+
+### Restore from backup
+
+1. Stop Sencho:
+ ```bash
+ docker stop sencho
+ ```
+
+2. Replace the data directory with your backup:
+ ```bash
+ rm -rf /path/to/sencho-data/*
+ cp /path/to/backup/sencho.db /path/to/sencho-data/sencho.db
+ ```
+
+3. Restore your compose directory if needed:
+ ```bash
+ cp -r /path/to/backup/compose /opt/compose
+ ```
+
+4. Start Sencho:
+ ```bash
+ docker start sencho
+ ```
+
+Sencho will read the restored database and resume with all your previous settings, nodes, and alert rules intact.
+
+---
+
+## Migrating to a new host
+
+### Step 1: Prepare the new host
+
+Install Docker and Docker Compose on the new machine. Create the same directory structure you use for your compose files, following the [1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule).
+
+### Step 2: Copy data
+
+Transfer your backup files to the new host:
+
+```bash
+scp -r /path/to/sencho-data newhost:/path/to/sencho-data
+scp -r /opt/compose newhost:/opt/compose
+```
+
+### Step 3: Deploy Sencho on the new host
+
+Use the same `docker-compose.yml` you used on the old host (with the same `COMPOSE_DIR` and `DATA_DIR` paths):
+
+```bash
+docker compose up -d
+```
+
+### Step 4: Update remote node references
+
+If other Sencho instances were pointing to your old host as a remote node, update their node config to use the new host's IP or hostname. Generate a new API token on the restored instance and distribute it.
+
+### Step 5: Verify
+
+- Log in and confirm your stacks, nodes, and alerts are all present
+- Check that at least one stack deploys correctly
+- Verify the node switcher shows the expected nodes with green status
+
+---
+
+## What is NOT backed up by this process
+
+| Item | Location | Notes |
+|------|----------|-------|
+| Container data volumes | Wherever each stack's volumes are mounted on the host | Back these up separately per-application |
+| Actual container images | Docker image cache | These are re-pulled on next deploy — no backup needed |
+| Sencho logs (docker logs) | Container stdout | Not persisted beyond container lifetime |
+
+
+ Sencho does not currently have a built-in backup scheduler or export function. The approaches above use standard OS tools and SQLite's own backup mechanism.
+
diff --git a/docs/operations/troubleshooting.mdx b/docs/operations/troubleshooting.mdx
new file mode 100644
index 00000000..8a1feb1d
--- /dev/null
+++ b/docs/operations/troubleshooting.mdx
@@ -0,0 +1,163 @@
+---
+title: Troubleshooting
+description: Solutions to the most common Sencho setup and runtime problems.
+---
+
+## Containers won't start after deploy
+
+**Symptom:** You click Deploy and containers immediately exit or never appear.
+
+**Check:** Open the [Host Console](/features/host-console) and run:
+
+```bash
+docker compose -f /path/to/your/stack/compose.yaml logs
+```
+
+The most common causes:
+
+- **Missing environment variable** — a required variable in your `.env` file is empty or has the wrong name.
+- **Port already in use** — another container or host process is bound to the same port. Change the host port in the compose file.
+- **Volume path does not exist** — a bind-mount path on the host doesn't exist yet. Create the directory manually.
+
+---
+
+## The 1:1 path rule — volumes resolve to wrong paths
+
+**Symptom:** Stacks deploy but relative volume paths (e.g. `./config:/config`) point to the wrong location inside the container, or `docker compose` exits with a path error.
+
+**Cause:** Your `COMPOSE_DIR` is mounted at a different path inside the Sencho container than it has on the host.
+
+**Fix:** Your compose volume mount and `COMPOSE_DIR` environment variable must use the **same absolute path** on both sides:
+
+```yaml
+# docker-compose.yml for Sencho itself
+volumes:
+ - /opt/docker:/opt/docker # same path inside and outside
+environment:
+ - COMPOSE_DIR=/opt/docker
+```
+
+See [Configuration — the 1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule) for a full explanation.
+
+---
+
+## "Permission denied" on the Docker socket
+
+**Symptom:** Sencho starts but shows errors accessing Docker, or the stack list is empty even though containers exist.
+
+**Cause:** The Sencho container cannot read `/var/run/docker.sock`.
+
+**Fix:** Ensure the socket is mounted:
+
+```yaml
+volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+```
+
+On Linux, the Docker socket is owned by the `docker` group. The Sencho entrypoint detects the socket's GID automatically and adds the internal `sencho` user to the matching group. If you see permission errors despite a correct mount, check that the socket file is readable:
+
+```bash
+ls -la /var/run/docker.sock
+# Expected: srw-rw---- 1 root docker ...
+```
+
+If the group is not `docker`, the auto-detection still works — Sencho reads the GID from the socket file at startup.
+
+---
+
+## Login page shows "Something went wrong"
+
+**Symptom:** You enter credentials and get a generic error instead of being logged in.
+
+**Possible causes and fixes:**
+
+| Cause | Fix |
+|-------|-----|
+| `JWT_SECRET` is not set or is empty | Set a non-empty value for `JWT_SECRET` in your environment |
+| Container restarted and session cookie is stale | Clear browser cookies for the Sencho domain and try again |
+| Rate limit triggered (5 failed attempts in 15 min) | Wait 15 minutes, or restart the container to reset the limiter |
+
+---
+
+## WebSocket connections fail (logs/console not streaming)
+
+**Symptom:** The log viewer or host console shows a spinner that never resolves, or you see "Disconnected" immediately after connecting.
+
+**Cause:** A reverse proxy is not forwarding WebSocket upgrade headers.
+
+**Fix:** Add WebSocket support to your proxy config:
+
+```nginx
+# Nginx
+proxy_http_version 1.1;
+proxy_set_header Upgrade $http_upgrade;
+proxy_set_header Connection "upgrade";
+proxy_read_timeout 3600s;
+```
+
+Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends — no extra config needed.
+
+---
+
+## Remote node shows "Offline" or "Unknown"
+
+**Symptom:** A node you added shows a red or gray status dot.
+
+**Checks in order:**
+
+1. **Is the remote Sencho instance running?** SSH to that machine and verify.
+2. **Is the API URL correct?** It must include the protocol and port (e.g. `http://192.168.1.20:3001`). Open it in a browser — you should see a JSON response from `/api/health`.
+3. **Is the token correct?** Tokens are long JWT strings. Even one missing character will cause auth to fail. Regenerate the token on the remote instance and update the node config.
+4. **Is there a firewall blocking the port?** The primary Sencho host must be able to reach the remote host's Sencho port.
+
+Click the **wifi icon** on the node row to re-test connectivity after making changes.
+
+---
+
+## Forgotten admin password
+
+Sencho has no password recovery flow. To reset the password:
+
+1. Stop the Sencho container
+2. Connect to the SQLite database directly:
+
+```bash
+sqlite3 /path/to/data/sencho.db
+```
+
+3. Delete the existing credentials so Sencho re-enters first-boot setup mode:
+
+```sql
+DELETE FROM global_settings WHERE key IN ('auth_username', 'auth_password_hash', 'auth_jwt_secret');
+```
+
+4. Restart the container — the setup screen will appear on next visit.
+
+
+ This resets authentication entirely. All active sessions become invalid. Your stacks, nodes, and alert rules are not affected.
+
+
+---
+
+## Checking the health endpoint
+
+Sencho exposes a health endpoint for monitoring and container health checks:
+
+```bash
+curl http://localhost:3000/api/health
+# {"status":"ok","uptime":12345.67}
+```
+
+A `200` response confirms the backend is running. Use this endpoint in your uptime monitor or load balancer health check.
+
+---
+
+## Getting logs from the Sencho container itself
+
+```bash
+docker logs sencho
+# or, to follow:
+docker logs -f sencho
+```
+
+The backend logs all route errors and service failures to stdout. This is the first place to look when the UI shows an error with no useful message.
diff --git a/docs/reference/settings.mdx b/docs/reference/settings.mdx
new file mode 100644
index 00000000..9ca2c9b7
--- /dev/null
+++ b/docs/reference/settings.mdx
@@ -0,0 +1,126 @@
+---
+title: Settings Reference
+description: Complete reference for every option in the Sencho Settings Hub.
+---
+
+Open the Settings Hub by clicking **Settings** in the top navigation bar. The left sidebar lists all available sections.
+
+
+
+
+
+---
+
+## Account
+
+**Scope:** Global (applies to this Sencho instance, not per-node)
+
+Change the admin account password. All three fields are required.
+
+| Field | Description |
+|-------|-------------|
+| **Current Password** | Your existing password for verification |
+| **New Password** | Must be at least 6 characters |
+| **Confirm New Password** | Must match New Password |
+
+Click **Update Password** to apply. The change takes effect immediately; existing sessions remain valid.
+
+---
+
+## System Limits
+
+**Scope:** Per-node (applies to the currently selected node)
+
+Configure resource thresholds that trigger visual warnings on the dashboard stat cards. These are display thresholds only — Sencho does not throttle or kill containers when limits are reached.
+
+| Setting | Range | Description |
+|---------|-------|-------------|
+| **Host CPU Limit** | 1–100% | CPU percentage above which the CPU card turns orange/red |
+| **Host RAM Limit** | 1–100% | RAM percentage above which the RAM card turns orange/red |
+| **Host Disk Limit** | 1–100% | Disk percentage above which the Disk card turns orange/red |
+| **Docker Janitor Threshold** | ≥ 0 GB | Minimum free disk space to maintain. When free space falls below this value, a warning is shown. Set to `0` to disable. |
+| **Global Crash Alerts** | On / Off | When enabled, Sencho sends a notification whenever any managed container exits unexpectedly |
+
+Click **Save** to apply. An unsaved-changes indicator appears when you have edits pending.
+
+---
+
+## Notifications
+
+**Scope:** Global
+
+Configure external destinations for alert notifications. Three agent types are supported, each on its own sub-tab: **Discord**, **Slack**, and **Webhook**.
+
+For each agent:
+
+| Field | Description |
+|-------|-------------|
+| **Enable toggle** | Activates or deactivates this agent. Disabled agents receive no messages even if a URL is saved. |
+| **Webhook URL** | The endpoint Sencho will POST to when an alert fires |
+
+Click **Save** to persist changes. Click **Test** to send a test payload immediately and verify delivery.
+
+At least one agent must be enabled for stack alerts to deliver notifications. See [Alerts & Notifications](/features/alerts-notifications) for how to create alert rules.
+
+---
+
+## Appearance
+
+**Scope:** Global (stored in the browser, not the server)
+
+| Setting | Options | Description |
+|---------|---------|-------------|
+| **Theme** | Light / Dark / Auto | `Auto` follows the OS system preference. Changes apply immediately without a page reload. |
+
+---
+
+## Developer
+
+**Scope:** Per-node (applies to the currently selected node)
+
+Advanced settings for log streaming behaviour and data retention. Most users can leave these at their defaults.
+
+| Setting | Default | Description |
+|---------|---------|-------------|
+| **Developer Mode** | Off | When on, the [Global Observability](/features/global-observability) view switches from polling to real-time Server-Sent Events streaming |
+| **Global Logs Refresh Rate** | 5s | Polling interval in standard mode. Options: `1s`, `3s`, `5s`, `10s` |
+| **Metrics Retention Hours** | 24 | How many hours of CPU/RAM history to keep for dashboard charts. Max: 8,760 (1 year) |
+| **Log Retention Days** | 30 | How many days of notification history to keep in the database. Max: 365 |
+
+Click **Save** to apply.
+
+
+ Lower refresh rates (1s) increase backend CPU usage as Sencho polls Docker more frequently. Use only when actively debugging.
+
+
+---
+
+## Nodes
+
+**Scope:** Global
+
+Manage connections to local and remote Sencho instances. This is the same interface as the [Multi-Node](/features/multi-node) feature — see that page for the full walkthrough.
+
+Quick reference:
+
+| Action | How |
+|--------|-----|
+| Add a remote node | Click **+ Add Node** |
+| Generate a token for this instance | Click **Generate Token** |
+| Test an existing node's connectivity | Click the wifi icon on any row |
+| Edit a node | Click the pencil icon |
+| Delete a node | Click the trash icon (remote nodes only) |
+
+---
+
+## App Store
+
+**Scope:** Global
+
+| Setting | Default | Description |
+|---------|---------|-------------|
+| **Template Registry URL** | LinuxServer.io registry | The URL Sencho fetches templates from. Must return a JSON array in Portainer v2 template format. Leave blank to restore the default. |
+
+Click **Save** to update the URL. Click **Refresh Cache** to clear the cached template list and fetch fresh data from the registry immediately.
+
+See [App Store](/features/app-store#custom-template-registry) for more on custom registries.