Widget System Architecture
Architecture of the dynamic widget and dashboard system
🧩 Widget System Architecture
The Widget System provides a flexible, responsive grid layout for dynamic dashboards and pages.
It integrates seamlessly with the Module System to allow modules to expose embeddable components as widgets.
🎯 Design Goals
- Integration: Reuse
ModuleEmbeddableComponentdefinitions. - Responsiveness: Intelligent layout adaptation for all devices.
- Resilience: Error boundaries to isolate widget failures.
- Performance: OnPush change detection and lazy loading.
🏗️ Component Architecture
1. WidgetGridComponent
The main container. Renders widgets using CSS Grid.
- Features: Auto-calculation of rows/columns, gap management, responsive breakpoints.
2. WidgetContainerComponent
The wrapper for individual widgets.
- Responsibilities:
- Error Boundary: Catches errors so one widget doesn't crash the grid.
- Loading State: Shows skeleton/spinner while widget loads.
- Dynamic Rendering: Uses
NgComponentOutletto render the actual component.
3. BaseWidgetComponent (Optional)
An abstract class that widgets can extend for helper methods.
- Features:
emitWidgetEvent(),subscribeToWidgetEvent(), standardized lifecycle.
📱 Responsive Strategy
We use a Two-Phase responsive strategy to ensure great UX without configuration hell.
Phase 1: Auto-Shrink (Default)
Smart logic automatically adapts desktop configurations for mobile.
- Mobile: Force 1 column width, stack vertically.
- Tablet: Shrink width to fit available columns.
- Desktop: Use original configuration.
Phase 2: Overrides (Advanced)
Specific widgets can provide override configurations for fine-grained control.
position: {
x: 0, y: 0, width: 6, height: 4,
responsive: {
mobile: { height: 2 } // Shorter on mobile
}
}
🔌 Integration Patterns
Dashboard Integration
Dashboards consume AppConfigService to get the list of ResolvedWidgetConfig.
<lib-gs-widget-grid [widgets]="enabledWidgets()" [gridConfig]="config" />
Module Registration
Modules define widgets in their manifest. The system automatically registers them.
embeddableComponents: [
{
id: 'my-module:widget',
componentType: MyWidgetComponent,
category: 'widget'
}
]
📊 Data Models
GridConfig
Defines the structure of the grid.
interface GridConfig {
columns: number;
gap: number;
rowHeight: number | 'auto';
breakpoints: { ... };
}
ResolvedWidgetConfig
The runtime configuration for a widget instance.
interface ResolvedWidgetConfig {
id: string;
componentType: Type<unknown>;
position: { x, y, width, height };
inputs?: Record<string, any>;
}
🛡️ Error Handling
The WidgetContainerComponent acts as a firewall. If a widget throws an error:
- The error is caught.
- The widget is replaced by a
WidgetErrorComponent. - The rest of the dashboard continues to function.
- Users can try to "Retry" just that specific widget.
Status: ✅ Production Architecture Last Updated: December 3, 2025