# UX Audit Report - Archipelago Web UI **Date**: 2026-03-11 **Scope**: All 12 pages (login, home, apps, marketplace, cloud, server, web5, settings, chat, federation, credentials, system update) **Method**: Screenshot review + source code analysis ## Summary | Priority | Count | Description | |----------|-------|-------------| | **P0** | 3 | Apps empty state never renders; Credentials API parse error; Persistent unhealthy banners | | **P1** | 13 | Dead links, no-op buttons, hardcoded fake data, missing error feedback, silent failures | | **P2** | 14 | Inconsistent patterns, visual polish, native dialogs, loading states | --- ## P0 - Broken Functionality ### Apps: Empty state hardcoded to never display - **File**: `Apps.vue:19` — `v-if="false"` means the "No Apps Installed" empty state can never render - **Fix**: Change to `v-if="sortedPackageEntries.length === 0 && !searchQuery"` ### Credentials: API parse error on page load - **File**: `Credentials.vue` — screenshot shows "Failed to load credentials: Parsing credentials" red error - **Fix**: Debug `identity.list-credentials` RPC response format; handle all response shapes gracefully ### Cross-page: Persistent "tor is unhealthy" banners stack in top-right - Every dashboard page shows 3-4 stacked red notification banners that never clear - **Fix**: Auto-dismiss when service recovers, or make dismissible; don't stack duplicates --- ## P1 - Confusing UX ### Login: "Forgot password?" link is dead (`href="#"`) - **File**: `Login.vue:178` - **Fix**: Remove link or show help message (password reset requires SSH/re-image) ### Login: No minimum password length feedback during setup - **File**: `Login.vue:80` — button disabled check doesn't include length >= 8 - **Fix**: Add reactive validation message and include length check in `:disabled` ### Home: Web5 card values are hardcoded (fake data) - **File**: `Home.vue:244-259` — DID "Active", DWN "Synced", Profits "0.024" are static - **Fix**: Fetch from RPC or show "--" / "Loading..." ### Home: No loading state for Network/Web5 cards - **File**: `Home.vue` — Network and Web5 cards show static content immediately - **Fix**: Add skeleton placeholders consistent with Cloud card pattern ### Home: Refresh buttons on Network/Web5 cards are no-ops - **File**: `Home.vue:208,266` — `@click="() => {}"` - **Fix**: Wire to reload data or remove the buttons ### Apps: Start/stop errors only logged to console - **File**: `Apps.vue:344,360` - **Fix**: Add toast notification on failure ### Server: "Manage Local Network" and "Manage Web3 Services" buttons are no-ops - **File**: `Server.vue:223,284` — no `@click` handler - **Fix**: Wire to route/modal or disable with "Coming Soon" tooltip ### Server: "View" logs button clears count but shows nothing - **File**: `Server.vue:766-768` — just resets counter - **Fix**: Navigate to logs view or show "Coming soon" message ### Server: WiFi connection failure silently swallowed - **File**: `Server.vue:668` - **Fix**: Show error message in WiFi modal ### Server: DNS configuration error silently swallowed - **File**: `Server.vue:622` - **Fix**: Show error message in DNS modal ### Chat: No close/back button on mobile - **File**: `Chat.vue:4` — `hidden md:flex` hides close button - **Fix**: Add mobile-specific back button ### Federation: Error display at bottom of template, easily missed - **File**: `Federation.vue:292-295` - **Fix**: Move error display above "Federated Nodes" section ### Federation: "Remove from Federation" has no confirmation - **File**: `Federation.vue:243` — destructive action, no confirm dialog - **Fix**: Add confirmation step before removing node --- ## P2 - Minor Polish ### Login: Duplicate `id="password"` across setup/login templates - **File**: `Login.vue:52,150` - **Fix**: Use distinct IDs (`setup-password`, `login-password`) ### Home: System stats show 0 until first RPC response - **File**: `Home.vue:297-323` - **Fix**: Show skeleton/placeholder bars instead of zero values ### Marketplace: Category tabs hidden on mobile - **File**: `Marketplace.vue:112` — `hidden md:flex` - **Fix**: Add horizontal scrollable tabs or dropdown for mobile ### Marketplace: Bottom row of apps may be cut off - **Fix**: Add `pb-24` bottom padding to scrollable container ### Cloud: No loading state while file counts fetch - **Fix**: Add loading skeleton to item count areas ### Web5: Quick actions grid wraps asymmetrically at lg breakpoint - **File**: `Web5.vue:11` — 5 items in 3-column grid - **Fix**: Use `lg:grid-cols-5` or restructure for balanced layout ### Settings: DID string has no copy button - **File**: `Settings.vue:63` — Tor address has copy button, DID doesn't - **Fix**: Add copy button matching Tor address pattern ### Settings: Onion address may overflow on mobile - **File**: `Settings.vue:87` - **Fix**: Add `truncate` with title tooltip ### Chat: Fallback message exposes env variable name - **File**: `Chat.vue:52` — shows `VITE_AIUI_URL` - **Fix**: Reword to user-friendly message ### Federation: Page header hidden on mobile with no alternative - **File**: `Federation.vue:3` - **Fix**: Verify mobile layout shell shows title ### Credentials: Toast position overlapped by mobile tab bar - **File**: `Credentials.vue:190` — `fixed bottom-6` - **Fix**: Change to `bottom-20` to clear mobile tab bar ### Credentials: Issue button has no validation feedback for empty fields - **File**: `Credentials.vue:44` - **Fix**: Add `:disabled` when required fields empty; add required indicators ### SystemUpdate: Sequential await calls slow page load - **File**: `SystemUpdate.vue:374-378` - **Fix**: Use `Promise.all()` for concurrent fetching ### SystemUpdate: `confirm()` for apply/rollback breaks glass UI - **File**: `SystemUpdate.vue:316,334` - **Fix**: Replace with glass-styled confirmation modals ### Apps: Uninstall failure uses `alert()` - **File**: `Apps.vue:396` - **Fix**: Replace with inline error toast --- ## Cross-Page Issues ### Toast pattern inconsistent - Credentials: custom inline toast. Settings: inline `
`. Apps: `alert()`. Server: swallows errors. - **Fix**: Implement shared `useToast()` composable used consistently everywhere ### Page headers inconsistently hidden on mobile - Apps, Cloud, Server, Federation: `hidden md:block`. Home, Web5, Settings, Credentials, SystemUpdate: always visible. - **Fix**: Standardize pattern across all pages