diff --git a/apps/docs/content/docs/core/alerts.mdx b/apps/docs/content/docs/core/alerts.mdx
new file mode 100644
index 00000000..ef67b215
--- /dev/null
+++ b/apps/docs/content/docs/core/alerts.mdx
@@ -0,0 +1,65 @@
+---
+title: Monitoring & Alerts
+description: "Metric alert rules — load balancer, per-service, and security/observability health — that notify your cluster-alert channels on a threshold breach, with silences."
+---
+
+import { Callout } from "fumadocs-ui/components/callout";
+
+The **Alerts** page (sidebar → **Alerts**) watches cluster metrics and notifies
+your cluster-alert channels when a metric crosses a threshold. It complements the
+**Monitoring** tab (live utilization graphs) by turning those signals into
+proactive notifications.
+
+## Alert rules
+
+Each rule watches one **metric** and fires when the value stays **over** (or
+**under**) a **threshold** for a **window** (`forMinutes`), then **resolves** when
+it recovers. On each transition (fire / resolve) it notifies every channel that
+has **cluster alerts** enabled. Rules have a **severity** (critical / warning /
+info) and can be **silenced** during maintenance.
+
+Create a rule from **Alerts → New rule**: pick the metric, comparator, threshold,
+window and severity. A live preview graph shows recent history for the metric.
+
+## Available metrics
+
+| Metric | Scope | Fires when |
+|---|---|---|
+| `lb_5xx_per_sec` | load balancer | 5xx rate over threshold |
+| `lb_req_per_sec` | load balancer | request rate over threshold |
+| `lb_latency_ms` | load balancer | average latency over threshold |
+| `service_cpu_pct` | a service (or **all**) | CPU used vs reserved over threshold |
+| `service_mem_pct` | a service (or **all**) | memory used vs reserved over threshold |
+| `crowdsec_active_bans` | cluster | active CrowdSec bans over threshold |
+| `crowdsec_detector_up` | cluster | the CrowdSec detector is **not** running |
+| `otel_collector_up` | cluster | the OTel collector is **not** running |
+| `log_agent_up` | cluster | some node's log agent is down |
+
+The load-balancer and service metrics are averaged over the rule's window (see
+[Load Balancer](/docs/core/load-balancer) and the Monitoring tab). The **service**
+metrics can target a single service or **all services** — an all-services rule
+fans out and fires/resolves each service independently.
+
+## Security & observability health
+
+The four cluster-wide metrics (`crowdsec_*`, `otel_collector_up`, `log_agent_up`)
+are the "is it up / is something wrong" signals for the platform's own features:
+
+- Each reports **not applicable** (the rule is skipped) when its feature is turned
+ off, so *off* never reads as *down*.
+- They are **debounced** — a breach must hold for the rule's window before it
+ fires, so a brief dip during a rolling update (a collector/detector restart)
+ doesn't flap the alert.
+
+See [Security](/docs/core/security) and [Telemetry](/docs/core/telemetry) for the
+features behind these metrics.
+
+## Silences
+
+Create a **silence** to mute notifications during a planned maintenance window. An
+empty-matcher silence is org-wide; setting a rule, target or severity narrows it.
+
+
+Rules keep evaluating and show as firing during a silence — only the matching
+notifications are suppressed.
+
diff --git a/apps/docs/content/docs/core/deploying.mdx b/apps/docs/content/docs/core/deploying.mdx
new file mode 100644
index 00000000..04e61b91
--- /dev/null
+++ b/apps/docs/content/docs/core/deploying.mdx
@@ -0,0 +1,75 @@
+---
+title: Deploying
+description: "Everything runs as a Nomad job — applications/databases from forms, Docker Compose auto-translated to Nomad HCL, native HCL deployed verbatim, or a Nomad Pack."
+---
+
+import { Callout } from "fumadocs-ui/components/callout";
+
+Everything nomploy runs ends up as a **Nomad job**. There are a few ways to get
+there depending on what you're deploying.
+
+## Applications and databases
+
+For an **Application** or **Database** service you fill in settings (source,
+image/build, env, ports, health, resources, replicas) and nomploy renders the
+Nomad jobspec for you. This is the path most users use — see
+[Autoscaling](/docs/core/autoscaling) and [GPU workloads](/docs/core/gpu) for the
+advanced knobs.
+
+## Compose services
+
+A **Compose** service gives you three deploy styles. You pick the style when you
+create the service, via the **Compose Type** selector:
+
+| Selector option | What it does |
+|---|---|
+| **docker-compose** | Legacy Swarm-style compose. |
+| **Nomad (compose or HCL jobspec)** | The default. Accepts either a Docker Compose file *or* a native Nomad HCL job — auto-detected. |
+| **Nomad Pack** | Deploys a [Nomad Pack](/docs/core/nomad-packs). |
+
+The Deploy Settings card shows a read-only badge (**Compose** / **Nomad** /
+**Nomad Pack**) reflecting the type.
+
+### Compose → Nomad HCL (automatic)
+
+Under **Nomad (compose or HCL jobspec)**, if your file is a Docker Compose file,
+nomploy translates it to an equivalent Nomad job at deploy time:
+
+- Each service becomes a task; ports, env, health checks, resources and replicas
+ are carried over.
+- Multi-replica services get a soft `spread` across nodes.
+- Every allocation gets a `network.dns` block pointing at the cluster DNS
+ servers, and Consul service registrations (with Traefik tags for any domains
+ you've added) so ingress works automatically.
+- `docker compose build` + `docker compose push` run before `nomad job run`.
+
+You don't do anything special — just paste your compose file and deploy.
+
+### Native Nomad HCL (automatic)
+
+Sometimes you want full control. Under the **same** *Nomad (compose or HCL
+jobspec)* type, if your file is a real Nomad job file — it contains a
+`job "" { … }` block — nomploy detects that and deploys it **verbatim**: no
+translation, no compose build/push, no variable substitution. This is the "deploy
+using Nomad syntax" path.
+
+Use it when you need Nomad features that compose can't express (task groups,
+templates, `volume`/`csi`, `constraint`, sidecars, and so on).
+
+### Nomad Pack
+
+Choose **Nomad Pack** to deploy a pack from a registry — see
+[Nomad Pack deploy](/docs/core/nomad-packs) for the one-click store and the
+variables form.
+
+## What happens on deploy
+
+Regardless of path, deployment is health-gated: the generated jobs use an
+`update` block with `auto_revert`, so a failed rollout rolls back to the last
+healthy version. Watch the deployment logs stream live in the UI.
+
+
+Runtime **secrets** are injected from a Nomad Variable (never baked into the job
+spec); the editor preserves your exact order and comments. See the service's
+**Environment** tab.
+
diff --git a/apps/docs/content/docs/core/gpu.mdx b/apps/docs/content/docs/core/gpu.mdx
new file mode 100644
index 00000000..af218972
--- /dev/null
+++ b/apps/docs/content/docs/core/gpu.mdx
@@ -0,0 +1,77 @@
+---
+title: GPU workloads
+description: "Schedule NVIDIA GPUs with Nomad's device plugin — enable GPU support on the node, then request a GPU in Compose or native HCL."
+---
+
+import { Callout } from "fumadocs-ui/components/callout";
+
+Nomploy schedules NVIDIA GPUs through Nomad's `nomad-device-nvidia` plugin. There
+are two steps: enable GPU support on the node, then request a GPU in your job.
+
+## 1. Enable GPU support on the node
+
+
+The NVIDIA driver (`nvidia-smi`) must already be installed on the machine —
+nomploy does not install the kernel driver.
+
+
+Open the server's setup/actions and use **GPU Configuration → Enable GPU
+Support**. This:
+
+- installs the NVIDIA Container Toolkit,
+- points Docker at the `nvidia` runtime, and
+- installs the `nomad-device-nvidia` plugin so Nomad can fingerprint and schedule
+ the GPUs.
+
+The card shows the detected GPU status and becomes **Reconfigure GPU** once set up.
+
+## 2. Request a GPU in your workload
+
+There's no separate GPU form field — you request GPUs in your service definition.
+
+### Docker Compose
+
+Use the standard compose device reservation:
+
+```yaml
+services:
+ trainer:
+ image: my/cuda-app:latest
+ deploy:
+ resources:
+ reservations:
+ devices:
+ - driver: nvidia
+ count: 1
+ capabilities: [gpu]
+```
+
+A device is treated as a GPU when its `driver` is `nvidia` **or** its
+`capabilities` include `gpu`. The `count` is summed across matching devices;
+`count: all` or an omitted count is treated as **1**. nomploy turns that into a
+Nomad `device "nvidia/gpu" { count = N }` block in the generated job (`nvidia/gpu`
+matches any NVIDIA GPU the plugin fingerprints).
+
+### Native Nomad HCL
+
+If you deploy a [native HCL job](/docs/core/deploying#native-nomad-hcl-automatic),
+request the device directly in the task's `resources`:
+
+```hcl
+resources {
+ cpu = 2000
+ memory = 4096
+ device "nvidia/gpu" {
+ count = 1
+ }
+}
+```
+
+This gives you the full device-plugin surface (constraints on model, memory,
+`affinity`, etc.) if you need it.
+
+## Notes
+
+- GPUs are only schedulable on nodes where you enabled GPU support in step 1.
+- Combine with a `constraint` if you have a mixed fleet and want a job pinned to
+ GPU nodes.
diff --git a/apps/docs/content/docs/core/meta.json b/apps/docs/content/docs/core/meta.json
index 2552bdd6..9811c506 100644
--- a/apps/docs/content/docs/core/meta.json
+++ b/apps/docs/content/docs/core/meta.json
@@ -34,10 +34,12 @@
"dns-providers",
"ssh-keys",
"certificates",
+ "nomad-tokens",
"backups",
"concurrent-builds",
"---Services---",
"overview",
+ "deploying",
"variables",
"domains",
"applications",
@@ -63,7 +65,9 @@
"cluster",
"load-balancer",
"autoscaling",
+ "gpu",
"telemetry",
+ "alerts",
"security",
"---Enterprise---",
"enterprise/index",
diff --git a/apps/docs/content/docs/core/nomad-tokens.mdx b/apps/docs/content/docs/core/nomad-tokens.mdx
new file mode 100644
index 00000000..740eb79b
--- /dev/null
+++ b/apps/docs/content/docs/core/nomad-tokens.mdx
@@ -0,0 +1,43 @@
+---
+title: Nomad ACL tokens
+description: "Mint, list and revoke scoped Nomad ACL tokens from the panel for direct Nomad API / CLI / Terraform access — without SSHing into a server."
+---
+
+import { Callout } from "fumadocs-ui/components/callout";
+
+Nomploy runs Nomad with **ACLs enabled** — the panel drives the cluster with its
+own management token, so you normally never deal with tokens directly. When you
+want to talk to the Nomad **API / CLI / Terraform yourself**, mint a scoped token
+from **Settings → Nomad Tokens** instead of copying the management token off a
+server.
+
+## Mint a token
+
+**Settings → Nomad Tokens → create.** Give it a name and a scope (the ACL policy
+it's bound to), and the panel returns a token **secret**.
+
+
+The secret is shown **once** at creation — copy it then. Treat it like a password;
+anyone with it can act on the cluster within its scope.
+
+
+Use it with the Nomad CLI or API pointed at the cluster:
+
+```bash
+export NOMAD_ADDR=https://
+export NOMAD_TOKEN=
+nomad job status
+```
+
+## List & revoke
+
+The page lists the tokens you've minted (name, scope, accessor — never the secret
+again). **Revoke** invalidates a token immediately cluster-wide, so a leaked or
+stale token is killed from the panel without touching the servers.
+
+## Notes
+
+- Scope tokens to the least privilege the task needs; keep the management token
+ for the panel only.
+- Revoking a token takes effect right away — any CLI/API/automation using it stops
+ working on its next call.