diff --git a/src/content/docs/changelog/index.mdx b/src/content/docs/changelog/index.mdx index e483d6e2..ad2fbba0 100644 --- a/src/content/docs/changelog/index.mdx +++ b/src/content/docs/changelog/index.mdx @@ -13,6 +13,7 @@ Notable changes to the kit, newest first. ## 2026-11-03 +- **Dependencies: the React apps are on the latest stable versions (chore).** Both apps move to **Vite 8** (Rolldown) with `@vitejs/plugin-react` 6, **TypeScript 6.0.3** (held below 6.1 until `typescript-eslint` supports 7), **ESLint 10**, `eslint-plugin-react-hooks` 7, **lucide-react 1.x**, React 19.3 and the current minors of TanStack Query, React Router, Radix, Tailwind 4.3, SignalR and i18next; the admin app moves to **zod 4** with `@hookform/resolvers` 7. The container build and Frontend CI run on **Node 26** (LTS), the runtime image is pinned to `nginx:1.31.8-alpine`, and `engines.node` is now `^20.19.0 || >=22.13.0`. If you forked the apps: `tsconfig` drops the deprecated `baseUrl`; `eslint-plugin-jsx-a11y` (no ESLint 10 release yet) is replaced by the `eslint-plugin-jsx-a11y-x` fork under the same `jsx-a11y` rule names; and the React Compiler-aware hooks rules now fail the lint on `setState` called directly in an effect, refs read or written during render, and components created during render, so your own pages may need the same fixes. zod 4 deprecates `.email()`/`.url()` and `{ message }` in favour of `z.email()`/`z.url()` and `{ error }`. The admin dev proxy now forwards SignalR's WebSocket upgrade. See [Development](/docs/frontend/development/#linting), [Prerequisites](/docs/getting-started/prerequisites/) and PR [#1461](https://github.com/fullstackhero/dotnet-starter-kit/pull/1461); part of [#1453](https://github.com/fullstackhero/dotnet-starter-kit/issues/1453). - **Dependencies: the backend stack is on the latest stable versions (chore).** ASP.NET Core, EF Core and `Microsoft.Extensions.*` move to the **10.0.14** patch line (with the `System.Security.Cryptography.Xml` / `.Pkcs` pins), .NET **Aspire 13.6.4** (hosting packages and AppHost SDK), Finbuckle.MultiTenant 10.1.6, FluentValidation 12.2.0, OpenTelemetry 1.20.1 (EF Core and StackExchange.Redis instrumentation on 1.20.1-beta.1), StackExchange.Redis 3.4.31, Scalar.AspNetCore 2.18.7, MailKit/MimeKit 4.18.2, AWSSDK.S3 4.0.104.8, QuestPDF 2026.9.1, Testcontainers 4.16.0 and Spectre.Console.Cli 0.57.2. `global.json` now asks for SDK `10.0.400` or later (still `latestFeature`). Containers: Postgres is **18** everywhere (Docker Compose already was; the Testcontainers harness and the CI migrator smoke move from 17), Valkey 9.1.3, RustFS 1.0.4, Mailpit v1.33.0, `amazon/aws-cli` 2.39.3, and RedisInsight is pinned to 3.8.0 instead of `latest`. Aspire 13.6 still defaults to `postgres:18.3`, so an Aspire data volume from 13.4 or later keeps working; only a volume created before 13.4 needs the [wipe](/docs/getting-started/troubleshooting/). Terraform's AWS provider constraint moves to `~> 6.71` (Terraform 1.15.4 is still the floor). If you forked the CLI, Spectre.Console.Cli 0.57 made `ExecuteAsync` overrides `public`. Part of [#1453](https://github.com/fullstackhero/dotnet-starter-kit/issues/1453); see PR [#1460](https://github.com/fullstackhero/dotnet-starter-kit/pull/1460). - **Frontends: i18n follow-ups (fix).** The admin language switcher now saves with `If-Match`, so a profile edit made in between is no longer silently overwritten (it retries once on `412`). The dashboard container now honours `FSH_DEFAULT_LANGUAGE` like the admin one; before, a containerized dashboard always started in `en-US`. `deploy/docker` and Terraform pass the setting to both apps. The dashboard no longer matches the English text of the deactivated-tenant error, because the API always sends its `code` now. See [Internationalization](/docs/cross-cutting-concerns/internationalization/#per-deployment-default) and [#1459](https://github.com/fullstackhero/dotnet-starter-kit/pull/1459). - **Identity: a role can no longer hold the same permission twice (fix, migration).** `identity.RoleClaims` had no uniqueness, so two API instances starting at once after a release that adds a permission, or the tenant seeder overlapping the startup sync, could both insert the same grant and leave a duplicate row behind with nothing in the logs. Authorization was not affected, but the table drifted. The new `AddRoleClaimsUniqueIndex` Identity migration first deletes existing duplicates (keeping the lowest `Id` per `(RoleId, ClaimType, ClaimValue)`) and then adds a unique index on those columns, which replaces the `RoleId`-only index. `RolePermissionSyncer` and `IdentityDbInitializer` treat a unique violation on that index as another writer having inserted the grant first and log it at Information instead of failing, and `PUT /api/v1/identity/{id}/permissions` collapses a permission repeated in the request. Run the DbMigrator `apply` as usual; claims with a `NULL` value are not affected. See [Authorization](/docs/security/authorization/#the-role-permission-syncer), [#1435](https://github.com/fullstackhero/dotnet-starter-kit/issues/1435) and [#1458](https://github.com/fullstackhero/dotnet-starter-kit/pull/1458). diff --git a/src/content/docs/deployment/ci-cd.mdx b/src/content/docs/deployment/ci-cd.mdx index 125e2d59..f367fab1 100644 --- a/src/content/docs/deployment/ci-cd.mdx +++ b/src/content/docs/deployment/ci-cd.mdx @@ -77,7 +77,7 @@ need a `NUGET_API_KEY` repository secret to push packages to NuGet.org. ## frontend.yml - lint, build, E2E -Triggers on pushes and PRs to `main` (and manual dispatch). A `Detect changes` job gates the work on `clients/**`. Both apps run as a matrix (`admin`, `dashboard`) on **Node 22** with npm caching. +Triggers on pushes and PRs to `main` (and manual dispatch). A `Detect changes` job gates the work on `clients/**`. Both apps run as a matrix (`admin`, `dashboard`) on **Node 26** with npm caching. | Job | Runs when | What it does | |---|---|---| diff --git a/src/content/docs/frontend/admin.mdx b/src/content/docs/frontend/admin.mdx index 35e1da1e..1513b5b9 100644 --- a/src/content/docs/frontend/admin.mdx +++ b/src/content/docs/frontend/admin.mdx @@ -23,15 +23,15 @@ seo: | | Version | Used for | |---|---|---| | React | 19.x | UI framework | -| Vite | 7.x | Dev server + build | -| TypeScript | 5.x | Type safety | +| Vite | 8.x | Dev server + build (Rolldown) | +| TypeScript | 6.0 | Type safety | | TanStack Query | 5.x | Server-state cache + mutations | | React Router | 7.x | Routing + protected routes | -| react-hook-form + zod | 7.x / 3.x | Forms + schema validation (admin only - the dashboard doesn't use them) | +| react-hook-form + zod | 7.x / 4.x | Forms + schema validation (admin only - the dashboard doesn't use them) | | @microsoft/signalr | 10.x | Realtime connection to the kit's hub | | Tailwind CSS | 4.x | Styling (shadcn-style, with CVA) | | Radix UI | 1.x–2.x | Headless primitives (Dialog, DropdownMenu, etc.) | -| Lucide | 0.4xx | Icon set | +| Lucide | 1.x | Icon set | | Playwright | 1.x | Route-mocked E2E tests (`npm run test:e2e`) | All pinned in `clients/admin/package.json`. @@ -226,7 +226,7 @@ npm install npm run dev # http://localhost:5173 with HMR ``` -The Vite dev server proxies `/api`, `/health`, `/openapi`, and `/scalar` to the backend - `http://localhost:5030` by default, overridable with a `VITE_API_BASE_URL` env var (this var only steers the **dev proxy target**; it is never baked into a build). Runtime configuration - API base URL, default tenant, inactivity timings - comes from `public/config.json`, fetched once at boot before React mounts. +The Vite dev server proxies `/api` (with WebSocket forwarding for SignalR), `/health`, `/openapi`, and `/scalar` to the backend - `http://localhost:5030` by default, overridable with a `VITE_API_BASE_URL` env var (this var only steers the **dev proxy target**; it is never baked into a build). Runtime configuration - API base URL, default tenant, inactivity timings - comes from `public/config.json`, fetched once at boot before React mounts. The kit's Aspire AppHost wires all of this automatically when you run `dotnet run --project src/Host/FSH.Starter.AppHost` - the API, admin, and dashboard all come up together. diff --git a/src/content/docs/frontend/architecture.mdx b/src/content/docs/frontend/architecture.mdx index c488f2b4..5c99ff7b 100644 --- a/src/content/docs/frontend/architecture.mdx +++ b/src/content/docs/frontend/architecture.mdx @@ -1,6 +1,6 @@ --- title: Frontend architecture -lastUpdated: 2026-10-14 +lastUpdated: 2026-11-03 description: Shared patterns across the admin + dashboard apps - folder layout, API client, route guards, realtime context, error handling, ProblemDetails parsing. sidebar: label: Architecture @@ -22,7 +22,7 @@ If you're forking only the dashboard (deleting admin), copy admin's audit-log vi ``` clients/{app}/ -├── package.json React 19, Vite 7, TS 5.x, TanStack Query, Radix, etc. +├── package.json React 19, Vite 8, TS 6.0, TanStack Query, Radix, etc. ├── vite.config.ts Vite + React + Tailwind plugins + dev proxy config ├── tsconfig.json ├── index.html Single-page-app shell diff --git a/src/content/docs/frontend/dashboard.mdx b/src/content/docs/frontend/dashboard.mdx index 0cd4d818..3a2b2079 100644 --- a/src/content/docs/frontend/dashboard.mdx +++ b/src/content/docs/frontend/dashboard.mdx @@ -1,6 +1,6 @@ --- title: Tenant dashboard -lastUpdated: 2026-10-14 +lastUpdated: 2026-11-03 description: The end-user-facing React + Vite app at clients/dashboard - catalog, chat, files, tickets, invoices, identity admin, plus real-time SignalR + SSE feeds. sidebar: label: Tenant dashboard @@ -20,7 +20,7 @@ seo: ## Tech stack -Same shape as the [admin console](/docs/frontend/admin/) - React 19 + Vite 7 + TypeScript + TanStack Query v5 + React Router 7 + Tailwind 4 + Radix + Lucide. Differences worth knowing: +Same shape as the [admin console](/docs/frontend/admin/) - React 19 + Vite 8 + TypeScript + TanStack Query v5 + React Router 7 + Tailwind 4 + Radix + Lucide. Differences worth knowing: | | Used for | |---|---| diff --git a/src/content/docs/frontend/development.mdx b/src/content/docs/frontend/development.mdx index bfec88ae..113b8349 100644 --- a/src/content/docs/frontend/development.mdx +++ b/src/content/docs/frontend/development.mdx @@ -1,6 +1,6 @@ --- title: Local development -lastUpdated: 2026-10-14 +lastUpdated: 2026-11-03 description: Running the React frontends with Vite HMR, building for production, deploying to static hosts or behind Nginx, runtime config via /config.json. sidebar: label: Local development @@ -107,7 +107,7 @@ The dashboard's variant swaps `dashboardUrl` for a `demoMode` flag (login-page d ### The container pattern -`clients/{app}/Dockerfile` is a two-stage build - `node:22-alpine` runs `npm ci && npm run build`, then `nginx:alpine` serves `dist/`. The entrypoint renders the runtime config before starting Nginx: +`clients/{app}/Dockerfile` is a two-stage build - `node:26-alpine` runs `npm ci && npm run build`, then `nginx:1.31.8-alpine` (pinned) serves `dist/`. The entrypoint renders the runtime config before starting Nginx: ```sh # clients/{app}/docker/docker-entrypoint.sh @@ -241,7 +241,7 @@ Tests live under `clients/{app}/tests/`. There is no unit-test runner (Vitest) w ## Linting -ESLint is wired (flat config at `clients/{app}/eslint.config.js`, extending the React + TypeScript + a11y rule sets): +ESLint 10 is wired (flat config at `clients/{app}/eslint.config.js`, extending the React + TypeScript + a11y rule sets). The React hooks rules are the React Compiler-aware set from `eslint-plugin-react-hooks` 7, so a `setState` called synchronously in an effect body, a ref read or written during render, or a component defined inside another component is a lint error. The a11y rules come from `eslint-plugin-jsx-a11y-x`, a fork of `eslint-plugin-jsx-a11y` with the same rules, because the original has no ESLint 10 release yet; it is registered under the `jsx-a11y` name, so rule ids are unchanged: ```bash npm run lint # report diff --git a/src/content/docs/frontend/index.mdx b/src/content/docs/frontend/index.mdx index 98dc2c86..f6f836ab 100644 --- a/src/content/docs/frontend/index.mdx +++ b/src/content/docs/frontend/index.mdx @@ -1,13 +1,13 @@ --- title: Overview -lastUpdated: 2026-06-11 +lastUpdated: 2026-11-03 description: Two React + Vite + TypeScript apps ship with the kit - an admin console for operators and a tenant dashboard for end users. sidebar: order: 1 pageType: guide seo: title: 'Frontend in .NET 10 - React + Vite admin + dashboard' - description: 'fullstackhero ships two production React 19 + Vite 7 + TypeScript frontends - clients/admin (operator console) and clients/dashboard (tenant-facing).' + description: 'fullstackhero ships two production React 19 + Vite 8 + TypeScript frontends - clients/admin (operator console) and clients/dashboard (tenant-facing).' keywords: 'fullstackhero react frontend, vite admin console, react dashboard .net 10, jwt auth react vite, tenant theme react' --- diff --git a/src/content/docs/getting-started/prerequisites.mdx b/src/content/docs/getting-started/prerequisites.mdx index 44074081..28673e4f 100644 --- a/src/content/docs/getting-started/prerequisites.mdx +++ b/src/content/docs/getting-started/prerequisites.mdx @@ -7,7 +7,7 @@ sidebar: pageType: guide seo: title: 'Prerequisites - .NET 10 SDK, Docker, Node setup' - description: 'Tools you need before running fullstackhero locally: .NET 10 SDK, Docker (for Postgres, Valkey, and RustFS containers), and optional Node 20+ for the React frontends.' + description: 'Tools you need before running fullstackhero locally: .NET 10 SDK, Docker (for Postgres, Valkey, and RustFS containers), and optional Node 20.19+ or 22.13+ for the React frontends.' keywords: '.NET 10 SDK install, fullstackhero prerequisites, .NET development environment' --- @@ -23,7 +23,7 @@ No separate Aspire install is needed: the AppHost project pulls the Aspire SDK ( ## Optional -- **Node 20+** - only if you'll run the React + Vite frontends in `clients/admin` and `clients/dashboard` (both declare `"node": ">=20"`). +- **Node 20.19+ or 22.13+** - only if you'll run the React + Vite frontends in `clients/admin` and `clients/dashboard` (both declare `"node": "^20.19.0 || >=22.13.0"`, the floor Vite 8 and ESLint 10 need). CI and the container builds use Node 26, the current LTS. - **PostgreSQL** - install locally only if you'd rather not run Postgres in a container. Otherwise Aspire provisions one for you (the kit's containers run Postgres 18). - **Valkey** - same. The kit runs Valkey 9 in its containers (a Redis-compatible, BSD-licensed Redis fork); any Redis-protocol server also works.