Dashboard System Architecture
Comprehensive guide to the SveltyCMS dashboard system including widget architecture, customization, and audit log monitoring.
On this page
The SveltyCMS dashboard provides a powerful, customizable monitoring interface built on a modular widget system. It offers real-time system metrics, security monitoring, content management insights, and enterprise-grade audit logging capabilities.
This document outlines the complete dashboard architecture, widget system, and integration patterns.
System Overview
The dashboard is built on a flexible, grid-based widget system that allows administrators and users to create personalized monitoring interfaces tailored to their specific needs.
Core Architecture
Widget Architecture
Base Widget System
All dashboard widgets extend the base-widget.svelte component, which provides:
- Standardized Layout: Consistent header, content area, and controls
- State Management: Persistent widget configuration and data caching
- Auto-refresh: Configurable polling intervals for live data
- Error Handling: Graceful error states and retry mechanisms
- Accessibility: Full keyboard navigation and screen reader support
Widget Registration
Widgets use dual discovery:
- Client (
+page.svelte) — Viteimport.meta.glob("./widgets/*.svelte")builds the runtime registry for lazy-loaded rendering. - Server (
+page.server.ts) —readdirSyncscans all*.sveltefiles inwidgets/and dynamically importswidgetMetafor the widget picker.
// Client registry in +page.svelte
const modules = import.meta.glob("./widgets/*.svelte");
// Server discovery in +page.server.ts
const files = readdirSync(widgetsPath).filter(
(file) => file.isFile() && file.name.endsWith(".svelte"),
);
Generative Dashboard
generativedashboard.svelte on the dashboard page provides an AI-assisted layout builder. It reuses the same widget registry and persists layouts through system-preferences.
Widget Metadata Schema
Each widget exports metadata for dashboard integration:
export const widgetMeta = {
name: "Widget Display Name",
icon: "mdi:icon-name",
description: "Brief description for widget picker",
defaultSize: { w: 2, h: 2 }, // Grid units
category: "monitoring" | "logs" | "content" | "static",
};
Available Widget Categories
1. System Monitoring Widgets
Real-time system performance and health monitoring with adaptive h:1 compact / h:2+ rich layouts:
cpu-widget.svelte
- Purpose: Live CPU usage monitoring with SVG sparklines and h:1 compact mode
- Features: Multi-core visualization, load average, temperature alerts
- Refresh: 2-second intervals for real-time monitoring
- Size: 2x2 grid units (default)
memory-widget.svelte
- Purpose: RAM and swap usage tracking
- Features: Used/available memory, swap utilization, memory pressure alerts
- Refresh: 5-second intervals
- Size: 2x2 grid units
disk-widget.svelte
- Purpose: Storage usage and I/O performance
- Features: Multiple disk monitoring, free space alerts, I/O statistics
- Refresh: 30-second intervals (storage changes slowly)
- Size: 2x2 grid units
cache-monitor-widget.svelte
- Purpose: Application cache performance monitoring
- Features: Hit/miss ratios, MB/GB size display, per-category breakdown, h:1 compact summary
- Refresh: 10-second intervals
- Size: 2x1 grid units
unified-metrics-widget.svelte ⭐ New
- Purpose: Comprehensive system performance and security overview
- Features: 3-tier layout (h:1 compact, h:2 rich, h:3+ full), health scoring, SVG sparklines
- Size: 2x3 grid units (default, pollInterval: 6s)
system-health-widget.svelte
- Purpose: Overall system health status
- Features: Aggregate health score, service status, uptime tracking
- Refresh: 15-second intervals
- Size: 3x1 grid units
database-pool-diagnostics.svelte ⭐ New
- Purpose: Real-time database connection pool monitoring
- Features:
- Pool Statistics: Total, active, idle connections, waiting requests
- Health Status: Visual health indicators (healthy/degraded/critical)
- Utilization Metrics: Pool utilization percentage with color-coded progress bar
- Smart Recommendations: Actionable optimization suggestions
- Auto-refresh: 30-second intervals for up-to-date pool health
- Integration: Uses DatabaseResilience system for diagnostics
- Refresh: 30-second intervals
- Size: 2x3 grid units
- Role-Based: Admin-only access (requires admin role for pool diagnostics API)
- API Endpoint:
/api/database/pool-diagnostics
2. Security & Audit Widgets
Enterprise-grade security monitoring and compliance tracking:
audit-log-widget.svelte ⭐ New
- Purpose: Real-time audit log monitoring and security event tracking
- Features:
- Admin View: System-wide security statistics, suspicious activity alerts
- User View: Personal activity log, security notifications
- Event Filtering: By type (auth, security, data), severity, time range
- Real-time Alerts: Critical security events with immediate notifications
- Compliance Ready: Structured logging for regulatory requirements
- Refresh: 10-second intervals for security-critical monitoring
- Size: 3x3 grid units (accommodates rich security data)
- Role-Based: Dynamically adapts content based on user permissions
security-widget.svelte
- Purpose: Advanced threat monitoring and incident response
- Features: Threat level indicators, blocked IPs, CSP violations
- Refresh: 5-second intervals for threat detection
- Size: 3x3 grid units
- API Endpoint:
/api/dashboard/security
3. Content Management Widgets
Content and media monitoring for editorial workflows:
last5-content-widget.svelte
- Purpose: Recent content creation and editing activity
- Features: Collection-based content listing, author attribution
- Refresh: Manual refresh (content changes less frequently)
- Size: 2x3 grid units
last5-media-widget.svelte
- Purpose: Recent media uploads and management
- Features: Thumbnail previews, upload statistics, storage usage
- Refresh: Manual refresh
- Size: 2x3 grid units
4. System Information Widgets
Operational insights and system communication:
logs-widget.svelte ⭐ Enhanced
- Purpose: Filterable system log viewer
- Features: Expandable cards, level filter, date range, text search, h:1 compact chips
system-messages-widget.svelte ⭐ Enhanced
- Purpose: System notifications with severity indicators
- Features: Severity-colored accents (critical/error/warning/info), auto-detected links, clickable expand, h:1 compact chips
user-online-widget.svelte ⭐ Enhanced
-
Purpose: Real-time online user presence
-
Features: Role badges (admin/editor/viewer), green presence dots, Gravatar support, h:1 compact avatar chips
-
Size: 2x1 grid units
performance-widget.svelte
- Purpose: Application performance metrics and optimization insights
- Features: Response times, throughput, performance trends
- Refresh: 15-second intervals
- Size: 3x2 grid units
unified-metrics-widget.svelte
- Purpose: Consolidated system metrics overview
- Features: Multi-metric dashboard, customizable thresholds
- Refresh: 10-second intervals
- Size: 4x2 grid units
Grid System & Customization
Responsive Grid Layout
The dashboard uses a 4-column responsive grid system:
- Desktop (>1200px): 4 columns, full widget functionality
- Tablet (768-1200px): 3 columns, condensed layouts
- Mobile (<768px): 1 column, stacked vertically
Drag & Drop System
Users can customize their dashboard through intuitive drag-and-drop:
// Drag and drop implementation highlights
let dragState = $state({
item: null,
element: null,
offset: { x: 0, y: 0 },
isActive: false,
gridPosition: { row: number, col: number },
});
function handleDragStart(event, widget) {
dragState.item = widget;
dragState.isActive = true;
// Calculate grid position and visual feedback
}
function handleDrop(event) {
// Update widget positions in system-preferences
// Persist new layout configuration
}
Widget Sizing
Widgets support flexible sizing within the grid:
- Minimum Size: 1x1 grid unit
- Maximum Size: 4x4 grid units
- Responsive Scaling: Automatic size adjustment on smaller screens
- Aspect Ratio: Maintained during resize operations
Data Flow & Performance
Widget Data Loading
Each widget follows a standardized data loading pattern:
// Widget data loading lifecycle
async function loadWidgetData() {
isLoading = true;
error = null;
try {
// 1. Check cache (if enabled)
const cachedData = getCache(cacheKey);
if (cachedData && !isExpired(cachedData)) {
return cachedData.data;
}
// 2. Fetch fresh data
const response = await fetch(endpoint);
const data = await response.json();
// 3. Update cache
setCache(cacheKey, data, cacheTTL);
return data;
} catch (err) {
// 4. Handle errors with retry logic
error = err.message;
scheduleRetry();
} finally {
isLoading = false;
}
}
Performance Optimizations
- Lazy Loading: Widgets load components only when scrolling into view (Intersection Observer)
- Smart Caching: Configurable TTL caching per widget category
- Debounced Refresh: Prevents excessive API calls during rapid interactions
- Progressive Enhancement: Core functionality works without JavaScript
- Code Splitting: Each widget is a separate chunk, reducing initial bundle by 200-300KB
- No Wrapper Components: Direct lazy loading eliminates unnecessary component layers
Lazy Loading Implementation
Dashboard implements native lazy loading without wrapper components for maximum performance:
// Integrated lazy loading in +page.svelte
let loadedWidgets = $state<Map<string, any>>(new Map());
let widgetObservers = new Map<string, IntersectionObserver>();
// Load widget when it becomes visible
function setupWidgetObserver(element: HTMLElement, params: [string, string]) {
const [widgetId, componentName] = params;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && !loadedWidgets.has(widgetId)) {
// Dynamic import when visible
loadWidgetComponent(widgetId, componentName);
observer.disconnect();
}
});
},
{ rootMargin: "100px" }, // Preload 100px before visible
);
observer.observe(element);
return { destroy: () => observer.disconnect() };
}
Benefits of Direct Integration:
- ✅ 40% Faster: No wrapper component overhead
- ✅ Type Safe: Direct TypeScript inference without prop drilling
- ✅ Smaller Bundle: Eliminates 5KB of wrapper code
- ✅ Simpler Debugging: Single component to trace
- ✅ Better DX: One file to maintain instead of two
Performance Benchmarks
Based on production testing with 12 widgets:
- Initial Load: < 500ms (dashboard shell only)
- Widget Loading: 50-150ms per widget (as they scroll into view)
- Total Bundle Reduction: ~250KB from lazy loading
- Memory Usage: 60% lower than eager loading
- Time to Interactive: < 1.2s on 3G connection
Widget Categories & Defaults
Widgets are categorized for optimal performance configuration:
export const WIDGET_DEFAULTS = {
// Real-time monitoring (no cache, frequent updates)
monitoring: {
showRefreshButton: true,
cacheKey: undefined,
retryCount: 3,
retryDelay: 1000,
},
// Activity logs (auto-poll, moderate caching)
logs: {
showRefreshButton: false,
cacheKey: undefined,
retryCount: 2,
retryDelay: 1000,
},
// Content listings (cached, manual refresh)
content: {
showRefreshButton: false,
cacheKey: (id: string) => `content-${id}`,
cacheTTL: 120000, // 2 minutes
retryCount: 3,
retryDelay: 1000,
},
};
Audit Log Widget Deep Dive
The new audit-log-widget represents the latest advancement in dashboard security monitoring:
Role-Based Functionality
Administrator View
// Admin users see comprehensive security overview
if (isAdmin && !showPersonalOnly) {
// System-wide statistics
const stats = await getAuditStatistics(7); // Last 7 days
// Suspicious activity detection
const suspicious = await getSuspiciousActivities(5);
// All system events
const events = await queryAuditLogs({ limit: 10 });
}
Regular User View
// Regular users see personal activity only
const personalEvents = await queryAuditLogs({
actorId: currentUser.id,
limit: 10,
});
Security Event Categories
The widget intelligently categorizes and displays events:
- Authentication Events: Login attempts, 2FA changes, password resets
- Security Events: Unauthorized access, privilege escalation, suspicious activity
- Data Operations: Exports, imports, sensitive data access
- System Events: Configuration changes, administrative actions
Real-Time Alerting
Critical security events trigger immediate visual alerts:
// Suspicious activity alert system
if (suspiciousEvents.length > 0) {
// Show prominent alert banner
// Highlight critical events in timeline
// Trigger browser notifications (if permitted)
}
Integration Points
The audit widget seamlessly integrates with:
- User Management System: Profile changes, role modifications
- Authentication Service: Login events, 2FA status
- Content Management: Data access, export operations
- API Gateway: Token usage, rate limiting events
Dashboard API Endpoints
The dashboard handler (src/routes/api/[...path]/handlers/dashboard.ts) exposes 13 RESTful sub-routes under /api/dashboard/*. All require session authentication and the dashboard:read permission (mapped in ENDPOINT_PERMISSIONS). Paths use kebab-case (system-info, last5-content, online-user).
Authentication & Multi-tenancy
Requests pass through the API dispatcher (+server.ts) which enforces authentication and checkEndpointPermission before reaching the dashboard handler. All dashboard widgets respect multi-tenancy:
- Tenant-scoped queries use
locals.tenantIdfor every database operation - System-wide widgets (health, metrics, system-info) return global data visible to all tenants
- Per-tenant widgets (last5-content, audit, security) filter results by
locals.tenantId - Dashboard layout preferences are stored per-user per-tenant (compound key
tenantId:userId) - Cache keys include
tenantIdto prevent cross-tenant cache leakage
Widget developers adding new dashboard endpoints must include tenantId in all database queries:
// ✅ Correct: dashboard handler passes tenantId
const result = await dbAdapter.crud.findMany("collection", {
tenantId: event.locals.tenantId, // ← Required for tenant isolation
...otherFilters,
});
// ❌ Wrong: missing tenantId — returns ALL tenants' data
const result = await dbAdapter.crud.findMany("collection", otherFilters);
Endpoint Reference
1. GET /api/dashboard/health
System health check for dashboard widgets.
Authentication: Required (dashboard:read)
Response:
{
"overallStatus": "READY" | "DEGRADED" | "INITIALIZING" | "FAILED" | "IDLE",
"timestamp": "2025-01-20T10:30:00Z",
"uptime": 3600,
"components": {
"database": { "status": "healthy", "responseTime": 5 },
"cache": { "status": "healthy" }
}
}
Status Codes:
200: System is READY or DEGRADED503: System is INITIALIZING, FAILED, or IDLE
Use Case: Load balancer health checks, uptime monitoring
2. GET /api/dashboard/metrics
Performance metrics from the MetricsService.
Authentication: Required (session cookie)
Query Parameters:
detailed(boolean): Include system metrics (memory, uptime)
Response:
{
"requests": { "total": 1523, "success": 1498, "errors": 25 },
"auth": { "logins": 342, "failures": 12, "logouts": 298 },
"cache": { "hits": 8543, "misses": 432 },
"sessions": { "active": 23, "total": 342 },
"system": {
// Only if detailed=true
"memory": { "used": 2147483648, "total": 8589934592 },
"uptime": 3600000
}
}
Use Case: performance-widget, unified-metrics-widget
3. GET /api/dashboard/system-info
Comprehensive system information: CPU, memory, disk, and OS.
Authentication: Required (dashboard:read)
Query Parameters:
type(string): Filter by type (cpu,disk,memory,network,os,process, orall)
Caching: 1-second TTL to prevent excessive system calls
Response:
{
"cpuInfo": {
"model": "Intel Core i7-9750H",
"cores": 12,
"speed": 2600,
"usage": 45.3,
"loadAverage": [2.1, 1.8, 1.5],
"history": [42.1, 43.5, 45.3]
},
"memoryInfo": {
"total": 17179869184,
"used": 12884901888,
"free": 4294967296,
"swapTotal": 2147483648,
"swapUsed": 1073741824
},
"diskInfo": {
"mounts": [
{
"filesystem": "/dev/sda1",
"size": 512110190592,
"used": 256055095296,
"available": 256055095296,
"capacity": 50,
"mounted": "/"
}
]
}
}
Use Case: cpu-widget, memory-widget, disk-widget, system-health-widget
4. GET /api/dashboard/logs
System logs with ANSI color conversion to HTML.
Authentication: Required (session cookie)
Query Parameters:
level(string): Filter by log level (error,warn,info,debug)search(string): Search within log messagesstartDate(ISO 8601): Filter logs after this dateendDate(ISO 8601): Filter logs before this datepage(number): Page number (default: 1)limit(number): Results per page (max: 100, default: 50)
Features:
- ANSI color codes converted to HTML
<span>elements - Supports compressed log files (
.gz,.br) - Pagination for large log files
- Real-time log tailing
Response:
{
"logs": [
{
"timestamp": "2025-01-20T10:30:15",
"level": "info",
"message": "User logged in",
"messageHtml": "<span style='color:#00ff00'>User logged in</span>"
}
],
"total": 1523,
"page": 1,
"totalPages": 31
}
Use Case: logs-widget
5. GET /api/dashboard/last5-content
Recent content from all collections via LocalCMS.collections.search.
Authentication: Required (dashboard:read)
Query Parameters:
limit(number): Number of items (max: 50, default: 5)
Features:
- Multi-collection aggregation across all tenant collections
- Sorted by
updatedAt(newest first) - Tenant-scoped queries
Response:
[
{
"id": "post-123",
"title": "Latest Blog Post",
"collection": "posts",
"createdAt": "2025-01-20T10:00:00Z",
"createdBy": "john.doe",
"status": "published"
}
]
Use Case: last5-content-widget
6. GET /api/dashboard/last5media
Recent media files from the media library.
Authentication: Required (session cookie)
Features:
- Database adapter integration
- Tenant-scoped queries
- File metadata (size, modified date, MIME type)
Response:
[
{
"name": "hero-image.jpg",
"size": 2457600,
"modified": "2025-01-20T09:45:00Z",
"type": "image/jpeg",
"url": "/media/hero-image.jpg"
}
]
Use Case: last5-media-widget
7. GET /api/dashboard/online-user
Currently online users derived from active sessions (getAllActiveSessions).
Authentication: Required (dashboard:read)
Features:
- Active session tracking (no synthetic random durations)
- Username and avatar display
- Online time formatting (“2h 15m”)
- Sorted by longest online time first
Response:
{
"onlineUsers": [
{
"id": "user-123",
"name": "John Doe",
"avatarUrl": "/avatars/john.jpg",
"onlineTime": "2h 15m",
"onlineMinutes": 135
}
]
}
Use Case: user-online-widget
8. GET /api/dashboard/system-messages
System messages derived from audit logs.
Authentication: Required (dashboard:read)
Query Parameters:
limit(number): Number of messages (max: 50, default: 5)
Features:
- Tail reading from log files
- Log parsing with structured output
- Default message when no logs available
- Message prioritization by severity
Response:
[
{
"id": "msg-1",
"title": "System Update",
"message": "New version deployed successfully",
"level": "info",
"timestamp": "2025-01-20T10:30:00Z",
"type": "system"
}
]
Use Case: system-messages-widget
9. GET /api/dashboard/cache-metrics
Cache performance metrics from CacheMetrics service.
Authentication: Required (session cookie)
Methods:
- GET: Retrieve cache metrics
- DELETE: Reset all cache metrics (admin only)
Response:
{
"overall": {
"hits": 8543,
"misses": 432,
"hitRate": 95.2,
"size": 2147483648
},
"byCategory": {
"content": { "hits": 5234, "misses": 123 },
"media": { "hits": 2109, "misses": 234 },
"system": { "hits": 1200, "misses": 75 }
},
"byTenant": {
"tenant-1": { "hits": 4321, "misses": 198 },
"tenant-2": { "hits": 4222, "misses": 234 }
},
"recentMisses": [{ "key": "content:post-123", "timestamp": "2025-01-20T10:30:00Z" }],
"timestamp": "2025-01-20T10:30:15Z"
}
Use Case: cache-monitor-widget
10. GET /api/dashboard/audit
Flat audit event feed for the audit-log widget.
Authentication: Required (dashboard:read)
11. GET /api/dashboard/security
Security incident statistics and active threats.
Authentication: Required (dashboard:read)
12. GET /api/dashboard/scim
SCIM provisioning status for the scim-status widget.
Authentication: Required (dashboard:read)
API Testing
Dashboard APIs have integration test coverage:
Test File: tests/integration/api/dashboard.test.ts
Coverage by Endpoint:
/health: 3 tests (status codes, component health, structure)/metrics: 3 tests (basic metrics, detailed mode, validation)/systemInfo: 6 tests (type filtering, caching, multi-platform)/logs: 5 tests (pagination, filtering, search, ANSI colors)/last5Content: 4 tests (content structure, limits, sorting)/last5media: 3 tests (media structure, empty handling)/online_user: 4 tests (user list, sorting, current user)/systemMessages: 4 tests (message structure, limits, defaults)/cache-metrics: 6 tests (metrics structure, categories, hit rates)
Running Dashboard Tests:
# Requires running development server
bun run dev
bun test tests/integration/api/dashboard.test.ts
Authentication in Tests:
// All tests use authenticated session
beforeAll(async () => {
const loginRes = await fetch("http://localhost:5173/api/auth/login", {
method: "POST",
body: JSON.stringify({ email: "admin@example.com", password: "admin123" }),
});
const cookies = loginRes.headers.get("set-cookie");
authCookie = cookies?.split(";")[0] || "";
});
Customization & Extension
Adding New Widgets
- Create Widget File:
src/routes/(app)/dashboard/widgets/my-widget.svelte - Export Metadata: Include
widgetMetaobject - Extend base-widget: Use provided component infrastructure
- Auto-Registration: Widget appears automatically in picker
Widget Development Best Practices
// Example widget structure
<script lang="ts" module>
export const widgetMeta = {
name: 'My Custom Widget',
icon: 'mdi:chart-line',
description: 'Custom monitoring widget',
defaultSize: { w: 2, h: 2 }
};
</script>
<script lang="ts">
// Widget logic, data loading, state management
</script>
<base-widget {label} {size} {onSizeChange}>
{#snippet children()}
<!-- Widget content -->
{/snippet}
</base-widget>
Configuration Persistence
Widget configurations are automatically persisted:
// System preferences store widget layouts
system-preferences: {
preferences: [
{
id: 'widget-123',
component: 'audit-log-widget',
size: { w: 3, h: 3 },
position: { x: 0, y: 0 },
config: { showPersonalOnly: false }
}
];
}
Security Considerations
Widget Security Model
- Permission-Based Rendering: Widgets respect user role limitations
- Data Isolation: Users can only access authorized data
- Secure Endpoints: All widget APIs protected by authentication
- XSS Prevention: All user content properly sanitized
Audit Trail Integration
All dashboard interactions are logged through the audit system:
- Widget additions/removals
- Configuration changes
- Data access patterns
- Security threshold breaches
Real-Time Data Streaming
Dashboard widgets receive live updates via svelte-realtime, which provides WebSocket-based streaming with SSE fallback. The integration lives in src/live/:
system.ts— Bridges the internalEventBusto connected WebSocket clients with tenant isolation. System events (content changes, user activity, cache invalidations) stream to all authorized dashboard widgets.chat.ts— Real-time AI chat for the dashboard co-pilot. Uses per-room streaming with individual access controls.ws-platform.ts— Shared WebSocket platform reference for global broadcasting. Initialized bysrc/hooks.ws.tsduring server startup.
// Dashboard widget subscribing to real-time events
import { events } from "$live/system";
$effect(() => {
const stream = events();
stream.subscribe((event) => {
// event contains: type, payload, timestamp, tenantId
updateWidgetData(event);
});
});
CDN Cache Purging
When content is published or media is updated, src/services/cdn/cdn-service.ts automatically purges the Cloudflare CDN cache to ensure global edge consistency:
import { cdnService } from "@services/cdn/cdn-service";
// Purge specific content by tags (surgical invalidation)
await cdnService.purge({ tags: ["collection:posts", "entry:abc123"] });
// Purge entire zone (use sparingly)
await cdnService.purge({ everything: true });
The service reads credentials from config/private.ts (CF_API_TOKEN, CF_ZONE_ID, CF_PURGE_MODE) and operates non-blocking — purge calls fire in the background without delaying the API response.
Security Alerting & SIEM Integration
src/services/security/monitoring-service.ts provides real-time anomaly detection with webhook-based alerting for external security systems:
import { securityMonitor } from "@services/security/monitoring-service";
// Start monitoring (called during server boot)
securityMonitor.start();
// Configure SIEM webhook (JSON, CEF, or LEEF format)
securityMonitor.configureWebhook({
url: "https://siem.company.com/ingest",
secret: "webhook-signing-key",
format: "cef",
enabled: true,
});
// Check monitoring status for dashboard widget
const status = securityMonitor.getStatus();
// { isMonitoring, alertCount, unacknowledgedCount, activeRules, eventCounts }
Five anomaly detection rules run automatically: brute force detection, unusual access patterns, permission escalation attempts, rapid session creation, and token abuse detection. Each rule has configurable thresholds and cooldown periods to prevent alert fatigue.
Planned Enhancements
- Custom Widget Builder — Visual widget creation interface for non-developers
- Export Capabilities — Dashboard screenshot and CSV/JSON data export
- PWA Support — Installable mobile dashboard with offline capability
- Service Worker Caching — Offline access to static dashboard assets
Conclusion
The SveltyCMS dashboard system provides a powerful, flexible foundation for monitoring and managing all aspects of the CMS platform. With the addition of comprehensive audit logging capabilities, administrators and users have unprecedented visibility into system operations, security events, and content management activities.
The modular widget architecture ensures the dashboard can evolve with changing requirements while maintaining optimal performance and user experience across all device types and user roles.