This repository contains the uFlex Developer Web, the internal platform/operations web app used by the KinIoT technical team (ROLE_DEVELOPER) to manage the global fleet of uFlex IoT rehabilitation kits.
It is part of the broader uFlex ecosystem (embedded firmware, edge gateway, REST API, clinic web, patient mobile, and this developer web) and is intentionally not a customer-facing product. It is a developer/operator console for hardware inventory, clinic fulfillment, fleet health, and edge gateway account operations.
The app authenticates a platform developer against the uFlex REST API and exposes a role-gated area (ROLE_DEVELOPER only — clinic admins and physiotherapists are redirected to a forbidden screen). From there the developer manages the device lifecycle that the clinic product cannot:
- Kits are seeded/registered as global stock (no owning clinic) and auto-assigned to a clinic when its subscription is paid; this app is where stock is curated and shortfalls are resolved.
- Edge gateways authenticate to the API with
ROLE_EDGEservice accounts that are provisioned and revoked here.
| Area | What it does |
|---|---|
| Overview | Cross-clinic inventory snapshot — total, in stock, assigned, available, in maintenance, retired, and per-clinic counts. |
| Inventory | Manage global stock: list stock devices, register kits one-by-one or in bulk, retire devices, and delete units. |
| Fulfillment | Queue of clinics that requested/paid for more kits than they own; Fulfill assigns available stock on demand. |
| Fleet health | Cross-clinic tabs for offline, low-battery, and needs-calibration devices, including battery and last-seen data. |
| Edge gateways | Provision, list, and revoke ROLE_EDGE service accounts; generated credentials are displayed once and can be copied. |
| Area | Technology |
|---|---|
| Framework | React 19 + Vite 8 (JavaScript, ESM) |
| UI | shadcn/ui (Nova preset) · Radix primitives · Tailwind CSS v4 |
| State | Zustand (per-context stores) |
| Routing | React Router 7 |
| Forms | React Hook Form + Zod |
| i18n | i18next + react-i18next (default English) |
| Fonts | Geist + Geist Mono (self-hosted via Fontsource) |
| Icons | lucide-react |
| Tooling | ESLint · pnpm (Node ≥24, pnpm ≥11) |
The app follows a DDD-style layered architecture organized by bounded context, mirroring uflex-clinic-web. Each context under src/ is split into domain / application / infrastructure / presentation. Cross-cutting shadcn primitives live inside the shared context (not at the project root).
src/
├── main.jsx · App.jsx · index.css # bootstrap · routes · Tailwind/shadcn tokens + Geist
├── iam/ # authentication
│ ├── domain/ # sign-in command, authenticated-user entity
│ ├── application/ # auth store (Zustand): token, isDeveloper, sign in/out
│ ├── infrastructure/ # sign-in DTOs, assembler, api
│ └── presentation/ # sign-in screen
├── device/ # inventory · overview · fulfillment · fleet health
│ ├── domain/ application/ infrastructure/ presentation/
├── edge/ # ROLE_EDGE service accounts
│ ├── domain/ application/ infrastructure/ presentation/
├── shared/
│ ├── application/ # theme store (dark default) · i18n init
│ ├── infrastructure/ # env, http (Bearer + 401 handling), cn util
│ └── presentation/ # app-shell, theme/language switchers, route guards,
│ # forbidden/not-found, and components/ui (shadcn)
└── i18n/ # en.json (default) · es.json
Adapted from the clinic-web assembler pattern (commands and DTOs are plain objects + JSDoc since this is JavaScript):
Command (domain) → Request (infra) → Api/http (infra) → Response/Resource (infra) → Store (application)
http(shared/infrastructure/http.js) builds URLs fromenvironment+buildApiUrl, attachesAuthorization: Bearer <token>fromlocalStorage, and on401clears the session and redirects to sign-in.- Route guards —
RequireAuthredirects anonymous users to/sign-in;RequireDeveloperredirects non-developers to/forbidden. Both wrap the authenticatedAppShell. - Theming — CSS variables in
index.css; dark is the default, toggled via a.darkclass on<html>and persisted inlocalStorage. Primary is turquoise#48CBB6; seeDESIGN.md. - i18n — keys in
src/i18n/{en,es}.json, default English, language persisted inlocalStorage.
- Node ≥ 24 (
.nvmrc/.node-versionpin the major) and pnpm ≥ 11 (packageManagerfield, via Corepack). - A running instance of the uFlex REST API reachable at the configured base URL, with a
ROLE_DEVELOPERaccount.
The API base URL is read from VITE_API_BASE_URL (see .env.example); it already includes the /api/v1 prefix:
cp .env.example .env
# VITE_API_BASE_URL=http://localhost:8080/api/v1pnpm install # install dependencies
pnpm dev # dev server at http://localhost:5151
pnpm build # production build
pnpm preview # serve the production build
pnpm lint # ESLintThis project uses pnpm only. Package-manager settings live in
pnpm-workspace.yaml—ignoreScripts(no dependency lifecycle scripts) andminimumReleaseAge(a 7-day supply-chain delay on new versions). Vendored shadcn primitives undersrc/shared/presentation/components/uiare excluded from linting so they stay upgradable verbatim.
User-facing strings are never hardcoded; the presentation layer reads them via react-i18next. Translations live in src/i18n/en.json (default/fallback) and src/i18n/es.json, and the active language persists across sessions.
- Design System — colors, typography (Geist), theming, and component guidance.
Active internal development. The current app implements the developer operations surface against uflex-rest-api:
- Developer sign-in with role-gated access (
ROLE_DEVELOPER). - Authenticated routes for
/overview,/inventory,/fulfillment,/fleet-health, and/edge. - Global device overview with fleet KPIs and per-clinic device counts.
- Stock inventory management with single registration, batch registration, retire, and delete actions.
- Fulfillment queue with on-demand stock assignment to clinics.
- Fleet health monitoring for offline, low-battery, and needs-calibration devices.
- Edge gateway service-account management with one-time credential display on provisioning.
There is no configured test runner yet; validation is currently via pnpm lint, pnpm build, and manual checks against a reachable API using a ROLE_DEVELOPER account. Firmware/OTA management, audit logs, and live telemetry remain out of scope for this frontend.