User Portal
Internal documentation for the user portal pages including the hub, code editor, AI workbench, site management, settings, and dashboard
User Portal
Six authenticated pages for member-level users: a hub, code editor, AI workbench, site manager, settings panel, and personalized dashboard. All are SSR, require the member role minimum, and use CosmicLayout with the UserSidebar component (collapsible, 220px default, state persisted in localStorage). The sidebar filters navigation links based on the user’s auth.features array (sites, editor, workbench).
User Portal Index (/user)
Hub page with quick-access SiteCard components linking to the editor, workbench, and media services. Feature-gated — cards only render for features present in the user’s auth.features array. Site cards display Gitea repository URLs, GitHub mirror status, and Cloudflare Pages deployment state, giving a unified view of where code lives and how it deploys.
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)
User preference configuration with auto-save to /api/user/preferences (500ms debounce, no save button).
Dashboard widget reordering — SortableJS drag-and-drop for widget order, checkbox toggles for visibility. The layout persists in KV as part of the user’s 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.
Dashboard (/dashboard)
Personalized widget-based dashboard driven by dashboard profiles stored in the user’s KV record. Each profile defines widget visibility and arrangement. Widgets render as independent cards that fetch their own data.
Infrastructure monitoring — host status for Meridian-Host (10.42.0.50, Unraid), Izar-Host (10.42.0.194, Proxmox), and Tarn-Host (192.168.20.118, Proxmox) showing CPU, memory, and disk. AI chat widget — embedded chat using Kimi K2.5. Cloudflare Pages status — latest deployment, build duration, preview URLs. Docker container summary — aggregated counts and status across hosts.
Infrastructure data polls every 30 seconds. The page is permission-gated (dashboard:view required). Widget visibility is role-filtered — admin-only widgets do not render for basic members even if present in the profile.