Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/content/docs/changelog/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Notable changes to the kit, newest first.

## 2026-11-03

- **Frontend containers: the inactivity timeout is configurable from the environment (fix).** Both apps read `inactivityIdleMs` and `inactivityWarningMs` from `/config.json`, but the container's `config.json.template` never carried them, so an operator could not change the auto sign-out time without rebuilding the image. The template now renders them from `FSH_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS`. Unset or empty keeps the built-in timings (admin 10 minutes, dashboard 20, each with a 60-second warning), so existing deployments behave as before; a value that is not a positive integer stops the container at start with a clear error rather than rendering invalid JSON. `deploy/docker` exposes them as `FSH_ADMIN_INACTIVITY_IDLE_MS`, `FSH_DASHBOARD_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS` in `.env`. The Terraform static-site `runtime_config` and the Aspire dev setup are unchanged. See [Frontend development](/docs/frontend/development/#the-container-pattern) and [#1442](https://github.com/fullstackhero/dotnet-starter-kit/pull/1442).
- **Dashboard: the overview welcomes the tenant by its name (fix).** The first-run card on a tenant with no subscription read "Welcome to" followed by the tenant identifier (for example `qpb2edshbj`), and the header caption showed the same identifier, because both came from the token's `tenant` claim. Both now use the tenant name from `GET /api/v1/tenants/me/status`, which the overview already loads for its "Valid for" card, and fall back to the identifier while that call is loading or has failed. No backend change. See [Tenant dashboard](/docs/frontend/dashboard/#page-inventory) and [#1437](https://github.com/fullstackhero/dotnet-starter-kit/pull/1437).
- **Both apps: non-ASCII claims in the access token now render correctly (fix).** `decodeJwt` decoded the token payload with a bare `atob`, which returns one character per byte, while the payload is UTF-8. A display name like "Comitê de Ética" therefore showed as "Comitê de Ética" in the user menu and the overview greeting, even though the token and the database were correct. The payload bytes are now decoded as UTF-8 in both the dashboard and the admin console. No configuration change. See PR [#1439](https://github.com/fullstackhero/dotnet-starter-kit/pull/1439).

Expand Down
4 changes: 2 additions & 2 deletions src/content/docs/frontend/architecture.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Frontend architecture
lastUpdated: 2026-06-11
lastUpdated: 2026-10-14
description: Shared patterns across the admin + dashboard apps - folder layout, API client, route guards, realtime context, error handling, ProblemDetails parsing.
sidebar:
label: Architecture
Expand Down Expand Up @@ -261,7 +261,7 @@ In dev, Vite serves `public/config.json`; in production, the Nginx container ren

### Inactivity auto sign-out

Both apps auto-sign-out idle sessions: admin after 10 minutes, dashboard after 20, each with a 60-second warning countdown - all four numbers configurable per deploy in `config.json`. The last-activity timestamp is shared across tabs via the `fsh.lastActivity` localStorage key so activity in any tab keeps the whole session alive.
Both apps auto-sign-out idle sessions: admin after 10 minutes, dashboard after 20, each with a 60-second warning countdown - all four numbers configurable per deploy in `config.json`. In the container images set `FSH_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS` (milliseconds); see [development](/docs/frontend/development/#the-container-pattern). The last-activity timestamp is shared across tabs via the `fsh.lastActivity` localStorage key so activity in any tab keeps the whole session alive.

## What both apps don't do

Expand Down
17 changes: 16 additions & 1 deletion src/content/docs/frontend/development.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Local development
lastUpdated: 2026-09-26
lastUpdated: 2026-10-14
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
Expand Down Expand Up @@ -113,6 +113,9 @@ The dashboard's variant swaps `dashboardUrl` for a `demoMode` flag (login-page d
# clients/{app}/docker/docker-entrypoint.sh
: "${FSH_API_URL:?FSH_API_URL is required (e.g. https://api.example.com)}"
: "${FSH_DEFAULT_TENANT:=root}"
: "${FSH_INACTIVITY_IDLE_MS:=600000}" # admin; the dashboard defaults to 1200000
: "${FSH_INACTIVITY_WARNING_MS:=60000}"
# ...exits with an error unless both inactivity values are positive integers

envsubst < /etc/fsh/config.json.template \
> /usr/share/nginx/html/config.json
Expand All @@ -127,6 +130,8 @@ The template lives at `/etc/fsh/config.json.template`, outside the web root, so
{
"apiBase": "${FSH_API_URL}",
"defaultTenant": "${FSH_DEFAULT_TENANT}",
"inactivityIdleMs": ${FSH_INACTIVITY_IDLE_MS},
"inactivityWarningMs": ${FSH_INACTIVITY_WARNING_MS},
"dashboardUrl": "${FSH_DASHBOARD_URL}"
}
```
Expand All @@ -139,6 +144,16 @@ docker run -e FSH_API_URL=https://api.example.com -e FSH_DASHBOARD_URL=https://a

The same image runs everywhere; only env vars differ.

| Variable | Apps | Default | Maps to |
|---|---|---|---|
| `FSH_API_URL` | both | required | `apiBase` |
| `FSH_DASHBOARD_URL` | admin | required | `dashboardUrl` |
| `FSH_DEFAULT_TENANT` | both | `root` | `defaultTenant` |
| `FSH_INACTIVITY_IDLE_MS` | both | admin `600000` (10 min), dashboard `1200000` (20 min) | `inactivityIdleMs` |
| `FSH_INACTIVITY_WARNING_MS` | both | `60000` (60 s) | `inactivityWarningMs` |

The two inactivity values are bare JSON numbers in the template, so the entrypoint validates them: unset or empty keeps the default, and anything that is not a positive integer (`abc`, `0`, `-5`, `1.5`) stops the container at start with an error instead of serving a broken `config.json`. The entrypoint defaults mirror the ones in each app's `src/env.ts`; change both together. The Docker Compose deployment reads `FSH_ADMIN_INACTIVITY_IDLE_MS`, `FSH_DASHBOARD_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS` from `.env`, because the two apps default to different idle times.

### Reading runtime config in code

```ts
Expand Down