Neo.mjs is a unique application worker UI framework that moves most of the application logic off the main browser thread using Web Workers, delivering exceptional UI performance. But that multi-threaded performance advantage disappears the moment your app is down, your API is unreachable, or a worker task is silently crashing. Vigilmon gives you the visibility layer you need: continuous HTTP monitoring, heartbeat checks, and instant alerts routed to email or Slack.
What You'll Build
- A health API endpoint for your Neo.mjs backend
- Vigilmon HTTP monitors for your Neo.mjs app and backend
- A heartbeat for scheduled background tasks
- Alert channels (email and Slack)
- An uptime badge embedded in your Neo.mjs UI
Prerequisites
- A Neo.mjs project (
npx neo-app) - Node.js backend for the health endpoint
- A free Vigilmon account
Step 1: Add a Health Endpoint
Neo.mjs apps typically pair with a Node.js/Express backend. Add a /health route:
// server.js
import express from "express";
const app = express();
app.get("/health", async (req, res) => {
const checks = {};
let degraded = false;
// Database check
try {
// await db.query("SELECT 1");
checks.database = "ok";
} catch (err) {
checks.database = `error: ${err.message}`;
degraded = true;
}
// Worker service check — verify the Neo.mjs worker host is reachable
try {
const r = await fetch("http://localhost:8080/ping", {
signal: AbortSignal.timeout(3000),
});
checks.workerHost = r.ok ? "ok" : `http_${r.status}`;
} catch {
checks.workerHost = "unreachable";
degraded = true;
}
res.status(degraded ? 503 : 200).json({
status: degraded ? "degraded" : "ok",
timestamp: new Date().toISOString(),
checks,
});
});
app.listen(process.env.PORT ?? 3000);
Test it:
curl http://localhost:3000/health | jq .
# {"status":"ok","timestamp":"2026-06-29T...","checks":{"database":"ok","workerHost":"ok"}}
Step 2: Configure Vigilmon HTTP Monitors
Log in to Vigilmon → Monitors → New Monitor:
Monitor 1: Neo.mjs App Shell
| Field | Value |
|---|---|
| URL | https://yourapp.com/ |
| Method | GET |
| Expected status | 200 |
| Expected body | A stable string from your HTML shell |
| Check interval | 1 minute |
Monitor 2: Health API
| Field | Value |
|---|---|
| URL | https://yourapp.com/health |
| Method | GET |
| Expected status | 200 |
| Check interval | 1 minute |
With both monitors, you cover two independent failure classes: the static hosting layer and the backend/data layer. Neo.mjs's worker-based architecture means the app shell can load even when the worker host is unhealthy — monitoring both independently catches this.
Step 3: Heartbeat for Background Tasks
Background jobs — data prefetch, worker cache invalidation, session cleanup — can fail silently. A Vigilmon heartbeat catches this by alerting when the expected ping doesn't arrive.
npm install node-cron
// scheduler.js
import cron from "node-cron";
const VIGILMON_HEARTBEAT_URL = process.env.VIGILMON_HEARTBEAT_URL ?? "";
async function pingHeartbeat() {
if (!VIGILMON_HEARTBEAT_URL) return;
try {
await fetch(VIGILMON_HEARTBEAT_URL, { signal: AbortSignal.timeout(5000) });
} catch {
// Monitoring must never crash the job
}
}
cron.schedule("*/15 * * * *", async () => {
try {
await invalidateWorkerCache();
await pingHeartbeat();
} catch (err) {
console.error("[scheduler] Cache invalidation failed:", err);
// Vigilmon alerts after the heartbeat window expires with no ping
}
});
async function invalidateWorkerCache() {
// Your actual cache invalidation logic
}
Set up the heartbeat in Vigilmon:
- Monitors → New Heartbeat Monitor
- Set Expected interval to 30 minutes (2× the cron interval for a grace window)
- Copy the ping URL to your
.env:
VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/xxxxxxxx
Step 4: Display Uptime Status in Your Neo.mjs UI
Neo.mjs components extend Neo.component.Base. Add a status badge component that runs safely on the main thread:
// apps/myapp/view/StatusBadge.mjs
import Component from '../../../node_modules/neo.mjs/src/component/Base.mjs';
class StatusBadge extends Component {
static config = {
className: 'MyApp.view.StatusBadge',
badgeUrl_: 'https://vigilmon.online/api/badge/your-monitor-id.svg',
statusUrl_: 'https://vigilmon.online/status/your-monitor-slug',
tag: 'a',
domListeners: {},
};
getVdomRoot() {
return {
tag: 'a',
href: this.statusUrl,
target: '_blank',
rel: 'noopener noreferrer',
'aria-label': 'Service uptime status',
cn: [
{
tag: 'img',
src: this.badgeUrl,
alt: 'Uptime',
width: 120,
height: 20,
},
],
};
}
}
Neo.applyClassConfig(StatusBadge);
export default StatusBadge;
Add it to your main viewport:
// apps/myapp/view/MainContainer.mjs
import Container from '../../../node_modules/neo.mjs/src/container/Base.mjs';
import StatusBadge from './StatusBadge.mjs';
class MainContainer extends Container {
static config = {
className: 'MyApp.view.MainContainer',
layout: { ntype: 'vbox', align: 'stretch' },
items: [
// ... your main content
{ module: StatusBadge },
],
};
}
Neo.applyClassConfig(MainContainer);
export default MainContainer;
Step 5: Set Up Alert Channels
In Vigilmon's Alert Channels settings:
- Alert Channels → Email → add your on-call email
- Attach to both HTTP monitors and the heartbeat
Slack
- Create a Slack Incoming Webhook for
#alerts - Alert Channels → Webhook → paste the URL
- Payload template:
{
"text": "🚨 *{{ monitor.name }}* is DOWN\n{{ monitor.url }}\nStatus: {{ event.status }}\n<https://vigilmon.online|Open Vigilmon>"
}
Step 6: Verify Everything Works
# 1. Health endpoint responds correctly
curl -s https://yourapp.com/health | jq .
# 2. Simulate DB failure → confirm health returns 503
# Expected: Vigilmon alerts within 2 minutes
# 3. Remove VIGILMON_HEARTBEAT_URL → let the scheduler run
# Expected: heartbeat alert fires after the grace window
# 4. Vigilmon → "Test Alert" → confirm delivery to Slack/email
Summary
| Monitor | What It Catches | |---|---| | HTTP app shell check | Hosting failures, broken static deploys | | HTTP health API | Database and worker host failures | | Heartbeat | Scheduler crashes, silent cache/sync failures |
Next Steps
- Create separate monitors for staging vs. production
- Use Vigilmon's response time graphs to detect latency regressions caused by worker overhead
- Configure multi-channel alerting: email for low-severity, Slack for critical
Ready to get started? Sign up for Vigilmon free — have your first monitor running in under 5 minutes.