Workspace-aware Next.js control plane for Noderax. It brings inventory, live telemetry, task operations, teams, members, setup, and platform administration into a single UI.
noderax-web is the frontend for noderax-api. It uses the Next.js App Router, route-handler proxy endpoints, React Query, Zustand, and Socket.IO-based realtime state sync.
Current product surface:
- First-run setup screen for installer-managed deployments with PostgreSQL, Redis, and optional SMTP validation
- Workspace selection and default-workspace fallback
- Workspace-scoped dashboard, nodes, tasks, events, scheduled tasks, members, and teams
- Platform-admin global user directory with invite-first create, edit, resend invite, activate, deactivate, and guarded delete flows
- Public auth lifecycle routes for:
- password login
- OIDC login buttons for enabled providers
- MFA challenge / recovery verification
- invitation acceptance
- forgot password
- reset password
- Account security controls with QR-based TOTP MFA enrollment and recovery codes
- Platform identity controls for SSO provider management and provider testing
- Platform-admin audit view plus workspace audit history
- Workspace task templates and team-targeted task execution flows
- Unified settings surface with:
AccountWorkspacePlatformfor platform admins
- GitHub-style workspace settings with:
- workspace profile editing
- workspace timezone control
- default-workspace selection
- dangerous workspace deletion flow
- Linux node detail with live telemetry, packages, running tasks, and event history
- Linux node interactive terminal route with live xterm.js console and persisted transcript history
- Task detail with live lifecycle and logs
- Platform-admin workspaces page
- User-centric membership management:
Usersis the only account creation surface- workspace members are assigned from existing accepted active users
- teams can only add active members already attached to the workspace
- teams can own nodes and be used as run/schedule targets
- Workspace archive UX:
- archived banner inside workspace routes
- archive / restore actions
- read-only operator controls while archived
- Workspace-scoped topbar search with grouped suggestions for nodes, tasks, schedules, events, members, and teams
- Next.js 16
- React 19
- TypeScript
- TanStack React Query
- Zustand
- Socket.IO Client
- Radix + Base UI primitives
- Tailwind CSS 4
- Zod
- React Hook Form
- Sonner
Browser traffic is session-based and proxied through Next.js.
- The user signs in on
/login. app/api/auth/loginauthenticates against the API.- JWT-backed session data is stored in cookies.
- Browser-side REST calls go through
app/api/proxy/[...path]. - The proxy forwards the access token upstream.
- Workspace selection is persisted via the
noderax_workspacecookie. - General realtime access uses
app/api/auth/realtime-tokenand connects to/realtime. - Interactive terminal access uses the same auth token flow but connects to the dedicated
/terminalnamespace.
The current primary UI uses workspace-scoped routes:
/workspaces/w/[workspaceSlug]/dashboard/w/[workspaceSlug]/nodes/w/[workspaceSlug]/nodes/[id]/w/[workspaceSlug]/nodes/[id]/terminal/w/[workspaceSlug]/nodes/[id]/packages/w/[workspaceSlug]/tasks/w/[workspaceSlug]/tasks/[id]/w/[workspaceSlug]/scheduled-tasks/w/[workspaceSlug]/events/w/[workspaceSlug]/audit/w/[workspaceSlug]/members/w/[workspaceSlug]/teams/w/[workspaceSlug]/workspace-settings
Additional top-level routes:
/login/forgot-password/invite/[token]/reset-password/[token]/settings/setup/users/audit
The top-level non-workspace pages continue to exist as convenience or fallback surfaces, but the workspace-scoped routes are the main operator path.
- JWT login with cookie-based session handling
- OIDC login start/callback through public auth handlers
- MFA challenge and recovery-code flows during login
- Invite acceptance and password reset flows through public auth handlers
- Next.js proxy layer over
noderax-api - Workspace-aware navigation and workspace cookie persistence
- Default workspace fallback when a prior workspace disappears
- Platform-admin workspace creation and workspace inventory
- Workspace archive / restore controls with read-only UI states
- Workspace member and team management built on top of the global user directory
- Task templates with prefill/save UX in task creation flows
- Team-targeted task runs and schedule targeting
- Linux node maintenance UX and node telemetry visibility
- Interactive terminal UX with:
- xterm.js live console tunneled through the agent
- recent session history
- persisted transcript timeline
- transcript "Terminal view" rendering
- live-session status messaging and termination feedback
- 5-minute reattach grace window after leaving the page
- Platform and workspace audit surfaces
- Workspace-scoped topbar search with grouped suggestions and
?q=route handoff - Unified settings page:
- account preferences
- change password
- token management and MFA enrollment
- workspace settings
- platform runtime settings, SMTP testing, and identity provider management
- Platform-admin user lifecycle management with self-protection and last-admin guardrails
- Task operations:
- on-demand task runs
- multi-node batch dispatch
- team-targeted runs
- scheduled task creation
- cancel flow for active tasks
- Package management through node detail
- Live node telemetry and task lifecycle updates
platform_admin- can create workspaces
- can access
/users - can create, edit, activate, deactivate, and delete global users
- can access
Platformsettings - can choose the platform default workspace
- Workspace
ownerandadmin- can manage workspace settings
- can add existing active users as members
- can manage teams that are composed from workspace members
- can delete the workspace if it is not the current default
- Workspace
memberandviewer- can use read surfaces allowed by the API
The UI hides actions that the current session should not perform.
Usersis the platform-wide identity directory and the only place where new accounts are created.- New users are invited first. They activate themselves from the invite link before they can sign in or be assigned anywhere.
Membersdoes not create users inline. It assigns an existing accepted active user to the current workspace with a workspace role.Teamsare workspace-local groups built from active members, and they also act as operational owners for nodes and team-targeted task/schedule flows.- Inactive users remain visible in historical membership lists, but they cannot sign in and they cannot be added to new workspaces or teams.
- Removing a workspace membership also removes that user from every team in the same workspace.
The unified /settings page now contains:
Account- profile/session/preferences
- timezone preferences used across task scheduling displays
- persisted notification email preferences
- authenticated password change with forced re-login
- token management
- QR-based MFA enrollment, recovery-code regeneration, and disable flow
Workspace- workspace name and slug with automatic slug generation
- workspace timezone
- notification levels (INFO, WARNING, CRITICAL) for Email and Telegram
- archive / restore
- default-workspace status and selection
- danger zone with typed confirmation for deletion
Platform- installer-managed runtime settings for app, auth, database, Redis, mail, and agent behavior
- SMTP draft validation
- OIDC provider configuration and discovery testing
- visible only to
platform_admin
The app consumes these realtime events:
node.status.updatedmetrics.ingestedtask.createdtask.updatedevent.created
Important implementation notes:
- Node subscriptions are derived from active queries only
- Node detail cache writes are scoped to the matching
nodeId - Task detail cache writes are scoped to the matching
taskId - This prevents cross-node telemetry pollution when multiple nodes are visible in cache history
Surfaces kept fresh by realtime:
- workspace dashboard
- workspace node list
- node detail
- node terminal
- task detail
- recent event views
Terminal-specific notes:
- Live terminal traffic uses the separate
/terminalnamespace rather than the general/realtimestream - Only the session creator can attach to and control a live terminal session
- Persisted transcript chunks are polled while a session is active so the history panel stays current
- Leaving the page no longer closes the shell immediately; the UI advertises the 5-minute reattach window
Primary upstream routes:
POST /auth/loginGET /auth/providersGET /auth/oidc/:provider/startGET /auth/oidc/:provider/callbackPOST /auth/mfa/setup/initiatePOST /auth/mfa/setup/confirmPOST /auth/mfa/challenge/verifyPOST /auth/mfa/recovery/verifyPOST /auth/mfa/recovery/regenerateDELETE /auth/mfaGET /auth/invitations/:tokenPOST /auth/invitations/:token/acceptPOST /auth/password/forgotGET /auth/password/reset/:tokenPOST /auth/password/reset/:tokenGET /usersGET /users/mePOST /usersPOST /users/:userId/resend-invitePATCH /users/:userIdDELETE /users/:userIdPATCH /users/me/preferencesPOST /users/me/passwordGET /workspacesPOST /workspacesPATCH /workspaces/:workspaceIdDELETE /workspaces/:workspaceIdGET /workspaces/:workspaceId/membersGET /workspaces/:workspaceId/assignable-usersGET /workspaces/:workspaceId/searchGET /workspaces/:workspaceId/teamsGET /workspaces/:workspaceId/teams/:teamId/membersGET /workspaces/:workspaceId/task-templatesPOST /workspaces/:workspaceId/task-templatesPATCH /workspaces/:workspaceId/task-templates/:idPOST /workspaces/:workspaceId/nodes/:nodeId/terminal-sessionsGET /workspaces/:workspaceId/nodes/:nodeId/terminal-sessionsGET /workspaces/:workspaceId/terminal-sessions/:sessionIdGET /workspaces/:workspaceId/terminal-sessions/:sessionId/chunksPOST /workspaces/:workspaceId/terminal-sessions/:sessionId/terminateDELETE /workspaces/:workspaceId/task-templates/:idGET /workspaces/:workspaceId/nodesPOST /workspaces/:workspaceId/nodes/:id/teamPOST /workspaces/:workspaceId/nodes/:id/maintenance/enablePOST /workspaces/:workspaceId/nodes/:id/maintenance/disableGET /workspaces/:workspaceId/tasksPOST /workspaces/:workspaceId/tasks/teams/:teamIdGET /workspaces/:workspaceId/scheduled-tasksGET /workspaces/:workspaceId/eventsGET /workspaces/:workspaceId/metricsGET /workspaces/:workspaceId/audit-logsGET /audit-logsGET /platform-settingsPATCH /platform-settingsPOST /platform-settings/validate/smtpGET /setup/statusPOST /setup/validate/postgresPOST /setup/validate/redisPOST /setup/validate/smtpPOST /setup/install
Copy the example file:
cp .env.example .env.localCurrent variables:
NODERAX_API_URL=http://localhost:3000/api/v1
NEXT_PUBLIC_NODERAX_API_URL=http://localhost:3000/api/v1
NEXT_PUBLIC_NODERAX_WS_URL=http://localhost:3000/realtimeNotes:
NODERAX_API_URLis required.- Realtime connects to
/realtime, not/api/v1/realtime. - If
NEXT_PUBLIC_NODERAX_WS_URLis omitted, the app falls back to the API origin or browser origin. - The runtime can also be overridden by the
noderax_api_urlcookie during setup/onboarding flows.
Install dependencies:
pnpm installStart the dev server:
pnpm devUseful checks:
pnpm lint
pnpm typecheck
pnpm buildapp/
(auth)/login/ Login route
api/ Auth and proxy handlers
setup/ Installer UI
settings/ Unified settings
workspaces/ Platform workspace inventory
w/[workspaceSlug]/ Workspace-scoped app routes
components/
dashboard/
layout/
nodes/
settings/
tasks/
users/
workspaces/
ui/
lib/
api.ts
auth.ts
hooks/
noderax.ts
websocket.ts
workspace.ts
store/
useAppStore.ts
- Dashboard totals are still operational snapshots, not a full analytics product.
- Text search on some list views remains client-side.
- Interactive terminal or SSH sessions are not implemented.
- The UI assumes the API is the source of truth for role enforcement and workspace access.
- Realtime cache synchronization is centralized in
lib/hooks/use-realtime.ts. - Session and upstream token handling live in
app/api/auth/*andlib/auth.ts. - New control-plane features should normally flow through:
lib/api.ts->lib/hooks-> route/page -> UI component.
