SolidJS is one of the fastest frontend frameworks available — fine-grained reactivity with near-zero runtime overhead. But that performance advantage disappears entirely the moment your app is down, your API is unreachable, or your background sync has been silently failing for 12 hours. 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 SolidJS backend (Node/Express or SolidStart)
- Vigilmon HTTP monitors for your SPA and backend
- A heartbeat for scheduled background tasks
- Alert channels (email and Slack)
- An uptime badge in your SolidJS UI
Prerequisites
- A SolidJS project (Vite + solid or SolidStart)
- Node.js backend for the health endpoint
- A free Vigilmon account
Step 1: Add a Health Endpoint
Option A: Plain Node/Express alongside a Vite SPA
If you're running SolidJS as a pure SPA with a separate Express API, add a /health route:
// server.js (Express)
import express from "express";
import { createClient } from "@libsql/client"; // or your DB driver
const app = express();
app.get("/health", async (req, res) => {
const checks = {};
let degraded = false;
// Database check
try {
const db = createClient({ url: process.env.DB_URL });
await db.execute("SELECT 1");
checks.database = "ok";
} catch (err) {
checks.database = `error: ${err.message}`;
degraded = true;
}
// Cache / Redis check
try {
// await redisClient.ping();
checks.cache = "ok";
} catch (err) {
checks.cache = `error: ${err.message}`;
degraded = true;
}
res.status(degraded ? 503 : 200).json({
status: degraded ? "degraded" : "ok",
timestamp: new Date().toISOString(),
checks,
});
});
app.listen(process.env.PORT ?? 3000);
Option B: SolidStart API Route
If you're using SolidStart, add a server function at src/routes/api/health.ts:
// src/routes/api/health.ts
import { json } from "@solidjs/router";
import type { APIEvent } from "@solidjs/start/server";
export async function GET(event: APIEvent) {
const checks: Record<string, string> = {};
let degraded = false;
try {
// Replace with your actual DB check
// await db.execute("SELECT 1");
checks.database = "ok";
} catch (err) {
checks.database = `error: ${(err as Error).message}`;
degraded = true;
}
try {
const res = await fetch("https://api.stripe.com/v1/", {
signal: AbortSignal.timeout(3000),
});
checks.stripe = res.status < 500 ? "ok" : `http_${res.status}`;
} catch {
checks.stripe = "unreachable";
}
return json(
{
status: degraded ? "degraded" : "ok",
timestamp: new Date().toISOString(),
checks,
},
{ status: degraded ? 503 : 200 }
);
}
Test it:
curl http://localhost:3000/api/health | jq .
# {"status":"ok","timestamp":"2026-06-29T...","checks":{"database":"ok","stripe":"ok"}}
Step 2: Configure Vigilmon HTTP Monitors
Log in to Vigilmon → Monitors → New Monitor:
Monitor 1: SolidJS SPA
| Field | Value |
|---|---|
| URL | https://yourapp.com/ |
| Method | GET |
| Expected status | 200 |
| Expected body | Any stable string from your HTML (e.g. app title) |
| Check interval | 1 minute |
Monitor 2: Health API
| Field | Value |
|---|---|
| URL | https://yourapp.com/api/health |
| Method | GET |
| Expected status | 200 |
| Check interval | 1 minute |
With both monitors, you cover two failure classes independently: the CDN/static serving layer and the backend/data layer.
Step 3: Heartbeat for Background Tasks
Background jobs — data sync, email digest, webhook ingestion — can fail silently for days without anyone noticing. 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("*/5 * * * *", async () => {
// Example: runs every 5 minutes
try {
await processWebhookQueue();
await pingHeartbeat();
} catch (err) {
console.error("[scheduler] Queue processing failed:", err);
// Vigilmon alerts after the heartbeat window expires with no ping
}
});
async function processWebhookQueue() {
// Your actual queue processing logic
}
Set up the heartbeat in Vigilmon:
- Monitors → New Heartbeat Monitor
- Set Expected interval to 10 minutes (2× the cron interval gives a generous 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 SolidJS UI
SolidJS's fine-grained reactivity makes it trivial to load external badge data without causing unnecessary re-renders.
// src/components/StatusBadge.tsx
import { createSignal, onMount } from "solid-js";
const BADGE_URL = "https://vigilmon.online/api/badge/your-monitor-id.svg";
const STATUS_URL = "https://vigilmon.online/status/your-monitor-slug";
export function StatusBadge() {
const [loaded, setLoaded] = createSignal(false);
return (
<a
href={STATUS_URL}
target="_blank"
rel="noopener noreferrer"
aria-label="Service uptime status"
class="inline-flex items-center"
>
<img
src={BADGE_URL}
alt="Uptime"
width={120}
height={20}
onLoad={() => setLoaded(true)}
style={{ opacity: loaded() ? 1 : 0, transition: "opacity 0.2s" }}
/>
</a>
);
}
Add it to your footer or nav:
// src/App.tsx
import { StatusBadge } from "./components/StatusBadge";
export default function App() {
return (
<div>
<main>{/* routes */}</main>
<footer class="footer">
<StatusBadge />
</footer>
</div>
);
}
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
curl -s https://yourapp.com/api/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
# 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 queue failures |
Next Steps
- Create separate monitors for staging vs. production
- Use Vigilmon's response time graphs to spot latency regressions correlated with SolidJS bundle size or API changes
- 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.