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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user