- 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>
12 KiB
Web App Architecture Analysis & Modularity Assessment
⚠️ OUTDATED DOCUMENT
Updated Version:/docs/modular-architecture-analysis.md
Date: This document from September 4, 2025 is outdated - significant architectural changes implemented September 6, 2025
Date: September 4, 2025
Project: Ario Web App (Vue 3 + Nostr + LNbits)
Objective: Evaluate current architecture for modular plugin-based development
Executive Summary
The current web application demonstrates solid foundational architecture with excellent Nostr infrastructure (RelayHub/NostrclientHub) but lacks true modularity for plugin-based development.
Overall Modularity Rating: 6.5/10
The app successfully implements core Nostr functionality and component organization but requires significant architectural refactoring to achieve the stated objective of independent, pluggable feature modules.
Current Architecture Assessment
✅ Strengths (What's Working Well)
1. Strong Base Infrastructure (8/10)
- RelayHub & NostrclientHub: Excellent centralized Nostr infrastructure with robust connection management, event handling, and browser compatibility
- Pinia Stores: Clean state management separation (
nostr.ts,market.ts) with reactive patterns - Composables Pattern: Good reactive logic encapsulation (
useRelayHub,useNostrChat,useMarket) - UI Component Library: Well-structured Shadcn/ui components with consistent design system
2. Component Organization (7/10)
- Components grouped by domain (
/market,/nostr,/events,/auth) - Page-level routing with lazy loading implementation
- Composables provide reusable business logic across components
- Clean separation of concerns between UI and business logic
3. Service Layer (6/10)
- Clean service abstractions (
nostrmarketService,paymentMonitor) - API layer separation (
/lib/api) - Type-safe interfaces and proper error handling
❌ Critical Issues (What's Missing)
1. No Plugin Architecture (3/10)
- Hard-coded routes: All features baked into main router configuration
- Tight coupling: Components directly import across modules without abstraction
- No feature isolation: Cannot develop/deploy components independently
- No plugin registration system: Missing infrastructure for dynamic feature loading
2. Cross-Module Dependencies (4/10)
Examples of problematic tight coupling:
// Payment monitor importing market types directly
src/lib/services/paymentMonitor.ts: import type { Order } from '@/stores/market'
// Navbar importing chat composable directly
src/components/layout/Navbar.vue: import { nostrChat } from '@/composables/useNostrChat'
// Services importing market store directly
src/lib/services/nostrmarketService.ts: import type { Stall, Product, Order } from '@/stores/market'
3. Missing Module Boundaries (5/10)
- No clear module interfaces/contracts
- Shared types scattered across modules without centralized definition
- No dependency injection system for service management
- Missing module lifecycle management
Required Changes for Modular Architecture
Phase 1: Core Infrastructure Refactor
1. Create Module System
// /src/modules/base/types.ts
interface ModuleConfig {
name: string
routes: RouteConfig[]
components: ComponentConfig[]
services: ServiceConfig[]
dependencies?: string[]
}
interface ModulePlugin {
install(app: App, options?: any): void
uninstall(): void
}
2. Plugin Registration System
// /src/core/plugin-manager.ts
class PluginManager {
private plugins = new Map<string, ModulePlugin>()
register(module: ModulePlugin): void
unregister(name: string): void
getModule(name: string): ModulePlugin
getDependencies(name: string): string[]
}
Phase 2: Module Extraction
1. Base Module Structure
/src/modules/base/
├── nostr/
│ ├── relayHub.ts # Centralized relay management
│ ├── nostrclientHub.ts # Client connection handling
│ └── types.ts # Nostr-specific types
├── auth/
│ ├── lnbits.ts # LNbits authentication
│ └── composables/
├── pwa/
│ ├── install-prompt.ts
│ └── notifications.ts
└── ui/ # Shadcn components
2. Feature Modules
/src/modules/
├── nostr-feed/
│ ├── components/
│ │ └── NostrFeed.vue
│ ├── composables/
│ │ └── useFeed.ts
│ ├── services/
│ │ └── feedService.ts
│ └── index.ts # Module export
├── market/
│ ├── components/
│ ├── composables/
│ ├── stores/
│ ├── services/
│ └── index.ts
├── chat/
└── events/
3. Module Interface Standards
// Each module exports standardized interface
export interface NostrFeedModule extends ModulePlugin {
name: 'nostr-feed'
components: {
NostrFeed: Component
}
routes: RouteConfig[]
dependencies: ['base']
config?: NostrFeedConfig
}
Phase 3: Event-Driven Communication
Replace Direct Imports with Event Bus
// /src/core/event-bus.ts
interface ModuleEventBus {
emit(event: string, data: any): void
on(event: string, handler: Function): void
off(event: string, handler: Function): void
}
// Example usage:
// Market module: eventBus.emit('order:created', order)
// Chat module: eventBus.on('order:created', handleNewOrder)
Dependency Injection Container
// /src/core/di-container.ts
class DIContainer {
provide<T>(token: string, instance: T): void
inject<T>(token: string): T
// Module-scoped injection
provideForModule(module: string, token: string, instance: any): void
}
Recommended Ground-Up Architecture
If rebuilding from scratch, implement these architectural patterns:
1. Module-First Architecture
src/
├── core/ # Base app infrastructure
│ ├── plugin-manager.ts # Plugin registration & lifecycle
│ ├── di-container.ts # Dependency injection
│ ├── event-bus.ts # Inter-module communication
│ ├── module-registry.ts # Module discovery & loading
│ └── base-services/ # Core services
├── modules/
│ ├── base/ # Core functionality (required)
│ │ ├── nostr/ # RelayHub, NostrclientHub
│ │ ├── auth/ # LNbits authentication
│ │ ├── pwa/ # Progressive Web App features
│ │ └── ui/ # Shadcn component library
│ ├── nostr-feed/ # Announcements & social feed
│ ├── market/ # Marketplace functionality
│ ├── chat/ # Nostr chat implementation
│ └── events/ # Event ticketing system
└── app.ts # Application composition & startup
2. Configuration-Driven Setup
// /src/app.config.ts
export const appConfig = {
modules: {
base: {
required: true,
nostr: {
relays: process.env.VITE_NOSTR_RELAYS
}
},
'nostr-feed': {
enabled: true,
config: {
refreshInterval: 30000,
maxPosts: 100
}
},
market: {
enabled: true,
config: {
defaultCurrency: 'sats',
paymentTimeout: 300000
}
},
chat: {
enabled: false // Can be toggled via config
},
events: {
enabled: true,
config: {
ticketValidationEndpoint: '/api/tickets/validate'
}
}
},
features: {
pwa: true,
pushNotifications: true,
electronApp: true
}
}
3. Dynamic Module Loading
// /src/core/module-loader.ts
class ModuleLoader {
async loadModule(name: string): Promise<ModulePlugin> {
const module = await import(`@/modules/${name}/index.ts`)
await this.resolveDependencies(module.dependencies || [])
return module.default
}
async unloadModule(name: string): Promise<void> {
const module = this.getModule(name)
if (module) {
await module.uninstall()
this.cleanupRoutes(name)
this.cleanupServices(name)
}
}
private async resolveDependencies(deps: string[]): Promise<void> {
for (const dep of deps) {
if (!this.isModuleLoaded(dep)) {
await this.loadModule(dep)
}
}
}
}
4. Module Development Workflow
# Develop single module in isolation
npm run dev:module market
# Test module independently
npm run test:module market
# Build specific modules only
npm run build:modules market,chat
# Hot reload module during development
npm run dev:hot-module nostr-feed
Key Architectural Improvements
1. Dependency Inversion
- Modules depend on interfaces, not concrete implementations
- Services injected via DI container rather than direct imports
- Clear separation between module contracts and implementations
2. Event-Driven Communication
- Replace direct imports with event-based messaging
- Loose coupling between modules via standardized events
- Centralized event routing and handling
3. Module Lifecycle Management
- Proper setup and teardown hooks for each module
- Resource cleanup when modules are disabled/unloaded
- Dependency resolution during module loading
4. Configuration Over Code
- Enable/disable features via configuration files
- Runtime module toggling without code changes
- Environment-specific module configurations
5. Hot Module Replacement
- Develop modules independently without full app restart
- Live reloading of individual modules during development
- Isolated testing environments for each module
Implementation Roadmap
High Priority (Immediate)
- ✅ Extract RelayHub/NostrclientHub to base module (mostly complete)
- Create plugin registration system - Core infrastructure for module loading
- Convert nostr-feed to plugin pattern - Proof of concept implementation
Medium Priority (Phase 2)
- Implement event bus communication - Replace direct imports between modules
- Add module lifecycle management - Proper setup/teardown hooks
- Create development tooling - Scripts for isolated module development
Low Priority (Phase 3)
- Add module versioning support - Handle different module versions
- Implement hot module replacement - Live development workflow
- Add module marketplace - Plugin discovery and installation
Conclusion
The current web application has excellent technical foundations, particularly the Nostr infrastructure (RelayHub/NostrclientHub), but requires significant architectural refactoring to achieve true modularity.
Key Strengths to Preserve:
- Robust Nostr client implementation
- Clean component organization
- Solid TypeScript foundations
- PWA capabilities
Critical Areas for Improvement:
- Plugin architecture implementation
- Module boundary enforcement
- Event-driven communication
- Development workflow optimization
Estimated Effort:
- Phase 1 (Core Infrastructure): 2-3 weeks
- Phase 2 (Module Extraction): 3-4 weeks
- Phase 3 (Advanced Features): 2-3 weeks
The investment in modular architecture will enable independent development of features, easier testing, better code maintainability, and the ability to dynamically enable/disable functionality based on deployment requirements.
Generated by: Claude Code Architecture Analysis
Last Updated: September 4, 2025