tutorial

How to Monitor Capri with Vigilmon

Add production-grade uptime monitoring to a Capri static site — health checks, heartbeat monitors for build pipelines and background tasks, and instant alerts when your islands-architecture site goes down.

Capri is a static site generator built around the islands architecture — it renders pages to pure HTML at build time and hydrates only the interactive "islands" in the browser, giving you the speed of static HTML with the richness of a component framework. But a fast site doesn't protect you from CDN outages, broken build pipelines, or API dependencies that go silent overnight. Vigilmon fills that gap: continuous HTTP monitoring, heartbeat checks, and instant alerts delivered to email or Slack.

What You'll Build

  • HTTP monitors for your Capri-generated static site
  • A health endpoint for any server-side functions or API proxies
  • A heartbeat for your build and deploy pipeline
  • Alert channels (email and Slack)
  • A status badge embedded as a Capri island

Prerequisites

  • A Capri site (supporting React, Preact, Vue, Svelte, or Solid islands)
  • Hosting on a static CDN (Netlify, Vercel, Cloudflare Pages, or similar)
  • A free Vigilmon account

Step 1: Monitor Your Static Site

Capri's primary output is static HTML deployed to a CDN. Configure a Vigilmon HTTP monitor to verify the site is reachable and the CDN is serving correctly:

Log in to VigilmonMonitors → New Monitor:

Monitor 1: Static Site Root

| Field | Value | |---|---| | URL | https://yoursite.com/ | | Method | GET | | Expected status | 200 | | Expected body | A stable string from your generated HTML (e.g. your site title) | | Check interval | 1 minute |

Monitor 2: Critical Content Page

Monitor a page that depends on your most important content pipeline:

| Field | Value | |---|---| | URL | https://yoursite.com/blog/ | | Method | GET | | Expected status | 200 | | Expected body | A stable heading or string from the page | | Check interval | 5 minutes |


Step 2: Add a Health Endpoint for Server Functions

If your Capri site uses a backend API, server-side rendering for specific routes, or an API proxy (common with Netlify Functions or Vercel Functions), add a health endpoint:

// netlify/functions/health.js  (Netlify Functions example)
export const handler = async () => {
  const checks = {};
  let degraded = false;

  // CMS / data source check
  try {
    const res = await fetch("https://your-cms.io/api/health", {
      signal: AbortSignal.timeout(3000),
    });
    checks.cms = res.ok ? "ok" : `http_${res.status}`;
    if (!res.ok) degraded = true;
  } catch {
    checks.cms = "unreachable";
    degraded = true;
  }

  // Database check (if applicable)
  try {
    // await db.query("SELECT 1");
    checks.database = "ok";
  } catch (err) {
    checks.database = `error: ${err.message}`;
    degraded = true;
  }

  return {
    statusCode: degraded ? 503 : 200,
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      status: degraded ? "degraded" : "ok",
      timestamp: new Date().toISOString(),
      checks,
    }),
  };
};

Add a Vigilmon monitor for it:

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


Step 3: Heartbeat for Your Build Pipeline

Capri sites are built and deployed by a CI/CD pipeline. A failed build that nobody notices means your users see stale or broken content. A Vigilmon heartbeat detects this automatically:

GitHub Actions example

# .github/workflows/deploy.yml
name: Build & Deploy

on:
  push:
    branches: [main]
  schedule:
    - cron: "0 2 * * *"  # Nightly rebuild for fresh content

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Build Capri site
        run: npm run build

      - name: Deploy to Netlify
        run: npx netlify-cli deploy --prod --dir=dist
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

      - name: Ping Vigilmon heartbeat
        if: success()
        run: curl -s "${{ secrets.VIGILMON_HEARTBEAT_URL }}" > /dev/null

Set up the heartbeat in Vigilmon:

  1. Monitors → New Heartbeat Monitor
  2. Set Expected interval to 25 hours (covers both scheduled nightly builds and ad-hoc deploys)
  3. Add the ping URL to your repo secrets as VIGILMON_HEARTBEAT_URL

Step 4: Status Badge as a Capri Island

Capri's island architecture is perfect for a live status badge — it's interactive (fetches live data) but lightweight. Here's an example using a React island:

// src/islands/StatusBadge.tsx  (React island)
import { useState, useEffect } from "react";

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

export default function StatusBadge() {
  const [visible, setVisible] = useState(false);

  useEffect(() => setVisible(true), []);

  return (
    <a
      href={STATUS_URL}
      target="_blank"
      rel="noopener noreferrer"
      aria-label="Service uptime status"
      style={{ display: "inline-flex", alignItems: "center" }}
    >
      <img
        src={BADGE_URL}
        alt="Uptime"
        width={120}
        height={20}
        style={{ opacity: visible ? 1 : 0, transition: "opacity 0.2s" }}
      />
    </a>
  );
}

Include it in a Capri page:

// src/pages/index.tsx
import StatusBadge from "../islands/StatusBadge";

export default function Home() {
  return (
    <main>
      <h1>My Capri Site</h1>
      {/* Static content — rendered at build time */}
      <p>Fast, static, and always up to date.</p>

      {/* Island — hydrated in the browser */}
      <footer>
        <StatusBadge client:load />
      </footer>
    </main>
  );
}

The client:load directive tells Capri to hydrate StatusBadge immediately after the page loads, while the rest of the page stays as static HTML.


Step 5: Set Up Alert Channels

In Vigilmon's Alert Channels settings:

Email

  1. Alert Channels → Email → add your on-call address
  2. Attach it to all monitors and the heartbeat

Slack

  1. Create a Slack Incoming Webhook for #alerts
  2. Alert Channels → Webhook → paste the URL
  3. Use this payload template:
{
  "text": "🚨 *{{ monitor.name }}* is DOWN\n{{ monitor.url }}\nStatus: {{ event.status }}\n<https://vigilmon.online|Open Vigilmon>"
}

Step 6: Verify the Setup

# 1. Confirm static site returns 200
curl -s -o /dev/null -w "%{http_code}" https://yoursite.com/

# 2. Confirm health function (if applicable)
curl -s https://yoursite.com/.netlify/functions/health | jq .

# 3. Force a CMS connectivity failure in the health function
# Expected: returns 503; Vigilmon alerts within 2 minutes

# 4. Block the build pipeline without pinging the heartbeat
# Expected: heartbeat alert fires after the grace window

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

Summary

| Monitor | What It Catches | |---|---| | HTTP root check | CDN outages, broken deployments, certificate failures | | HTTP health function | CMS, database, and third-party API failures | | Heartbeat | Failed builds, broken deploy pipelines |


Next Steps

  • Add monitors for each critical page that relies on different content sources
  • Use Vigilmon's response time graphs to detect CDN latency regressions after island hydration
  • Configure multi-channel alerting: email for warnings, Slack for critical failures

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 →