Adjusted internal documentation links and updated references within various Markdown files to reflect a new directory structure for audit and meta documents. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 4dee684a-a4b9-4c32-a818-3a27dae1b027 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 971b8c75-c322-4ede-98ea-eb5ae31d4e5c Replit-Helium-Checkpoint-Created: true
14 KiB
Dashboard UI Audit
Document Version: 1.0
Last Updated: January 2026
Scope: Client bundle structure, D3 charting, clock displays, browser settings, rendering pipeline
1. Executive Summary
The Nightscout web dashboard provides real-time glucose visualization with extensive customization options. This audit examines the frontend architecture, rendering pipeline, and modernization opportunities.
Dashboard Overview
| Metric | Value |
|---|---|
| Bundle System | Webpack 5 |
| UI Framework | jQuery + D3.js |
| Charting | D3.js v5 + Flot |
| Real-time Updates | Socket.IO |
| Bundle Size | ~1MB+ (production) |
2. Client Bundle Architecture
2.1 Entry Point
Location: bundle/bundle.source.js
import '../static/css/drawer.css';
import '../static/css/dropdown.css';
import '../static/css/sgv.css';
$ = require("jquery");
require('jquery-ui-bundle');
window._ = require('lodash');
window.d3 = require('d3');
require('jquery.tooltips');
window.Storage = require('js-storage');
require('flot');
require('../node_modules/flot/jquery.flot.time');
2.2 Module Structure
bundle/
└── bundle.source.js # Main entry point
lib/client/
├── index.js # Client initialization
├── chart.js # D3 chart rendering
├── renderer.js # UI rendering utilities
├── hashauth.js # Client-side authentication
├── browser-settings.js # User preferences
├── receiveddata.js # Data merge/cache logic
└── socket.js # WebSocket handling
2.3 Build Configuration
Location: webpack/webpack.config.js
Key Settings:
- Output:
static/bundle.js - Mode: production/development
- Moment locale optimization
- Babel transpilation
Scripts:
{
"bundle": "webpack --mode production --config webpack/webpack.config.js",
"bundle-dev": "webpack --mode development --config webpack/webpack.config.js",
"bundle-analyzer": "webpack --mode development ... --json > stats.json && webpack-bundle-analyzer stats.json"
}
3. UI Framework Components
3.1 jQuery Usage
Version: ^3.5.1
Primary Uses:
- DOM manipulation
- Event handling
- AJAX requests (deprecated pattern)
- jQuery UI for dialogs, datepickers
Code Pattern:
$('#container').html(content);
$('.sgv-pill').removeClass('urgent').addClass('info');
$('#currentBG').text(utils.scaleMgdl(bg));
3.2 D3.js Usage
Version: ^5.16.0
Primary Uses:
- SVG chart rendering
- Data binding
- Scales and axes
- Transitions and animations
Chart Types:
- Main glucose chart (focus area)
- Context brush chart (overview)
- Treatment overlays
- Prediction lines
3.3 Flot Usage
Version: ^0.8.3 (legacy)
Primary Uses:
- Report charts
- Pie charts (glucose distribution)
- Time-series in reports
Status: Legacy dependency, candidate for removal
4. Main Chart Implementation
4.1 Chart Structure
Location: lib/client/chart.js
┌─────────────────────────────────────────────────────────────┐
│ Focus Chart Area │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Glucose readings (SGV dots) │ │
│ │ Trend line │ │
│ │ Predictions (if enabled) │ │
│ │ Treatment markers │ │
│ │ Basal profile (if enabled) │ │
│ │ │ │
│ │ Y-axis: mg/dL or mmol/L │ │
│ │ X-axis: Time │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Context Chart (Brush Selector) │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
4.2 Chart Initialization
function init (client, d3, $) {
var chart = {};
var utils = client.utils;
var renderer = client.renderer;
// Define scales
chart.xScale = d3.scaleTime();
chart.yScale = d3.scaleLinear();
// Define axes
chart.xAxis = d3.axisBottom(chart.xScale);
chart.yAxis = d3.axisLeft(chart.yScale);
// Define brush for context chart
chart.brush = d3.brushX();
return chart;
}
4.3 Data Rendering
Glucose Readings:
chart.bindData(sgvs)
.enter()
.append('circle')
.attr('class', function(d) { return 'sgv ' + getColorClass(d); })
.attr('cx', function(d) { return chart.xScale(d.mills); })
.attr('cy', function(d) { return chart.yScale(d.sgv); })
.attr('r', 3);
Treatments:
chart.renderTreatments(treatments)
.enter()
.append('g')
.attr('class', 'treatment')
.attr('transform', function(d) {
return 'translate(' + chart.xScale(d.mills) + ',' + y + ')';
});
4.4 Color Coding
| Range | Class | Default Color |
|---|---|---|
| Urgent High | urgent |
Red |
| High | warn |
Yellow |
| In Range | inrange |
Green |
| Low | warn |
Yellow |
| Urgent Low | urgent |
Red |
Thresholds (configurable):
BG_HIGH=260
BG_TARGET_TOP=180
BG_TARGET_BOTTOM=80
BG_LOW=55
5. Clock Display Views
5.1 Clock View Types
Location: views/clockviews/
| View | Purpose | Features |
|---|---|---|
| Clock | Simple clock display | BG, time, trend |
| Color Clock | Color-coded by range | Visual range indication |
| BGClock | BG-focused display | Large BG, delta |
| Simple BG | Minimal display | BG only |
5.2 Clock CSS Structure
Location: views/clockviews/clock-shared.css
body {
text-align: center;
background-color: black;
color: grey;
overflow: hidden;
}
#currentBG {
font-size: 20vmin;
font-weight: bold;
}
#currentDelta {
font-size: 10vmin;
}
5.3 Clock Configuration
Location: views/clockviews/clock-config.css
Configuration panel for:
- Time format (12h/24h)
- Units (mg/dL, mmol/L)
- Display elements visibility
- Color themes
6. Browser Settings
6.1 Settings Storage
Location: lib/client/browser-settings.js
Uses js-storage for localStorage management:
var Storages = require('js-storage');
var storage = Storages.localStorage;
browserSettings.load = function() {
return storage.get(STORAGE_KEY) || {};
};
browserSettings.save = function(settings) {
storage.set(STORAGE_KEY, settings);
};
6.2 Available Settings
| Setting | Type | Default | Description |
|---|---|---|---|
units |
string | "mg/dl" | Display units |
timeFormat |
number | 12 | Time format (12/24) |
nightMode |
boolean | false | Dark theme |
showRawbg |
string | "never" | Raw BG display |
customTitle |
string | "Nightscout" | Custom page title |
theme |
string | "default" | Color theme |
alarmUrgentHigh |
boolean | true | Enable urgent high alarm |
alarmHigh |
boolean | true | Enable high alarm |
alarmLow |
boolean | true | Enable low alarm |
alarmUrgentLow |
boolean | true | Enable urgent low alarm |
alarmTimeagoWarn |
boolean | true | Enable stale data warning |
6.3 Settings Sync
Settings are stored locally and not synced:
- Each browser has independent settings
- No server-side storage of preferences
- Token-based URL sharing possible
7. Rendering Pipeline
7.1 Initial Load
Page Load
↓
Load bundle.js (~1MB)
↓
Initialize client
↓
Fetch /api/v1/status
↓
Connect WebSocket
↓
Fetch initial data (/api/v1/entries, /api/v1/treatments)
↓
Render chart
↓
Subscribe to updates
7.2 Real-Time Update Cycle
WebSocket dataUpdate event
↓
receiveDData.mergeDataUpdate()
↓
Update local data cache
↓
Run plugins (setProperties)
↓
Update pills and status
↓
chart.update()
↓
D3 data binding
↓
DOM update
7.3 Performance Metrics
| Metric | Typical Value | Target |
|---|---|---|
| Initial bundle load | 1-2s | <1s |
| First paint | 2-3s | <1.5s |
| Chart render | 100-200ms | <100ms |
| Data update | 50-100ms | <50ms |
8. View Templates
8.1 Template Engine
Engine: EJS (Embedded JavaScript)
Main Template: views/index.html
8.2 Page Structure
<!DOCTYPE html>
<html>
<head>
<title>Nightscout</title>
<link rel="stylesheet" href="/bundle/bundle.css">
</head>
<body>
<nav id="navbar">
<!-- Navigation and pills -->
</nav>
<main>
<div id="container">
<svg id="chartContainer"></svg>
</div>
</main>
<script src="/bundle/bundle.js"></script>
</body>
</html>
8.3 Available Views
| Route | View | Purpose |
|---|---|---|
/ |
index | Main dashboard |
/report |
report | Reports viewer |
/profile |
profile | Profile editor |
/admin |
admin | Admin tools |
/food |
food | Food database |
/clock |
clock | Simple clock |
/clock-color |
clock-color | Color clock |
/bgclock |
bgclock | BG clock |
/simplebg |
simplebg | Simple BG |
9. Responsive Design
9.1 Current State
- Desktop-first design
- Limited mobile optimization
- Fixed breakpoints
9.2 Breakpoints
/* Example from existing CSS */
@media (max-width: 768px) {
.toolbar { display: none; }
#container { width: 100%; }
}
9.3 Mobile Issues
| Issue | Impact | Status |
|---|---|---|
| Touch events | Poor mobile interaction | Partial |
| Chart zoom | Pinch zoom not supported | Open |
| Portrait mode | Layout issues | Partial |
| PWA support | Not installable | Open |
10. Accessibility
10.1 Current State
- Limited ARIA labels
- No keyboard navigation
- Color-only status indication
- No screen reader support
10.2 Accessibility Issues
| Issue | WCAG | Priority |
|---|---|---|
| Missing alt text | 1.1.1 | High |
| Color contrast | 1.4.3 | Medium |
| Focus indicators | 2.4.7 | Medium |
| Status announcements | 4.1.3 | High |
10.3 Recommendations
- Add ARIA labels to interactive elements
- Implement keyboard navigation
- Add screen reader announcements for alarms
- Improve color contrast ratios
- Add focus visible styles
11. Performance Optimization
11.1 Bundle Size Analysis
Current Bundle (~1MB+):
| Library | Size (approx) | Optimization |
|---|---|---|
| D3.js | 250KB | Tree-shake unused |
| jQuery | 90KB | Consider removal |
| Lodash | 70KB | Use lodash-es |
| Moment.js | 230KB | Replace with dayjs |
| Socket.IO | 50KB | Current |
| Flot | 100KB | Remove (legacy) |
11.2 Optimization Strategies
-
Code Splitting:
// Dynamic import for reports const reports = await import('./reports'); -
Tree Shaking:
// Instead of: import _ from 'lodash'; // Use: import { debounce, throttle } from 'lodash-es'; -
Lazy Loading:
- Load reports module on demand
- Defer non-critical CSS
-
Asset Optimization:
- Compress images
- Use WebP format
- Implement caching headers
11.3 Performance Budget
| Metric | Current | Target |
|---|---|---|
| Bundle size (gzip) | ~300KB | <200KB |
| First contentful paint | 2.5s | <1.5s |
| Time to interactive | 4s | <2s |
| Lighthouse score | ~60 | >80 |
12. Issues and Recommendations
12.1 Critical Issues
| Issue | Impact | Recommendation |
|---|---|---|
| Large bundle size | Slow initial load | Code splitting |
| No PWA support | Mobile experience | Add service worker |
| jQuery dependency | Maintenance burden | Migrate to vanilla JS |
12.2 UI Framework Migration
Options:
-
Vanilla JavaScript:
- Pros: No framework overhead
- Cons: More code to maintain
-
React:
- Pros: Large ecosystem, component model
- Cons: Significant rewrite
-
Vue.js:
- Pros: Gentle learning curve
- Cons: Less ecosystem than React
-
Svelte:
- Pros: Small bundle, no virtual DOM
- Cons: Smaller ecosystem
Recommendation: Consider incremental migration to Svelte or Vue for new features while maintaining existing code.
12.3 Chart Library Migration
D3.js v5 → v7:
- Breaking changes in API
- Worth migrating for bundle size
- Better TypeScript support
Alternative: Chart.js:
- Pros: Simpler API, smaller bundle
- Cons: Less customization
- Suitable for reports
12.4 Modernization Roadmap
-
Phase 1 (0-3 months):
- Add service worker for PWA
- Implement code splitting
- Replace Moment.js with dayjs
-
Phase 2 (3-6 months):
- Migrate from jQuery to vanilla JS
- Add responsive design improvements
- Implement accessibility basics
-
Phase 3 (6-12 months):
- Consider framework adoption
- Upgrade D3.js to v7
- Remove Flot dependency