User Portal
Internal documentation for authenticated user pages including the portal hub, access command center, unified dashboard, editor, workbench, and settings
User Portal
Core authenticated pages for member-level users include /user, /user/access, /user/dashboard, /user/editor, /user/workbench, /user/sites, /user/settings, and /user/email. All use SSR, require an authenticated session, and render with CosmicLayout + UserSidebar (collapsible, localStorage-persisted state).
User Portal Index (/user)
Hub page with quick actions into the unified dashboard, access command page, editor, and workbench. Quick links are feature-aware and derived from the authenticated user payload.
Access Command (/user/access)
Travel-aware endpoint launcher for curated homelab surfaces (MasaiMara, Casablanca, Margaritaville, Titan/Plex, graph endpoints). Endpoint resolution order is:
- User
quickLinksfrom/admin/users - Service registry URLs from
/admin/homelab/service-registry - Curated fallback URLs (where configured)
Each resolved endpoint is labeled by reachability mode:
public(Cloudflare/public URL)tailscale(100.x or.ts.net)lan(10.x/172.16-31.x/192.168.x/localhost)unknown(missing or invalid URL mapping)
This page is intended as a practical command surface for remote travel scenarios without forcing ad-hoc VPN reconfiguration.
Unified Dashboard (/user/dashboard)
Primary personalized dashboard for all users, including Bogart. This route is authenticated (portal:view) and supports admin impersonation via ?as=user@example.com.
Main sections:
- Adaptive routing model with travel region profile and policy mode
- Site matrix for MasaiMara, Margaritaville, and Casablanca with control + file surfaces
- Service cockpit (Plex, Unraid files, Synology files, graphs, downloads)
- Container panel seeded from mapped services and optionally hydrated from
/api/mm-argobox/containerswhen permissions allow
Link resolution is dynamic and template-driven. The route maps user quick links + registered services against keyword templates in:
src/lib/unified-dashboard-template.ts
Bogart-specific link alias:
/user/bogart/dashboard(redirects to/user/dashboard)
Code Editor (/user/editor)
Browser-based CodeMirror 6 editor with multi-tab file editing. Each tab shows the filename and a modified indicator dot for unsaved changes. A repository selector dropdown loads the file tree for any Gitea repo the user has access to, and a collapsible tree view navigates the directory structure.
Syntax highlighting covers HTML, CSS, JavaScript, TypeScript, JSX, TSX, JSON, YAML, Markdown, Astro, and SVG via CodeMirror 6 language extensions. Saving via Ctrl+S commits directly to Gitea with SHA tracking for optimistic concurrency -- if the SHA has drifted, the save is rejected with a conflict error.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/user/files |
List repo contents or fetch file content with SHA |
PUT |
/api/user/files |
Save file -- commits to Gitea with SHA-based conflict detection |
GET accepts repo, path, and ref (branch) query parameters. PUT body includes repo, path, content, sha, and optional message.
AI Workbench (/user/workbench)
AI chat interface with an immersive full-viewport layout (CosmicLayout with hideHeader/hideFooter). Models are fetched dynamically from /api/user/models (list varies by role). Responses stream via SSE with real-time markdown rendering and syntax-highlighted code blocks with copy buttons.
Chat history persists in localStorage (last 50 messages). Suggested prompts display when the conversation is empty. Messages POST to /api/user/chat with the selected model, history, and new message.
My Sites (/user/sites)
Site management page using SiteCard components. Each card displays:
- Sync status -- real-time badge from
/api/user/site-statusshowing Gitea-to-GitHub mirror state - Mirror mode -- Auto-sync (pushes on commit) or Manual
- Deploy button -- triggers POST to
/api/user/deployfor a Cloudflare Pages build - Recent commits -- latest messages and timestamps from Gitea
- Status badge -- Cloudflare Pages deployment state (success, building, failed)
Settings (/user/settings)
Auth: SSR with resolveAuthState() + portal:view permission gate. Previously unprotected (no SSR, no auth) — fixed 2026-03-08.
User preference configuration with auto-save to /api/user/preferences (500ms debounce, no save button).
Widget preferences -- SortableJS drag-and-drop order and visibility toggles persist in user preferences.
Theme colors -- primary and secondary color pickers with gradient preview. Defaults: #06b6d4 (cyan) primary, #8b5cf6 (violet) secondary. Injected as CSS custom properties at runtime.
Default landing page -- choose between portal index, editor, or workbench as the /user destination. Sidebar collapsed toggle -- sets initial UserSidebar state, seeds the localStorage key.
Admin Preview Flow
Admin user preview for member dashboards is wired to:
/user/dashboard?as=<user-email>/user/access?as=<user-email>
The ?as= impersonation param is threaded through:
- Page data — both
dashboard.astroandaccess.astroresolve impersonated user's quickLinks, services, display name from KV - Sidebar —
UserSidebar.astroclient-side JS appends?as=to all sidebar links - Layout —
CosmicLayout.astroresolves impersonated user's features from KV for sidebar visibility - Hero buttons — dashboard hero links include
?as=param
This is used by /admin/users Preview buttons to validate exactly what a specific member will see after profile/service changes.