diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/audit-log-blueprint-actions.png b/docs/images/tutorials/create-and-approve-a-blueprint/audit-log-blueprint-actions.png
new file mode 100644
index 00000000..d8441a04
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/audit-log-blueprint-actions.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-created-pending.png b/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-created-pending.png
new file mode 100644
index 00000000..b65b21ff
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-created-pending.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-editor-compose.png b/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-editor-compose.png
new file mode 100644
index 00000000..964a3d5f
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-editor-compose.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-editor-selector-drift.png b/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-editor-selector-drift.png
new file mode 100644
index 00000000..9daa789a
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/blueprint-editor-selector-drift.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/catalog-active.png b/docs/images/tutorials/create-and-approve-a-blueprint/catalog-active.png
new file mode 100644
index 00000000..093292ec
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/catalog-active.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/deployment-failed-port-conflict.png b/docs/images/tutorials/create-and-approve-a-blueprint/deployment-failed-port-conflict.png
new file mode 100644
index 00000000..a99c4c49
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/deployment-failed-port-conflict.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/detail-sheet-active.png b/docs/images/tutorials/create-and-approve-a-blueprint/detail-sheet-active.png
new file mode 100644
index 00000000..0b6ee3c1
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/detail-sheet-active.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/node-labels-add-edge.png b/docs/images/tutorials/create-and-approve-a-blueprint/node-labels-add-edge.png
new file mode 100644
index 00000000..3dc2a021
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/node-labels-add-edge.png differ
diff --git a/docs/images/tutorials/create-and-approve-a-blueprint/rollout-preview.png b/docs/images/tutorials/create-and-approve-a-blueprint/rollout-preview.png
new file mode 100644
index 00000000..c3347e80
Binary files /dev/null and b/docs/images/tutorials/create-and-approve-a-blueprint/rollout-preview.png differ
diff --git a/docs/tutorials/create-and-approve-a-blueprint.mdx b/docs/tutorials/create-and-approve-a-blueprint.mdx
index bcab3b13..d4851d40 100644
--- a/docs/tutorials/create-and-approve-a-blueprint.mdx
+++ b/docs/tutorials/create-and-approve-a-blueprint.mdx
@@ -1,26 +1,116 @@
---
title: Create and Approve a Blueprint
sidebarTitle: Create and approve a blueprint
-description: Step-by-step instructions for authoring, previewing, and approving a rollout blueprint.
+description: Author a fleet-wide compose template, target it at a node with a label, and walk through the confirm-before-mutate rollout that puts it on the fleet.
---
-
- This tutorial is a placeholder pending full content. See the [Blueprint Model feature page](/features/blueprint-model) for the current reference documentation.
-
+Every other lane in Sencho manages one Compose file on one node. A **Blueprint** is the other lane: you declare a Compose file once, point it at the nodes you want by label or by ID, and Sencho keeps those nodes in sync with that declaration going forward, deploying it where it's missing and telling you the moment a targeted node drifts from what you declared. This walks through the two-part motion every Blueprint goes through before it touches your fleet: you **create** it (author the compose, pick a target, choose how drift gets handled), then you **approve** it (review exactly what Sencho is about to place, and confirm). By the end, a small stateless service is running on a real node, deployed entirely through the Blueprint you approved rather than a manual `docker compose up`.
-## What you'll do
+This tutorial does not cover stateful Blueprints (the extra confirmation step for named volumes and bind mounts), pinning a Blueprint to a specific node, or moving a deployment between nodes. See the [Blueprints](/features/blueprint-model) feature page for stateful workflows, and [Move a Blueprint Deployment to a New Node](/tutorials/set-up-fleet-federation) once you've completed this one and want to relocate a deployment with Federation.
## Prerequisites
+- **An admin account.** Creating, editing, and applying a Blueprint all require the admin role. Operators and viewers can read the catalog and the detail sheet but can't act on either.
+- **At least one node**, local or remote, that you can attach a label to. Blueprints are a Community-tier capability; no paid plan is required.
+
-
+
+ Blueprints target nodes by label or by explicit node ID. Open **Settings → Infrastructure → Nodes**, find the node you want this Blueprint to reach, and click the **+** button in its **Labels** column. Type `edge` and click **Add**.
+
+
+
+
+
+ Labels are plain lowercase strings, not key/value pairs. You can add more than one to a node, and a Blueprint's selector can match on any combination of them.
+
+
+ Go to **Fleet → Deployments** and click **New Blueprint**. Fill in:
+
+ - **Name**: `whoami-edge`
+ - **Description**: `Minimal identity endpoint for the edge tier`
+
+ In the **Compose** editor, replace the placeholder YAML with a small, stateless HTTP service that just echoes back which container answered, useful for confirming a deploy actually landed:
+
+ ```yaml
+ services:
+ app:
+ image: traefik/whoami:v1.10
+ restart: unless-stopped
+ ports:
+ - "8080:80"
+ ```
+
+ As you type, the classification banner above the editor updates. With no volumes in this compose, it settles on **Stateless · portable**: Sencho can deploy and evict this Blueprint freely, with none of the extra confirmation prompts a stateful Blueprint requires.
+
+
+
+
+
+ Scroll down to **Selector** and leave **Labels** selected. Click the `edge` pill under **Match nodes with ANY of these labels**. The line below confirms `Resolves to nodes labelled any of [edge]`. Under **Drift policy**, leave **Suggest** selected, the middle option: Sencho will always detect drift on this Blueprint, and Suggest additionally sends a notification when it happens, without redeploying anything on its own. (**Observe** stays silent about drift beyond the deployment row; **Enforce** auto-redeploys to fix it.)
+
+
+
+
+
+ Click **Create blueprint**.
+
+
+ The detail sheet opens on your new Blueprint: `any=[edge] · suggest · rev 1`, with **Apply now**, **Edit**, **Disable**, and **Delete** across the top. The **Deployments** section is still empty, with the note `No matching nodes yet. Add a label or pick a node ID, then click Apply now.`
+
+
+
+
+
+ This is expected, not a bug: creating a Blueprint only declares intent. Sencho computes what it would actually do, and does it, only once you open the rollout preview.
+
+
+ Click **Apply now**. Sencho computes a rollout preview: `Safe 1 · Warnings 1 · Blockers 0`, with a warning noting `no persistent volumes detected` (informational for a stateless Blueprint, not a problem), and one line under **Changes**: `Local (local/online) · create · safe: New placement`.
+
+
+
+
+
+ This preview is the actual authorization step: nothing on the fleet has changed yet, and Sencho is showing you exactly what it's about to do before it does it. Click **Confirm Apply**.
+## Verify it worked
+
+Check from two places, since a single stale UI element could tell you the wrong thing.
+
+**The Deployments tab.** Back on **Fleet → Deployments**, the `whoami-edge` tile now shows a green dot, the **stateless** chip, and `1/1 active · any=[edge]`. Open the tile: the deployment table lists **Local**, status **Active**, with a **Withdraw** action now available. The stack also appears in the left sidebar's stack list like any other running stack, materialized on disk the same way a per-stack deploy would be.
+
+
+
+
+
+
+
+
+
+**The audit log.** Open **Audit**, switch to **Table**, and search `blueprints/1` (or whatever ID your Blueprint got, visible in the browser's address bar or in the raw preview response). You'll see a `POST /api/blueprints/1/apply` row for each time you clicked **Confirm Apply**, each logged with your account, a timestamp, and a 200 status. If you also hit and fixed a port conflict (see below), a `PUT /api/blueprints/1` row from saving the edit shows up between the two applies.
+
+
+
+
+
+## If something goes wrong
+
+The most common first-time failure is a host port that's already taken. `8080` is a common default that other containers on the same node may already be bound to. If that happens, the deployment row moves to **Failed**, and the notes column carries the real Docker error, ending in something like `Bind for 0.0.0.0:8080 failed: port is already allocated`.
+
+
+
+
+
+To recover, click **Edit**, change the host-side port in the `ports` mapping to something free (`8091:80`, for instance), and **Save changes**. Saving bumps the revision and clears approval back to pending, so click **Apply now** again: the preview this time shows an `update` action instead of `create`. Confirm it, and the deployment moves through **Deploying** to **Active** on the new port.
+
## Related
- Author, preview, and approve fleet-wide rollouts.
+ The full mental model: markers, drift modes, stateful safety rails, and the reconciler's approval mechanics.
+
+
+ Once a Blueprint is running, use Federation's pin and cordon controls to relocate it to a different node.
diff --git a/docs/tutorials/set-up-fleet-federation.mdx b/docs/tutorials/set-up-fleet-federation.mdx
index c2afa71d..cc9e1ed9 100644
--- a/docs/tutorials/set-up-fleet-federation.mdx
+++ b/docs/tutorials/set-up-fleet-federation.mdx
@@ -14,12 +14,12 @@ By the end, the workload runs only on the new node, the old node is marked unsch
Both controls follow the same rule, and it's the part most likely to trip up a first-time user: **pinning and cordoning only declare intent.** Neither one deploys or withdraws a single container by itself. The reconciler stages what it *wants* to do next; you still open the blueprint and click **Confirm Apply** before anything on the fleet actually changes. That extra step is what makes this walkthrough three actions long instead of one.
-This tutorial does not cover creating a Blueprint from scratch, draining a node of everything it runs, or evicting a stateful deployment. See the [Blueprints](/features/blueprint-model) and [Fleet Federation](/features/fleet-federation) feature pages for those.
+This tutorial does not cover creating a Blueprint from scratch (see [Create and Approve a Blueprint](/tutorials/create-and-approve-a-blueprint)), draining a node of everything it runs, or evicting a stateful deployment. See the [Blueprints](/features/blueprint-model) and [Fleet Federation](/features/fleet-federation) feature pages for those last two.
## Prerequisites
- **An admin account.** Cordoning a node and pinning a blueprint both check the same permission, scoped to the node you're acting on; clearing a pin checks that same permission without a node scope. Delegating that permission to a non-admin role for one specific node is an Admiral-tier capability, so on Community you complete every step here as the instance's admin.
-- **An existing Blueprint already deployed on at least one node.** Federation steers placement for Blueprints that exist; it does not create them. If you don't have one yet, create it under **Fleet → Deployments** first, see [Blueprints](/features/blueprint-model).
+- **An existing Blueprint already deployed on at least one node.** Federation steers placement for Blueprints that exist; it does not create them. If you don't have one yet, walk through [Create and Approve a Blueprint](/tutorials/create-and-approve-a-blueprint) first.
- **At least two nodes in the fleet**, both online. Pinning only matters when there's somewhere else to pin to. Multi-node fleets and Federation are both Community-tier, no paid plan required.
@@ -113,4 +113,7 @@ If **Confirm Apply** is greyed out instead, a blocker is present, most often an
The declarative deployment model Federation steers, including selectors, drift policy, and the rollout-preview mechanic.
+
+ Author and deploy a Blueprint from scratch, the prerequisite this tutorial assumes.
+