tutorial

Monitoring Your Reef.js App with Vigilmon: Health Checks, Heartbeats & Uptime Alerts

Add production-grade monitoring to a Reef.js reactive UI application — a health API, background job heartbeats, and instant alerts when your lightweight component-driven frontend or backend goes down.

Reef.js lets you build reactive, state-driven UI components without a framework, build step, or virtual DOM — just a tiny library you drop in. But no framework overhead still doesn't protect you from server outages, broken APIs, or silently failing background jobs. Vigilmon gives you the production observability your Reef.js app needs: continuous HTTP monitoring, heartbeat checks, and instant alerts routed to email or Slack.

What You'll Build

  • A health API endpoint for your Reef.js application backend
  • Vigilmon HTTP monitors for your Reef.js SPA and backend API
  • A heartbeat for scheduled background tasks
  • Alert channels (email and Slack)
  • An uptime badge rendered as a Reef.js component

Prerequisites

  • A Reef.js project (using reefjs or the CDN build)
  • Node.js backend for the health endpoint
  • A free Vigilmon account

Step 1: Add a Health Endpoint

Reef.js handles your client-side state; your backend provides data and serves your app. Add a /health route:

// server.js (Express)
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;
  }

  // External API check
  try {
    const response = await fetch("https://api.example.com/ping", {
      signal: AbortSignal.timeout(3000),
    });
    checks.external_api = response.ok ? "ok" : `http_${response.status}`;
  } catch (err) {
    checks.external_api = "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-07-03T...","checks":{"database":"ok","external_api":"ok"}}

Step 2: Configure Vigilmon HTTP Monitors

Log in to VigilmonMonitors → New Monitor:

Monitor 1: Reef.js SPA (frontend)

| Field | Value | |---|---| | URL | https://yourapp.com/ | | Method | GET | | Expected status | 200 | | Expected body | A stable string from your HTML (e.g. <div id="app">) | | Check interval | 1 minute |

Monitor 2: Backend Health API

| Field | Value | |---|---| | URL | https://yourapp.com/health | | Method | GET | | Expected status | 200 | | Check interval | 1 minute |

Covering both monitors lets you distinguish CDN/static serving failures from backend data layer failures.


Step 3: Heartbeat for Background Tasks

Reef.js apps are often backed by lightweight backends running scheduled tasks — data polling, cache warming, notification queues. These fail silently without a heartbeat check.

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("*/5 * * * *", async () => {
  try {
    await pollExternalData();
    await pingHeartbeat();
  } catch (err) {
    console.error("[scheduler] Data poll failed:", err);
    // Vigilmon alerts after the heartbeat window expires with no ping
  }
});

async function pollExternalData() {
  // Fetch and cache data that Reef.js components will consume
}

Set up the heartbeat in Vigilmon:

  1. Monitors → New Heartbeat Monitor
  2. Set Expected interval to 10 minutes (2× the cron interval)
  3. Copy the ping URL to your .env:
VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/xxxxxxxx

Step 4: Display Uptime Status as a Reef.js Component

Reef.js makes it easy to build a reactive status badge component that re-renders when state changes:

// src/status-badge.js
import Reef from "reefjs";

const BADGE_URL = "https://vigilmon.online/api/badge/your-monitor-id.svg";
const STATUS_URL = "https://vigilmon.online/status/your-monitor-slug";

const badgeStore = new Reef.Store({
  data: { loaded: false },
});

const statusBadge = new Reef("#vigilmon-badge", {
  store: badgeStore,
  template(props) {
    return `
      <a
        href="${STATUS_URL}"
        target="_blank"
        rel="noopener noreferrer"
        aria-label="Service uptime status"
        style="display:inline-flex;align-items:center"
      >
        <img
          src="${BADGE_URL}"
          alt="Uptime"
          width="120"
          height="20"
          style="opacity:${props.loaded ? 1 : 0};transition:opacity 0.2s"
        />
      </a>
    `;
  },
});

document.addEventListener("reef:render", (event) => {
  if (!event.target.closest("#vigilmon-badge")) return;
  const img = event.target.querySelector("img");
  if (img) {
    img.addEventListener("load", () => {
      badgeStore.data.loaded = true;
    }, { once: true });
  }
});

Add the mount point to your HTML:

<!-- index.html -->
<footer>
  <div id="vigilmon-badge"></div>
</footer>
<script type="module" src="/src/status-badge.js"></script>

Step 5: Set Up Alert Channels

In Vigilmon's Alert Channels settings:

Email

  1. Alert Channels → Email → add your on-call email
  2. Attach to both HTTP monitors and the heartbeat

Slack

  1. Create a Slack Incoming Webhook for #alerts
  2. Alert Channels → Webhook → paste the URL
  3. 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
curl -s https://yourapp.com/health | jq .

# 2. Break the DB connection string → confirm health returns 503
# Expected: Vigilmon alerts within 2 minutes

# 3. Remove VIGILMON_HEARTBEAT_URL → let the scheduler run without pinging
# Expected: heartbeat alert fires after the grace window

# 4. Vigilmon → "Test Alert" → confirm delivery to Slack/email

Summary

| Monitor | What It Catches | |---|---| | HTTP SPA check | CDN failures, broken static deploys | | HTTP health API | Database, cache, and third-party API failures | | Heartbeat | Scheduler crashes, silent data poll failures |


Next Steps

  • Create separate monitors for staging vs. production
  • Use Vigilmon's response time graphs to spot API latency spikes that affect Reef.js data loading
  • 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.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →