Water-quality monitoring is a useful example of how web development can connect data with real-world systems.
A dashboard can display measurements such as pH and water temperature, show the time of the latest reading, and flag values that need review.
In this tutorial, we will build a small front-end prototype using HTML and JavaScript. The example uses simulated readings, not real sensors.
What are we building?
Our dashboard will:
- Display a pH reading.
- Display a water-temperature reading.
- Show when the readings were updated.
- Reject invalid sensor values.
- Indicate when a reading falls outside configurable example limits.
Important: The example limits below are for demonstrating software logic only. They are not a validated pool-safety standard and must not be used to determine whether water is safe to swim in.
Step 1: Create the HTML
Create a file named index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Water Quality Dashboard</title>
</head>
<body>
<main>
<h1>Water Quality Dashboard</h1>
<section aria-labelledby="ph-heading">
<h2 id="ph-heading">pH reading</h2>
<p id="ph-value">Waiting for data...</p>
<p id="ph-status" aria-live="polite"></p>
</section>
<section aria-labelledby="temp-heading">
<h2 id="temp-heading">Water temperature</h2>
<p id="temp-value">Waiting for data...</p>
<p id="temp-status" aria-live="polite"></p>
</section>
<p id="updated"></p>
</main>
<script src="script.js"></script>
</body>
</html>
Step 2: Add the JavaScript
Create script.js:
const phValue = document.querySelector("#ph-value");
const phStatus = document.querySelector("#ph-status");
const tempValue = document.querySelector("#temp-value");
const tempStatus = document.querySelector("#temp-status");
const updated = document.querySelector("#updated");
// Illustrative thresholds for this demo only.
const demoLimits = {
phMin: 6.5,
phMax: 8.0,
temperatureMin: 10,
temperatureMax: 40
};
function isValidNumber(value) {
return typeof value === "number" && Number.isFinite(value);
}
function renderReading(data) {
if (
!isValidNumber(data.ph) ||
!isValidNumber(data.temperature)
) {
phValue.textContent = "Invalid reading";
phStatus.textContent = "Check the incoming data.";
tempValue.textContent = "Invalid reading";
tempStatus.textContent = "Check the incoming data.";
updated.textContent = "";
return;
}
phValue.textContent = data.ph.toFixed(2);
tempValue.textContent = `${data.temperature.toFixed(1)} °C`;
const phInDemoRange =
data.ph >= demoLimits.phMin &&
data.ph <= demoLimits.phMax;
const temperatureInDemoRange =
data.temperature >= demoLimits.temperatureMin &&
data.temperature <= demoLimits.temperatureMax;
phStatus.textContent = phInDemoRange
? "Within demonstration range"
: "Outside demonstration range";
tempStatus.textContent = temperatureInDemoRange
? "Within demonstration range"
: "Outside demonstration range";
updated.textContent =
`Updated: ${new Date(data.timestamp).toLocaleString()}`;
}
const simulatedReading = {
ph: 7.2,
temperature: 26.5,
timestamp: Date.now()
};
renderReading(simulatedReading);
Step 3: Understand the data flow
The dashboard receives an object containing measurements and a timestamp.
The renderReading() function first validates the values. It then updates the page using textContent, which avoids interpreting the readings as HTML.
Finally, it compares the readings with the example thresholds and displays a status message.
In a real application, the simulated object could be replaced with data from an API or an IoT gateway.
What would a production system need?
A real water-monitoring system would need more than a front-end dashboard:
- Calibrated sensors and documented measurement accuracy.
- Secure communication between devices and the server.
- Validation for missing, stale or implausible readings.
- Appropriate thresholds based on the application and relevant guidance.
- Error handling and alerts for sensor failures.
- Regular maintenance and verification against suitable testing methods.
A dashboard should never claim that pool water is safe solely because a few sensor readings appear normal.
Conclusion
This small project demonstrates how JavaScript can turn structured measurements into a readable dashboard. It also highlights a key principle of monitoring software: presenting data clearly is important, but validating the source and understanding the limitations are equally important.
From simulated sensor projects to real IoT applications, good monitoring starts with reliable data and honest reporting of uncertainty.
Top comments (0)