Found 30 issues: 3 P0 (broken), 13 P1 (confusing), 14 P2 (polish). Key findings: Apps empty state hardcoded off, credentials parse error, persistent unhealthy banners, dead links, no-op buttons, silent failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
160 lines
6.3 KiB
Markdown
160 lines
6.3 KiB
Markdown
# 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 `<p>`. 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
|