What changed
Until Phase 4 the dashboard was a single placeholder page. In Phase 5 it becomes a four-page application:
Behind the scenes, you’re using:
- Vue Router — client-side navigation between pages without a full reload.
- Chart.js — the line charts that appear when you tap a sensor card.
- Tailwind CSS — the design system. All colours, sizes, and spacing come from a small set of utility classes.
- Composables — reusable Vue functions like
useReadings()that share the live WebSocket between every page.
If every navigation reloaded the whole page, you’d also drop the WebSocket every time. By doing routing in JavaScript, the connection stays open and the data keeps flowing as you move around.
Pull and rebuild
The frontend image needs to be rebuilt because we’ve added Vue Router and Chart.js as dependencies.
cd /opt/iot-platform
git pull
docker compose build frontend
docker compose up -d
Building takes a couple of minutes the first time — npm install downloads ~130 packages. Watch the progress with:
docker compose logs -f frontend
Open http://pi-iot-XX.local/ on your laptop. You should see the new shell — a sidebar on the left with four icons, a top bar with the connection pill, and the sensor grid in the main area.
Tour the four pages
Click each icon in the sidebar in turn:
- ◉ Sensors — the home grid. Cards for every sensor that’s ever published. Run the test publisher again if it’s empty.
- ▦ Modules — placeholder tiles for the modules we haven’t built yet. They’re greyed out on purpose.
- ⚙ Settings — platform info plus a live feed of system events.
- i About — stack and phase summary.
Notice the URL changes (/, /modules, /settings, /about) but the page never fully reloads — the connection pill stays connected the whole time.
The browser’s back/forward buttons work as you’d expect — Vue Router uses the standard history.pushState API. This is what makes a SPA feel like a real website.
Tap a sensor card
Make sure the test publisher is running on your laptop (same command as Phase 4). On the Sensors page, click any card.
A modal opens with:
- The sensor name and current value, big and clear.
- A line chart showing the last ~100 readings, from oldest on the left to newest on the right.
- The chart auto-updates as new readings arrive — you should see the right edge advance roughly every second.
Hover anywhere on the chart line (or tap on a touchscreen) to see the exact value and timestamp at that point.
Close the modal by clicking the × button or tapping outside the box. Try a different sensor — the chart should be a different colour for humidity than for temperature.
When the modal opens, the dashboard fires off GET /api/sensors/<id>/readings?limit=100. That’s the same endpoint you tried with curl in Phase 4 — you’re reusing the work.
Read the audit log
Go to Settings. Below the platform info you’ll see a Recent events section listing the latest 50 rows from system_logs.
You should see at least one boot event from the last time the API started. Click Refresh to reload the list. If the API has been up since 03:00 UTC, you’ll also see a reading_retention.run event — that’s the nightly clean-up.
Try this: SSH into the Pi and restart the API:
docker compose restart api
Wait 5 seconds, then click Refresh on the Settings page. A new boot event should appear at the top of the list with the current timestamp.
In a real lab, you’ll want to know why something happened. The audit log gives a per-event trail: when did the platform restart, when did retention last run, when did an AI call fail. Operators love this stuff.
Touch test
The dashboard is meant to be used with fingers, not just a mouse. Open Chromium on the Pi’s 5″ touchscreen and visit:
http://localhost/
Run through these checks with your fingertip:
- Each sidebar icon is at least 48×48 pixels — you can hit it accurately on the first try.
- Sensor cards are big enough to read from across the room — the value uses an extra-large font.
- Tapping a card opens the modal smoothly. Tapping outside the modal or the close button dismisses it.
- The Settings Refresh button is easy to hit and gives visible feedback when you press it.
- Nothing depends on hovering the mouse — touch screens have no hover.
That’s a real bug. Touch targets below ~44 px are awkward even for adult fingers, terrible for primary-school students. Tell your teacher what you found — we’ll fix it.
Kiosk mode autostart
The final touch: the Pi should boot straight into the dashboard, full-screen, with no browser chrome or desktop visible. That’s called kiosk mode.
The repo has a script that sets it up:
cd /opt/iot-platform
./scripts/setup-kiosk.sh
The script:
- Installs Chromium if it’s missing.
- Writes a desktop autostart entry to
~/.config/autostart/iot-dashboard.desktop. - Configures Chromium to launch full-screen pointing at
http://localhost.
To test, reboot the Pi:
sudo reboot
After about a minute, the touchscreen should come up showing the dashboard full-screen — no taskbar, no address bar, just sensors.
Need to get out of kiosk mode (e.g. to update software)? Press Alt+F4 on a USB keyboard to quit Chromium. The desktop comes back. To go back into kiosk mode, just relaunch Chromium or reboot.
Different Pi OS versions use different desktop environments. Check that ~/.config/autostart/iot-dashboard.desktop exists. If it does and Chromium still doesn’t launch, try the older path ~/.config/lxsession/LXDE-pi/autostart — ask your teacher for the exact lines to add.
Final verification
The platform should now look and feel like a real classroom IoT terminal. Tick everything below before declaring Phase 5 done.