tutorial

Monitoring Your X-Tag App with Vigilmon: Health Checks, Heartbeats & Uptime Alerts

Add production-grade monitoring to an X-Tag Web Components application — a health API, background job heartbeats, and instant alerts when your custom elements or backend goes down.

X-Tag is Mozilla's small JavaScript library for creating reusable custom HTML elements using the Web Components standard. Its declarative, standards-based approach makes custom elements easy to compose, but production reliability requires more than good code — it requires visibility. Vigilmon gives you continuous HTTP monitoring, heartbeat checks, and instant alerts via email or Slack the moment your app or backend misbehaves.

What You'll Build

  • A health API endpoint for your X-Tag app's backend
  • Vigilmon HTTP monitors for your Web Components frontend and backend
  • A heartbeat for scheduled background tasks
  • Alert channels (email and Slack)
  • An uptime status custom element using X-Tag itself

Prerequisites

  • An X-Tag project (vanilla JS with X-Tag registered custom elements)
  • Node.js/Express backend for the health endpoint
  • A free Vigilmon account

Step 1: Add a Health Endpoint

X-Tag runs entirely in the browser, so add a /health route to your backend server:

// 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;
  }

  // Third-party API check
  try {
    const resp = await fetch("https://api.example.com/ping", {
      signal: AbortSignal.timeout(3000),
    });
    checks.externalApi = resp.ok ? "ok" : `http_${resp.status}`;
  } catch {
    checks.externalApi = "unreachable";
    degraded = true;
  }

  res.status(degraded ? 503 : 200).json({
    status: degraded ? "degraded" : "ok",
    timestamp: new Date().toISOString(),
    checks,
  });
});

app.listen(process.env.PORT ?? 3000, () => {
  console.log("Server running on port", process.env.PORT ?? 3000);
});

Test it:

curl http://localhost:3000/health | jq .
# {"status":"ok","timestamp":"2026-06-29T...","checks":{"database":"ok","externalApi":"ok"}}

Step 2: Configure Vigilmon HTTP Monitors

Log in to VigilmonMonitors → New Monitor:

Monitor 1: X-Tag Frontend App

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

Monitor 2: Health API

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

Both monitors together cover the static serving layer and the backend/data layer independently.


Step 3: Heartbeat for Background Tasks

Background jobs — webhook processing, data sync, cache warming — can fail silently for hours. A Vigilmon heartbeat alerts you 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 main job
  }
}

cron.schedule("*/10 * * * *", async () => {
  try {
    await syncCustomElementData();
    await pingHeartbeat();
  } catch (err) {
    console.error("[scheduler] Sync failed:", err);
    // Missing ping → Vigilmon fires an alert after the grace window
  }
});

async function syncCustomElementData() {
  // Your actual data sync or cache warming logic
}

Set up the heartbeat in Vigilmon:

  1. Monitors → New Heartbeat Monitor
  2. Set Expected interval to 20 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 with a Custom X-Tag Element

One of X-Tag's strengths is encapsulating behavior in reusable HTML elements. Create a <uptime-badge> custom element:

// uptime-badge.js
import XTag from "x-tag";

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

XTag.register("uptime-badge", {
  prototype: Object.create(HTMLElement.prototype),

  lifecycle: {
    created() {
      this.innerHTML = `
        <a
          href="${STATUS_URL}"
          target="_blank"
          rel="noopener noreferrer"
          aria-label="Service uptime status"
          style="display: inline-flex; align-items: center;"
        >
          <img
            id="uptime-img"
            src="${BADGE_URL}"
            alt="Uptime"
            width="120"
            height="20"
            style="opacity: 0; transition: opacity 0.2s;"
          />
        </a>
      `;
      this.querySelector("#uptime-img").addEventListener("load", () => {
        this.querySelector("#uptime-img").style.opacity = "1";
      });
    },
  },
});

Import and use in your HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>My X-Tag App</title>
  <script type="module" src="/x-tag.min.js"></script>
  <script type="module" src="/uptime-badge.js"></script>
</head>
<body>
  <main>
    <!-- your x-tag custom elements here -->
    <x-app></x-app>
  </main>
  <footer>
    <uptime-badge></uptime-badge>
  </footer>
</body>
</html>

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. Kill the scheduler → let heartbeat window expire
# Expected: heartbeat alert fires after the grace window

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

Summary

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


Next Steps

  • Create separate monitors for staging vs. production environments
  • Use Vigilmon's response time graphs to correlate backend latency with custom element rendering delays
  • 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 →