# nself-admin Architecture Technical architecture documentation for nself-admin v1.0.0. ## Architecture Decision Records - [ADR-003: admin/ Next.js Permanent Exception](./ADR-003-nextjs-permanent-exception.md) — admin/ stays on Next.js permanently while the rest of the nSelf ecosystem converges on React + Vite + Tauri 2 (per the 2026-05-14 Flutter-elimination directive). Server.js, Docker socket integration, LokiJS, `pg` direct connection, and the server-side socket.io emitter are all architecturally incompatible with a Vite SPA. Status: **Accepted (permanent)**. ## Table of Contents 1. [System Overview](#system-overview) 2. [Core Principles](#core-principles) 3. [Technology Stack](#technology-stack) 4. [Architecture Diagrams](#architecture-diagrams) 5. [Directory Structure](#directory-structure) 6. [Component Hierarchy](#component-hierarchy) 7. [Data Flow](#data-flow) 8. [State Management](#state-management) 9. [API Design](#api-design) 10. [Real-Time Architecture](#real-time-architecture) 11. [Security Model](#security-model) 12. [Performance Optimizations](#performance-optimizations) 13. [Database Schema](#database-schema) 14. [Deployment Architecture](#deployment-architecture) --- ## System Overview nself-admin is a **web-based UI wrapper** for the [nself CLI](https://github.com/nself-org/cli). It provides a visual interface for managing your self-hosted backend stack without reimplementing any CLI logic. ### Key Characteristics - **UI Wrapper**: All operations delegate to `nself` CLI commands - **Zero Footprint**: Never modifies user's project except through nself CLI - **Self-Contained**: Internal state stored in embedded LokiJS database - **Docker-First**: Designed to run in containers with volume mounts - **Real-Time**: WebSocket and SSE for live updates ### Architecture at a Glance ``` Browser (User) → nself-admin (Next.js) → nself CLI → Docker → Services ↓ LokiJS Database ``` --- ## Core Principles ### 1. CLI Delegation Principle **GOLDEN RULE**: Never reimplement nself CLI logic in nself-admin. **Examples:** ```typescript // ✅ CORRECT: Delegate to CLI export async function POST() { const result = await execFile('nself', ['start']) return NextResponse.json({ output: result.stdout }) } // ❌ WRONG: Reimplementing CLI logic export async function POST() { const composeFile = readFileSync('docker-compose.yml') await execFile('docker-compose', ['up', '-d']) // This reimplements nself's logic! } ``` ### 2. Progressive Disclosure Guide users through a logical flow: 1. **Password Setup** - First-time security 2. **Project Initialization** - 6-step wizard 3. **Service Build** - Configuration and build 4. **Service Start** - Launch containers 5. **Dashboard** - Monitor and manage ### 3. Separation of Concerns - **Frontend**: React components, UI state - **API Routes**: Business logic, CLI execution - **Database**: Sessions, cache, audit logs - **CLI Executor**: Isolated command execution - **Services**: Background tasks (polling, WebSocket) ### 4. Fail-Safe Design - **Graceful Degradation**: UI works without WebSocket - **Error Boundaries**: Isolate component failures - **Retry Logic**: Automatic retries with exponential backoff - **Health Checks**: Monitor all critical services --- ## Technology Stack ### Frontend | Technology | Version | Purpose | | ---------------- | ------- | ---------------------------- | | Next.js | 16.x | React framework (App Router) | | React | 19.x | UI library | | TypeScript | 5.9 | Type safety | | Tailwind CSS | 4.x | Styling | | Radix UI | Latest | Headless components | | Zustand | 5.x | Global state | | SWR | 2.x | Data fetching | | Socket.io Client | 4.8 | WebSocket | | Monaco Editor | 4.x | Code editor | | Recharts | 3.x | Charts | ### Backend | Technology | Version | Purpose | | ---------- | ------- | ----------------- | | Node.js | 18+ | Runtime | | LokiJS | 1.5 | Embedded database | | bcryptjs | 3.x | Password hashing | | Socket.io | 4.8 | WebSocket server | | Dockerode | 4.x | Docker API | | Zod | 4.x | Validation | ### Development | Technology | Version | Purpose | | ---------- | ------- | --------------- | | Jest | 30.x | Unit testing | | Playwright | 1.55 | E2E testing | | ESLint | 9.x | Linting | | Prettier | 3.x | Formatting | | pnpm | 10.x | Package manager | --- ## Architecture Diagrams ### High-Level System Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ │ User's Machine │ │ │ │ ┌──────────┐ │ │ │ Browser │ │ │ └────┬─────┘ │ │ │ HTTP/WebSocket (Port 3021) │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ nself-admin Docker Container │ │ │ │ │ │ │ │ ┌────────────┐ ┌──────────┐ ┌───────────┐ │ │ │ │ │ Next.js │◄────►│ API │◄────►│ LokiJS │ │ │ │ │ │ Frontend │ │ Routes │ │ Database │ │ │ │ │ └────────────┘ └────┬─────┘ └───────────┘ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ┌──────────────┐ │ │ │ │ │ nself CLI │ │ │ │ │ │ Executor │ │ │ │ │ └──────┬───────┘ │ │ │ └───────────────────────────┼────────────────────────────┘ │ │ │ │ │ ┌────────────────────┼────────────────────┐ │ │ │ ▼ │ │ │ ┌────▼─────┐ ┌──────────────┐ ┌────▼──────┐ │ │ │ Docker │ │ Project │ │ Docker │ │ │ │ Socket │ │ Directory │ │ Compose │ │ │ └──────────┘ │ (/workspace)│ └───────────┘ │ │ └──────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Running Containers │ │ │ │ PostgreSQL │ Hasura │ Auth │ MinIO │ Redis ... │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### Request Flow ``` ┌────────┐ │ User │ └───┬────┘ │ │ 1. Click "Start Services" ▼ ┌───────────────┐ │ React │ │ Component │ └───┬───────────┘ │ │ 2. Call API ▼ ┌───────────────┐ │ API Route │ │ /api/services │ │ /start │ └───┬───────────┘ │ │ 3. Validate session ▼ ┌───────────────┐ │ Auth Check │ └───┬───────────┘ │ │ 4. Execute CLI ▼ ┌───────────────┐ │ nself CLI │ │ Executor │ └───┬───────────┘ │ │ 5. Run command ▼ ┌───────────────┐ │ execFile() │ │ nself start │ └───┬───────────┘ │ │ 6. Docker operations ▼ ┌───────────────┐ │ Docker Engine │ └───┬───────────┘ │ │ 7. Start containers ▼ ┌───────────────┐ │ Services │ │ Running │ └───────────────┘ ``` --- ## Directory Structure ### Project Root ``` nself-admin/ ├── .claude/ # Development instructions │ └── CLAUDE.md # Project guidelines ├── docs/ # Documentation │ ├── ARCHITECTURE.md # This file │ ├── API.md # API reference │ ├── DEPLOYMENT.md # Deployment guide │ ├── DEVELOPMENT.md # Development guide │ ├── MIGRATION.md # Migration guides │ └── CHANGELOG.md # Release notes ├── public/ # Static assets ├── scripts/ # Build/deployment scripts ├── src/ # Source code │ ├── app/ # Next.js App Router │ ├── components/ # React components │ ├── contexts/ # React contexts │ ├── hooks/ # Custom hooks │ ├── lib/ # Utilities │ └── services/ # Background services ├── tests/ # Test files ├── .env.example # Example environment ├── Dockerfile # Container definition ├── docker-compose.yml # Local development ├── jest.config.js # Jest configuration ├── next.config.mjs # Next.js configuration ├── package.json # Dependencies ├── pnpm-lock.yaml # Lock file ├── tailwind.config.ts # Tailwind configuration └── tsconfig.json # TypeScript configuration ``` ### Source Code (`src/`) ``` src/ ├── app/ # Next.js App Router │ ├── api/ # API routes (120+ endpoints) │ │ ├── auth/ # Authentication (5 endpoints) │ │ ├── config/ # Configuration (8 endpoints) │ │ ├── database/ # Database (18 endpoints) │ │ ├── deploy/ # Deployment (10 endpoints) │ │ ├── docker/ # Docker (15 endpoints) │ │ ├── services/ # Services (12 endpoints) │ │ ├── cloud/ # Cloud providers (15 endpoints) │ │ ├── k8s/ # Kubernetes (12 endpoints) │ │ ├── monitor/ # Monitoring (8 endpoints) │ │ ├── plugins/ # Plugins (10 endpoints) │ │ └── system/ # System (7 endpoints) │ ├── login/ # Login page │ ├── build/ # Build wizard │ ├── config/ # Configuration pages │ ├── database/ # Database pages │ ├── services/ # Service management │ ├── deployment/ # Deployment pages │ ├── cloud/ # Cloud provider pages │ ├── plugins/ # Plugin pages │ ├── monitor/ # Monitoring pages │ ├── settings/ # Settings pages │ ├── layout.tsx # Root layout │ └── page.tsx # Dashboard ├── components/ # React components (60+) │ ├── ui/ # Base components │ │ ├── button.tsx │ │ ├── input.tsx │ │ ├── card.tsx │ │ └── ... │ ├── build/ # Build wizard components │ ├── config/ # Config components │ ├── database/ # Database components │ ├── services/ # Service components │ ├── skeletons/ # Loading states │ ├── Header.tsx # Top navigation │ ├── Layout.tsx # Main layout │ └── Navigation.tsx # Sidebar ├── contexts/ # React contexts │ └── AuthContext.tsx # Auth state ├── hooks/ # Custom hooks │ ├── useDashboardData.ts # Dashboard data │ ├── useServiceStatus.ts # Service status │ ├── useSession.ts # Session management │ └── useWebSocket.ts # WebSocket connection ├── lib/ # Utilities │ ├── api-client.ts # API client │ ├── auth-db.ts # Auth database │ ├── database.ts # LokiJS interface │ ├── nselfCLI.ts # CLI executor │ ├── validation.ts # Zod schemas │ └── utils.ts # Utilities └── services/ # Background services └── SimplifiedPolling.ts # Polling service ``` --- ## Component Hierarchy ### Layout Components ``` ├──
│ ├── │ ├── │ └── ├── │ └── × N ├── │ └── [Page Component] └──