diff --git a/src/content/docs/changelog/index.mdx b/src/content/docs/changelog/index.mdx
index 82a81a3d..7d552445 100644
--- a/src/content/docs/changelog/index.mdx
+++ b/src/content/docs/changelog/index.mdx
@@ -16,7 +16,8 @@ Notable changes to the kit, newest first.
- **Dependencies updated to latest for the v10 release** — .NET **Aspire 13.3.5** (Hosting packages + AppHost SDK), Finbuckle.MultiTenant 10.1.0, MailKit/MimeKit 4.17.0, AWSSDK.S3 4.0.23.4, Scalar.AspNetCore 2.14.14, and SonarAnalyzer 10.27. Builds clean with warnings-as-errors and the full test suite (unit + Testcontainers integration) stays green.
- **Template packaging fixes — scaffolded Dockerfiles and dev-machine packing** — `dotnet new fsh` / `fsh new` packed extensionless files (every `Dockerfile`) to a doubled nested path, so scaffolded projects got a `Dockerfile` *directory* instead of a file and `deploy/docker` (`docker compose up`) was broken. Also made the IDE-cache excludes (`.vs`/`.idea`/`.vscode`) recursive so `dotnet pack` no longer fails (or bundles IDE junk) when packing the template on a developer machine. Scaffolded output now builds and self-hosts cleanly.
- **Scaffolded apps log in out of the box, get isolated data volumes, and start on `main`** — three `fsh new` / Aspire DX fixes: the AppHost migrator now runs `apply --seed`, so the root admin (`admin@root.com`) is seeded automatically — previously a freshly-run app came up with an empty user table and **nobody could log in**; each app's Docker volumes are namespaced by app name (e.g. `myapp-postgres-data`) instead of sharing a literal `postgres-data`, so two FSH-based apps on one machine no longer clobber each other's database; and `fsh new` initializes git on `main` rather than following the machine's git default (often `master`).
-- **Demo logins (`acme`/`globex`) work on a fresh Aspire launch** — the dashboard's demo-login panel advertised accounts that were never seeded: the AppHost migrator ran only `apply --seed` (which seeds the root admin), while the `acme`/`globex` demo tenants are created by the dev-only `seed-demo` verb. Aspire now runs `seed-demo` as a dedicated `fsh-demo-seeder` step after migration — so `admin@acme.com` / `Password123!` works the moment the dashboard loads. Also fixes the migrator crashing at startup in Development (its trimmed service graph tripped the DI container's build-time validation) and corrects the verb's environment gate to `DOTNET_ENVIRONMENT` (the migrator is a generic-host console app, not a web host).
+- **Demo logins (`acme`/`globex`) work on a fresh Aspire launch** — the dashboard's demo-login panel advertised accounts that were never seeded: the AppHost migrator ran only `apply --seed` (which seeds the root admin), while the `acme`/`globex` demo tenants are created by the dev-only `seed-demo` verb. Aspire now runs `seed-demo` as a dedicated demo-seeder step after migration — so `admin@acme.com` / `Password123!` works the moment the dashboard loads. Also fixes the migrator crashing at startup in Development (its trimmed service graph tripped the DI container's build-time validation) and corrects the verb's environment gate to `DOTNET_ENVIRONMENT` (the migrator is a generic-host console app, not a web host).
+- **Aspire resource names are namespaced per app** — the AppHost's resource/container names (API, migrator, demo-seeder, admin, dashboard) now derive from the app's namespace, like the Docker volume names already did. A scaffolded `Acme.Store` shows `acme-store-api` etc. instead of the kit's literal `fsh-*`, so two FSH-based apps on one machine don't collide. (This repo resolves to `fsh-starter-*`; the `postgres`/`redis`/`minio` infra and the `fsh-db` database keep stable names.)
- **Stale sessions resolve cleanly instead of erroring** — both React apps (admin + dashboard) treated an expired token left in `localStorage` as signed-in, firing protected requests that 401'd in a loop (`SecurityTokenExpiredException`). On boot they now attempt one silent token refresh: success restores the session, failure routes to `/login`. Long-lived sessions still refresh transparently mid-use.
- **CI split into path-scoped backend + frontend pipelines** — the single `ci.yml` is replaced by `backend.yml` (runs only on `src/**` changes) and `frontend.yml` (runs only on `clients/**`), so a client-only change never builds or tests the API, and vice versa. The SDK is pinned to the .NET 10 **GA** release via a root `global.json` (no more preview channel). Unit and integration tests each run **once**, and the coverage gate merges their results instead of re-running the whole solution. The React apps get real CI for the first time — ESLint, `tsc`/Vite build, and the Playwright E2E suites (admin + dashboard) on Node 22. Branch protection requires the always-resolving `Backend CI` / `Frontend CI` gate jobs. See [CI/CD](/docs/deployment/ci-cd/).
- **Consolidated to a single `main` branch** — the repo now uses one long-lived default branch, `main`; the `develop` branch is retired. Branch from and target `main`; stable releases are cut from `v*` tags. See [Contributing](/docs/contributing/).
diff --git a/src/content/docs/deployment/aspire.mdx b/src/content/docs/deployment/aspire.mdx
index 984cd98e..2f5f01a8 100644
--- a/src/content/docs/deployment/aspire.mdx
+++ b/src/content/docs/deployment/aspire.mdx
@@ -33,18 +33,26 @@ documents what it starts and **why** it's wired the way it is.
| RedisInsight | *(sidecar)* | Key browser auto-connected to the Valkey instance for inspecting cache keys in dev | Persistent |
| MinIO | `minio` | S3-compatible object storage, **:9000** (API) / **:9001** (console) | Persistent (data volume) |
| MinIO init | `minio-init` | One-shot: creates the `fsh-uploads` bucket + download policy, then exits | Run-once |
-| DB migrator | `fsh-db-migrator` | One-shot: applies migrations across the tenant catalog + every tenant's module DBs (`apply --seed`, so the root admin exists), then exits | Run-once |
-| Demo seeder | `fsh-demo-seeder` | One-shot, **dev-only**: runs `seed-demo` after the migrator to provision the `acme`/`globex` demo tenants + users, then exits | Run-once |
-| API | `fsh-api` | The ASP.NET Core API (`net10.0`) | Long-running |
-| Admin app | `fsh-admin` | Operator React + Vite SPA on **:5173** | Long-running |
-| Dashboard app | `fsh-dashboard` | Tenant React + Vite SPA on **:5174** (with SSE live feed) | Long-running |
+| DB migrator | `fsh-starter-db-migrator` | One-shot: applies migrations across the tenant catalog + every tenant's module DBs (`apply --seed`, so the root admin exists), then exits | Run-once |
+| Demo seeder | `fsh-starter-demo-seeder` | One-shot, **dev-only**: runs `seed-demo` after the migrator to provision the `acme`/`globex` demo tenants + users, then exits | Run-once |
+| API | `fsh-starter-api` | The ASP.NET Core API (`net10.0`) | Long-running |
+| Admin app | `fsh-starter-admin` | Operator React + Vite SPA on **:5173** | Long-running |
+| Dashboard app | `fsh-starter-dashboard` | Tenant React + Vite SPA on **:5174** (with SSE live feed) | Long-running |
+
+
+The `fsh-starter-*` resource names — and the Docker volume names — are derived
+from the AppHost's assembly name. A CLI-scaffolded app (say `Acme.Store`) gets
+`acme-store-api`, `acme-store-admin`, and so on, so two FSH-based apps on one
+machine never collide on container or volume names. The third-party infra
+(`postgres`, `redis`, `minio`) and the `fsh-db` database keep stable names.
+
The Aspire dashboard opens automatically and shows every resource's state,
logs, traces, and endpoints. The API's Scalar UI is at `/scalar`.
The API waits for Postgres and Valkey to be healthy **and** for the one-shot
-jobs (`minio-init`, `fsh-db-migrator`, `fsh-demo-seeder`) to finish before it starts. So the API
+jobs (`minio-init`, `fsh-starter-db-migrator`, `fsh-starter-demo-seeder`) to finish before it starts. So the API
never boots against an unmigrated database or a missing bucket — no retry loops,
no first-request 500s.
@@ -69,8 +77,9 @@ browser PUTs from the admin (`:5173`) and dashboard (`:5174`) origins via
### The migrator is the production deploy step too
-`fsh-db-migrator` is the same `FSH.Starter.DbMigrator` project you run as an
-explicit step in production (`dotnet run --project ... -- apply`). The database
+The `fsh-starter-db-migrator` resource runs the same `FSH.Starter.DbMigrator`
+project you run as an explicit step in production (published as the
+`fsh-db-migrator` image; `dotnet run --project ... -- apply`). The database
is **never** migrated at API startup — locally or in the cloud. One mechanism,
two contexts.
diff --git a/src/content/docs/deployment/database-migrations.mdx b/src/content/docs/deployment/database-migrations.mdx
index 0d89220d..089a466d 100644
--- a/src/content/docs/deployment/database-migrations.mdx
+++ b/src/content/docs/deployment/database-migrations.mdx
@@ -69,8 +69,8 @@ dotnet run --project src/Host/FSH.Starter.DbMigrator -- apply --catalog-only
## Local development
When you run the stack via Aspire, the migrator runs **for you**: the
-`fsh-db-migrator` resource executes `apply --seed` on each AppHost launch (so the
-root admin `admin@root.com` is seeded), then a dev-only `fsh-demo-seeder` resource
+`fsh-starter-db-migrator` resource executes `apply --seed` on each AppHost launch (so the
+root admin `admin@root.com` is seeded), then a dev-only `fsh-starter-demo-seeder` resource
runs `seed-demo` to provision the `acme`/`globex` demo tenants and their users. The
API is gated on both (`WaitForCompletion`), so it never starts against an
unmigrated database and the demo logins work the moment the dashboard loads. See
diff --git a/src/content/docs/frontend/admin.mdx b/src/content/docs/frontend/admin.mdx
index 17cd2408..db841caf 100644
--- a/src/content/docs/frontend/admin.mdx
+++ b/src/content/docs/frontend/admin.mdx
@@ -253,7 +253,7 @@ The dev server proxies API calls to the backend's URL configured in `clients/adm
VITE_API_BASE_URL=http://localhost:5000
```
-The kit's Aspire AppHost wires this automatically when you run via `dotnet run --project src/Host/FSH.Starter.AppHost` — both `fsh-api` and `fsh-admin` come up, the admin app discovers the API's URL via Aspire's service discovery.
+The kit's Aspire AppHost wires this automatically when you run via `dotnet run --project src/Host/FSH.Starter.AppHost` — both `fsh-starter-api` and `fsh-starter-admin` come up, the admin app discovers the API's URL via Aspire's service discovery.
## Build + deploy
diff --git a/src/content/docs/frontend/dashboard.mdx b/src/content/docs/frontend/dashboard.mdx
index 6fe6c299..19288d88 100644
--- a/src/content/docs/frontend/dashboard.mdx
+++ b/src/content/docs/frontend/dashboard.mdx
@@ -207,7 +207,7 @@ npm run dev # http://localhost:5174 with HMR
The dev server proxies API calls to the backend's URL configured in `clients/dashboard/.env`.
-When run via the kit's Aspire AppHost, the dashboard wires automatically — `fsh-api`, `fsh-admin`, `fsh-dashboard` all come up with one command, and service discovery handles the URLs.
+When run via the kit's Aspire AppHost, the dashboard wires automatically — `fsh-starter-api`, `fsh-starter-admin`, `fsh-starter-dashboard` all come up with one command, and service discovery handles the URLs.
## Related
diff --git a/src/content/docs/getting-started/introduction.mdx b/src/content/docs/getting-started/introduction.mdx
index a927c02e..fee1eff0 100644
--- a/src/content/docs/getting-started/introduction.mdx
+++ b/src/content/docs/getting-started/introduction.mdx
@@ -119,7 +119,7 @@ app.UseHeroMultiTenantDatabases();
app.UseHeroPlatform(p => { p.MapModules = true; /* ... */ });
```
-The API never mutates data on startup. Demo data (acme/globex tenants, sample catalog/tickets/chat) is provisioned by `FSH.Starter.DbMigrator seed-demo`, which Aspire runs automatically on launch (the `fsh-demo-seeder` resource) — so the demo logins work out of the box.
+The API never mutates data on startup. Demo data (acme/globex tenants, sample catalog/tickets/chat) is provisioned by `FSH.Starter.DbMigrator seed-demo`, which Aspire runs automatically on launch (the `fsh-starter-demo-seeder` resource) — so the demo logins work out of the box.
## Stack