- 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>
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
- #Core Systems
- #Service Architecture
- #Module System
- #Communication Patterns
- #Data Flow
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
- Event Creation - User action triggers event creation
- Event Signing - AuthService signs event with user's private key
- Relay Publishing - RelayHub publishes to configured relays
- Event Storage - StorageService caches event locally
- UI Updates - Reactive properties trigger component re-renders
Lightning Payment Flow
- Invoice Generation - EventsService creates Lightning invoice
- QR Code Display - UI presents payment interface
- Payment Detection - WebLN or external wallet processes payment
- Verification - Service confirms payment via Lightning backend
- State Updates - Payment success triggers relevant service updates
Module Initialization Flow
- Dependency Resolution - PluginManager sorts modules by dependencies
- Service Registration - Each module registers services in DI container
- Route Registration - Module routes added to Vue Router
- Component Registration - Global components made available
- Service Initialization - Services initialize in dependency order
See Also
Deep Dive Documentation
- modular-design - Plugin architecture details
- dependency-injection - Service container system
- relay-hub - Nostr relay management
- event-bus - Inter-module messaging
Implementation References
- ../02-modules/index - Individual module guides
- ../03-core-services/index - Service implementations
- ../04-development/index - Architectural patterns in practice
Tags: #architecture #design-patterns #modularity #dependency-injection
Last Updated: 2025-09-06
Author: Development Team