Voltz is built on a sophisticated service-oriented architecture that promotes modularity, maintainability, and scalability. This document provides a comprehensive overview of the framework's architectural principles and core components.
Voltz follows SOA principles where functionality is organized into discrete services that communicate through well-defined interfaces. This approach provides:
- Modularity: Clear separation of concerns
- Reusability: Services can be used across different parts of the application
- Testability: Services can be tested in isolation
- Maintainability: Changes to one service don't affect others
The framework uses a sophisticated dependency injection container that manages service dependencies:
- Explicit Declaration: Dependencies must be declared in the decorator parameter list
- Lifecycle Management: Proper initialization and cleanup of services
- Singleton Support: Services can be configured as singletons or transient instances
Full TypeScript integration ensures type safety across all layers:
- Compile-time Checking: Catch errors during development
- IntelliSense Support: Rich IDE support with autocomplete
- Refactoring Safety: Safe code refactoring with type checking
The main process is the heart of the Electron application, running in Node.js environment.
Main Process
├── Core Framework
│ ├── Container (DI)
│ ├── Module Registry
│ ├── Window Manager
│ └── Application Store
├── Decorators
│ ├── @IpcController
│ ├── @IpcService
│ ├── @IpcHandle/@IpcOn
│ └── @LifecycleService
└── Application Modules
├── Controllers
└── Services
Container (src/main/core/container.ts)
- Dependency injection container
- Service registration and resolution
- Explicit dependency declaration in decorators
- Singleton and transient service support
Module Registry (src/main/core/registry.ts)
- Central registry for all services and controllers
- Automatic module discovery and loading
- Lifecycle management for services
- IPC handler setup and coordination
Window Manager (src/main/core/window-manager.ts)
- Window creation and management
- Window configuration handling
- Cross-window communication support
Application Store (src/main/core/store.ts)
- Persistent data storage
- Type-safe configuration management
- Application settings persistence
The preload layer acts as a secure bridge between the main and renderer processes.
Preload Layer
├── Context Bridge
├── IPC Communication
├── Type Definitions
└── Security Isolation
Key Features:
- Context Isolation: Secure communication without exposing Node.js APIs
- Type-Safe APIs: Full TypeScript support for exposed APIs
- Selective Exposure: Only necessary APIs are exposed to the renderer
The renderer process runs the React-based user interface.
Renderer Process
├── React Application
├── UI Components (shadcn/ui)
├── TailwindCSS Styling
├── Hooks and Utilities
└── Type-Safe IPC Calls
graph TD
A[Module Discovery] --> B[Decorator Processing]
B --> C[Dependency Resolution]
C --> D[Service Registration]
D --> E[Lifecycle Initialization]
- Module Discovery: The registry scans for modules using glob patterns
- Decorator Processing: TypeScript decorators are processed to extract metadata
- Dependency Resolution: Constructor dependencies are resolved using reflection
- Service Registration: Services are registered in the DI container
- Lifecycle Initialization: Services with lifecycle hooks are initialized
graph LR
A[Renderer Request] --> B[Preload Bridge]
B --> C[Main Process IPC]
C --> D[Controller Method]
D --> E[Service Logic]
E --> F[Response]
F --> G[Renderer Update]
- Renderer Request: UI component calls exposed API
- Preload Bridge: Request passes through secure context bridge
- Main Process IPC: IPC handler receives the request
- Controller Method: Decorated controller method processes request
- Service Logic: Controller delegates to appropriate service
- Response: Result is sent back through the chain
graph TD
A[Application Start] --> B[Module Registration]
B --> C[Service Initialization]
C --> D[onInit Hooks]
D --> E[Application Ready]
E --> F[Runtime Operations]
F --> G[Application Shutdown]
G --> H[onDestroy Hooks]
H --> I[Cleanup Complete]
Voltz uses TypeScript decorators to provide a clean, declarative way to configure services and controllers.
@IpcService()
@IpcService()
@LifecycleService()
export class UserService implements LifecycleAware {
// Service implementation
}@LifecycleService() / @LifecycleAware()
@LifecycleService()
export class DatabaseService implements LifecycleAware {
async onInit(): Promise<void> {
// Initialize database connection
}
async onDestroy(): Promise<void> {
// Close database connection
}
}@IpcController(dependencies)
@IpcController(['UserService', 'ValidationService'])
@LifecycleService()
export class UserController {
constructor(
private userService: UserService,
private validationService: ValidationService
) {}
}@IpcHandle(channel) / @IpcOn(channel)
@IpcHandle('user:create')
async createUser(event: IpcMainInvokeEvent, userData: UserData): Promise<User> {
return this.userService.createUser(userData)
}
@IpcOn('user:updated')
handleUserUpdate(event: IpcMainEvent, userId: string): void {
this.notificationService.notifyUserUpdate(userId)
}All dependencies must be explicitly declared in the controller decorator:
// Dependencies must be explicitly declared
@IpcController(['OrderService', 'PaymentService', 'EmailService'])
export class OrderController {
constructor(
private orderService: OrderService,
private paymentService: PaymentService,
private emailService: EmailService
) {}
}You can register services using the dependency names:
@IpcController(['UserService', 'CustomUtilityService'])
export class UserController {
constructor(
private userService: UserService,
private utilityService: CustomUtilityService
) {}
}Default singleton behavior prevents unnecessary object creation:
- Services are created once and reused
- Reduces memory overhead
- Maintains state across application lifecycle
Voltz maintains Electron's security model:
webPreferences: {
nodeIntegration: false, // Disable Node.js in renderer
contextIsolation: true, // Enable context isolation
preload: path.join(__dirname, 'preload.js') // Secure bridge
}Only necessary APIs are exposed to the renderer:
contextBridge.exposeInMainWorld('electron', {
// Only expose specific, safe methods
getUserData: () => ipcRenderer.invoke('user:getData'),
updateSettings: (settings) => ipcRenderer.invoke('settings:update', settings)
})TypeScript ensures that IPC communication is type-safe:
interface ElectronAPI {
getUserData: () => Promise<UserData>
updateSettings: (settings: AppSettings) => Promise<void>
}This architecture provides a solid foundation for building complex desktop applications while maintaining code quality, type safety, and developer productivity.