web-app/docs/01-architecture/index.md
padreug cdf099e45f Create comprehensive Obsidian-style documentation structure
- Reorganize all markdown documentation into structured docs/ folder
- Create 7 main documentation categories (00-overview through 06-deployment)
- Add comprehensive index files for each category with cross-linking
- Implement Obsidian-compatible [[link]] syntax throughout
- Move legacy/deprecated documentation to archive folder
- Establish documentation standards and maintenance guidelines
- Provide complete coverage of modular architecture, services, and deployment
- Enable better navigation and discoverability for developers and contributors

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-06 14:31:27 +02:00

8.1 KiB

🏗️ Architecture Overview

System design and patterns powering Ario's modular, scalable, and maintainable architecture with dependency injection, plugin-based modules, and reactive services.

Table of Contents

Architecture Principles

Modularity - Plugin-Based Design

Every feature is implemented as a self-contained module that can be enabled, disabled, or configured independently. This approach ensures:

  • Separation of Concerns - Each module owns its domain logic
  • Testability - Modules can be tested in isolation
  • Maintainability - Changes to one module don't affect others
  • Extensibility - New features can be added as plugins

Loose Coupling - Dependency Injection

Services communicate through well-defined interfaces using a dependency injection container:

  • Interface-Based Design - Services depend on abstractions, not implementations
  • Runtime Configuration - Service instances can be swapped for testing or different environments
  • Clear Dependencies - Service relationships are explicit and manageable
  • Lifecycle Management - Services have defined initialization and disposal phases

Reactive Architecture - Vue-Powered Services

Services integrate Vue's reactivity system for state management:

  • Reactive State - Services expose reactive refs and computed properties
  • Automatic Updates - UI automatically updates when service state changes
  • Event-Driven Communication - Services communicate via event bus patterns
  • Consistent Patterns - Same reactivity patterns used throughout the application

Core Systems

Dependency Injection Container

Location: src/core/di-container.ts

Centralized service registry and resolution system:

// Service registration (in modules)
container.provide(SERVICE_TOKENS.RELAY_HUB, relayHub)

// Service consumption (anywhere)
const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB)

Key Features:

  • Type-safe service tokens
  • Singleton lifecycle management
  • Runtime service validation
  • Development-time debugging support

Plugin Manager

Location: src/core/plugin-manager.ts

Orchestrates module loading and dependency resolution:

class PluginManager {
  async loadModule(plugin: ModulePlugin): Promise<void>
  getDependencyGraph(): Map<string, string[]>
  validateDependencies(modules: ModulePlugin[]): void
}

Base Service Architecture

Location: src/core/base/BaseService.ts

Abstract foundation for all services with common patterns:

abstract class BaseService {
  protected isInitialized = ref(false)
  protected isDisposed = ref(false)
  
  abstract initialize(): Promise<void>
  abstract dispose(): Promise<void>
}

Service Architecture

Service Categories

Infrastructure Services (Base Module)

  • RelayHub - Nostr relay connection management
  • AuthService - User authentication and key management
  • StorageService - User-scoped local storage operations
  • ToastService - User notifications and feedback

Feature Services (Module-Specific)

  • ChatService - Encrypted messaging functionality
  • MarketService - Marketplace operations
  • EventsService - Event creation and ticketing
  • FeedService - Social feed management

Service Communication Patterns

Direct Service Dependencies

For tightly coupled operations:

class ChatService extends BaseService {
  constructor(
    private relayHub = injectService(SERVICE_TOKENS.RELAY_HUB),
    private auth = injectService(SERVICE_TOKENS.AUTH_SERVICE)
  ) {}
}

Event Bus Communication

For loose coupling between modules:

// Publishing events
eventBus.emit('user:authenticated', { userId: user.pubkey })

// Subscribing to events
eventBus.on('payment:received', handlePaymentReceived)

Module System

Module Plugin Structure

Each module implements the ModulePlugin interface:

interface ModulePlugin {
  name: string
  version: string
  dependencies: string[]
  
  install(app: App, options?: any): Promise<void>
  routes?: RouteRecordRaw[]
  components?: Record<string, Component>
}

Module Categories

Base Module - Core Infrastructure

  • Purpose - Provides shared services and infrastructure
  • Dependencies - None (foundation module)
  • Exports - RelayHub, AuthService, StorageService, ToastService

Feature Modules - Domain-Specific Logic

  • Chat Module - Encrypted messaging with Nostr DMs
  • Events Module - Event creation and Lightning ticketing
  • Market Module - Nostr marketplace functionality
  • Nostr Feed Module - Social feed and content discovery

Module Configuration

Location: src/app.config.ts

export const moduleConfigs = {
  'base': { enabled: true },
  'chat': { enabled: true, maxMessageLength: 1000 },
  'events': { enabled: true, defaultCurrency: 'sat' },
  'market': { enabled: true, allowedCategories: ['all'] },
  'nostr-feed': { enabled: true, defaultRelays: [] }
}

Communication Patterns

Service-to-Service Communication

// 1. Direct injection for required dependencies
const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB)

// 2. Event bus for optional/cross-module communication
eventBus.emit('user:profile-updated', profileData)

// 3. Reactive refs for state sharing
const connectionStatus = computed(() => relayHub.connectionStatus.value)

Component-to-Service Communication

// 1. Composables wrap service access
const { publishNote, isPublishing } = useNoteComposer()

// 2. Direct service injection in components
const toastService = injectService(SERVICE_TOKENS.TOAST_SERVICE)

// 3. Store integration for component state
const authStore = useAuthStore()

Module-to-Module Communication

// ❌ Direct imports break modularity
import { chatService } from '../chat/services/chat-service'

// ✅ Dependency injection maintains loose coupling
const chatService = injectService(SERVICE_TOKENS.CHAT_SERVICE)

// ✅ Event bus for cross-module notifications
eventBus.emit('chat:message-received', messageData)

Data Flow

Nostr Event Lifecycle

  1. Event Creation - User action triggers event creation
  2. Event Signing - AuthService signs event with user's private key
  3. Relay Publishing - RelayHub publishes to configured relays
  4. Event Storage - StorageService caches event locally
  5. UI Updates - Reactive properties trigger component re-renders

Lightning Payment Flow

  1. Invoice Generation - EventsService creates Lightning invoice
  2. QR Code Display - UI presents payment interface
  3. Payment Detection - WebLN or external wallet processes payment
  4. Verification - Service confirms payment via Lightning backend
  5. State Updates - Payment success triggers relevant service updates

Module Initialization Flow

  1. Dependency Resolution - PluginManager sorts modules by dependencies
  2. Service Registration - Each module registers services in DI container
  3. Route Registration - Module routes added to Vue Router
  4. Component Registration - Global components made available
  5. Service Initialization - Services initialize in dependency order

See Also

Deep Dive Documentation

Implementation References


Tags: #architecture #design-patterns #modularity #dependency-injection
Last Updated: 2025-09-06
Author: Development Team