fix: BUG-33 CPU threshold, TASK-27 tab icons, TASK-36 iframe errors

- BUG-33: CPU load alert threshold increased from 2x to 4x core count
  (8→16 on 4-core machine) to reduce false alerts during container ops
- TASK-27: Launch buttons for new-tab apps now show external link icon
  (BTCPay, Grafana, PhotoPrism, Portainer, OnlyOffice, etc.)
- TASK-36: Iframe error screen now distinguishes between X-Frame-Options
  blocked vs container not reachable, with appropriate messaging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-18 19:24:52 +00:00
parent e1b2ade7c6
commit 302f22019d
182 changed files with 969 additions and 36407 deletions

View File

@@ -1,41 +1,10 @@
# Neode UI - Vue 3 Edition
# Archipelago Web UI
A modern, clean Vue 3 + Vite + Tailwind rewrite of the Neode OS interface.
Vue 3 + TypeScript + Vite + Tailwind CSS + Pinia
## 🎯 Why This Rewrite?
The web interface for Archipelago — a self-sovereign Bitcoin Node OS.
The original Angular interface had routing issues, disappearing components, and was difficult to maintain. This Vue 3 rewrite provides:
-**Clean routing** - Vue Router is simpler and more predictable than Angular router
-**Modern tooling** - Vite is 10x faster than Angular CLI
-**Better DX** - TypeScript + Vue 3 Composition API + Tailwind = rapid development
-**Same glassmorphism design** - All your beautiful UI styling recreated
-**Same features** - Splash screen, login, onboarding, apps list, etc.
-**Backend agnostic** - Connects to the same Rust backend via RPC/WebSocket
## 🏗️ Architecture
```
neode-ui/
├── src/
│ ├── api/ # RPC client & WebSocket handler
│ ├── stores/ # Pinia state management (replaces PatchDB)
│ ├── views/ # Page components
│ ├── components/ # Reusable components (SplashScreen, etc.)
│ ├── router/ # Vue Router configuration
│ ├── types/ # TypeScript types (ported from Angular)
│ └── style.css # Global styles + Tailwind
├── public/assets/ # Static assets (images, fonts, icons)
└── vite.config.ts # Vite config with proxy to backend
```
## 🚀 Getting Started
### Prerequisites
- Node.js 20.19+ or 22.12+ (20.18.2 works but shows warning)
### Quick Start (Recommended)
## Quick Start
```bash
cd neode-ui
@@ -43,183 +12,144 @@ npm install
npm start
```
Visit **http://localhost:8100** and login with password: `password123`
Visit **http://localhost:8100** login with password: `password123`
This starts both:
- Mock backend (port 5959) - no Docker required!
- Vite dev server (port 8100) with instant HMR
This starts:
- Mock backend on port 5959 (no Docker required)
- Vite dev server on port 8100 with HMR
**Stop servers:**
```bash
npm stop
Stop with `npm stop`.
## Architecture
```
neode-ui/
├── src/
│ ├── api/ # RPC client (rpc-client.ts), WebSocket, container client
│ ├── stores/ # Pinia stores (app, container, appLauncher, monitoring)
│ ├── views/ # Page components (Dashboard, Marketplace, Settings, etc.)
│ ├── components/ # Reusable components (SplashScreen, AppSession, etc.)
│ ├── router/ # Vue Router configuration
│ ├── types/ # TypeScript type definitions
│ └── style.css # Global styles + Tailwind utilities
├── public/assets/ # Static assets (images, fonts, app icons, audio)
├── mock-backend.js # Mock backend server (simulates Rust backend)
├── docker/ # Docker configs (nginx, entrypoint)
└── vite.config.ts # Vite config with backend proxy
```
📖 **See [DEV-SCRIPTS.md](./DEV-SCRIPTS.md) for detailed documentation**
## Dev Modes
### Development Options
The mock backend supports multiple startup modes via `VITE_DEV_MODE`:
| Mode | Command | Behavior |
|------|---------|----------|
| **default** | `npm start` | Fully set up, login screen |
| **existing** | `VITE_DEV_MODE=existing npm run dev:mock` | Same as default |
| **setup** | `VITE_DEV_MODE=setup npm run dev:mock` | First-time password setup flow |
| **onboarding** | `VITE_DEV_MODE=onboarding npm run dev:mock` | Post-setup onboarding flow |
| **boot** | `npm run dev:boot` | 25s simulated boot sequence |
## Mock Backend
The mock backend (`mock-backend.js`) simulates the full Rust backend for local development:
**Pre-installed apps** (always visible in My Apps):
- Bitcoin Core, LND, Electrs, Mempool, FileBrowser, LoraBell, ThunderHub, Fedimint
**Marketplace**: 30+ curated apps with Docker images, install/uninstall simulation
**Features simulated**:
- Authentication (login, password change, TOTP 2FA)
- System metrics (CPU, memory, disk — randomized for realism)
- Node identity (DID, Nostr pubkey, Tor address)
- Federation (3 mock nodes with apps, metrics, trust levels)
- Mesh networking (4 LoRa peers, encrypted messaging, invoices)
- Peer-to-peer messaging
- FileBrowser API (mock file system with Music, Documents, Photos, Videos)
- DWN sync status
- Transport layer (mesh/LAN/Tor routing)
- Notifications (5 realistic entries)
- Claude AI chat proxy (requires `ANTHROPIC_API_KEY`)
**Container runtime**: If Docker/Podman is available, the mock backend will run real containers for installed apps. Otherwise, it simulates them.
## Demo Deployment (Portainer)
Deploy the demo via Docker Compose for showcasing:
```bash
# Start everything (mock backend + Vite)
npm start
# Stop everything
npm stop
# Run mock backend only
npm run backend:mock
# Run Vite only (requires backend running separately)
npm run dev
# Run with real Rust backend (requires core/ to be running)
npm run dev:real
docker compose -f docker-compose.demo.yml build
docker compose -f docker-compose.demo.yml up -d
```
### Build for Production
Or deploy through **Portainer Stacks**:
1. Stacks > Add stack > name: `archy-demo`
2. Web editor: paste `docker-compose.demo.yml` contents
3. Add environment variable: `ANTHROPIC_API_KEY` (for Claude chat)
4. Deploy
Access at **http://your-host:4848** — password: `password123`
## Development Commands
```bash
npm run build
npm start # Start mock backend + Vite (recommended)
npm stop # Stop all servers
npm run dev:mock # Same as start, without port cleanup
npm run dev:boot # Boot mode (simulated startup delay)
npm run backend:mock # Mock backend only
npm run dev # Vite only (needs backend running separately)
npm run dev:real # Vite with real Rust backend
npm run build # Production build (outputs to ../web/dist/neode-ui/)
npm run build:docker # Build for Docker (no type checking)
npm run type-check # TypeScript type checking
npm test # Run tests
```
Outputs to `../web/dist/neode-ui/`
## Design System
## 🎨 Design System
### Glass Classes
### Glassmorphism Classes
| Class | Use |
|-------|-----|
| `.glass-card` | Content containers, modals, panels |
| `.glass-button` | ALL buttons (primary and secondary) |
| `.path-option-card` | Interactive cards with hover lift |
| `.info-card` | Status badges, metric displays |
```html
<!-- Glass card -->
<div class="glass-card p-6">Content</div>
### Tokens
<!-- Glass button -->
<button class="glass-button px-4 py-3">Click me</button>
- **Font**: Avenir Next (primary), Montserrat (`font-archipelago`)
- **Glass**: `bg: rgba(0,0,0,0.60)`, `blur: 24px`, `border: rgba(255,255,255,0.22)`
- **Accent**: `#fb923c` (Bitcoin orange), `#4ade80` (green), `#ef4444` (red)
- **Text**: `rgba(255,255,255,0.9)` primary, `rgba(255,255,255,0.6)` muted
<!-- Manual glass styling -->
<div class="bg-glass-dark backdrop-blur-glass border border-glass-border shadow-glass">
Custom glass element
</div>
```
### Rules
### Spacing (4px grid system)
- Global CSS classes in `style.css` only — never inline Tailwind in components
- `.gradient-button` is **banned** — use `.glass-button`
- All components use `<script setup lang="ts">`
- `p-4` = 16px padding
- `m-6` = 24px margin
- `gap-4` = 16px gap
### Colors
- `text-white/80` = 80% white opacity
- `bg-glass-dark` = rgba(0, 0, 0, 0.35)
- `border-glass-border` = rgba(255, 255, 255, 0.18)
## 🔌 API Connection
### RPC Calls
## API
```typescript
import { rpcClient } from '@/api/rpc-client'
// Login
await rpcClient.login('password')
// Start a package
await rpcClient.startPackage('bitcoin')
// Get metrics
const metrics = await rpcClient.getMetrics()
```
### State Management (Pinia)
State management via Pinia stores. WebSocket patches applied automatically.
```typescript
import { useAppStore } from '@/stores/app'
## Build Output
const store = useAppStore()
- **Dev build**: `../web/dist/neode-ui/`
- **Docker build**: `dist/` (deployed to nginx)
- **Production deploy**: via `scripts/deploy-to-target.sh --live`
// Access reactive state
const packages = computed(() => store.packages)
const isAuthenticated = computed(() => store.isAuthenticated)
## License
// Call actions
await store.login(password)
await store.installPackage('nextcloud', marketplaceUrl, '1.0.0')
```
### WebSocket Updates
The store automatically subscribes to WebSocket updates and applies JSON patches to the state. No manual setup required!
## 📝 Routes
| Route | Component | Description |
|-------|-----------|-------------|
| `/` | Redirect | Redirects to /login |
| `/login` | Login | Login page with glass styling |
| `/onboarding/intro` | OnboardingIntro | Welcome screen |
| `/onboarding/options` | OnboardingOptions | Setup options |
| `/dashboard` | Dashboard | Main layout with sidebar |
| `/dashboard/apps` | Apps | Apps list with glass cards |
| `/dashboard/apps/:id` | AppDetails | App details page |
| `/dashboard/marketplace` | Marketplace | Browse apps |
| `/dashboard/server` | Server | Server settings |
| `/dashboard/settings` | Settings | UI settings |
## ✨ Features Recreated
- [x] Alien-style terminal splash screen with typing animation
- [x] Skip intro button
- [x] Login page with glass card and fade-up animation
- [x] Onboarding intro with feature highlights
- [x] Onboarding options with selectable glass cards
- [x] Dashboard layout with glass sidebar
- [x] Apps list with status badges and quick actions
- [x] Connection status banner
- [x] Offline detection
- [x] WebSocket state synchronization
- [x] RPC authentication
- [x] Responsive design
## 🐛 Debugging
### Common Issues
**Assets not loading?**
```bash
# Ensure assets are copied
cp -r ../web/projects/shared/assets/img/* public/assets/img/
```
**Backend connection refused?**
- Check backend is running on port 5959
- Update proxy in `vite.config.ts` if using different port
**TypeScript errors?**
```bash
npm run type-check
```
## 📦 Deployment
The Vue app can be served by the Rust backend (replace the Angular build):
1. Build: `npm run build` (outputs to `../web/dist/neode-ui/`)
2. Update Rust to serve from this directory
3. Restart backend
## 🔮 Future Enhancements
- [ ] Dark/light theme toggle
- [ ] App configuration UI
- [ ] Marketplace browsing & search
- [ ] Server metrics charts
- [ ] Backup/restore UI
- [ ] Notification system
- [ ] Multi-language support
## 🤝 Contributing
This is a clean rewrite - feel free to add features without the baggage of the old Angular codebase!
## 📄 License
Same as Neode OS
MIT