Solid Start is the official meta-framework for SolidJS — it brings file-based routing, server functions, streaming SSR, and edge deployment to the fastest reactive UI runtime available. But fine-grained reactivity and server rendering both fail silently when your database is gone, your deployment is broken, or your scheduled jobs have been crashing for hours. Vigilmon provides 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 route in your Solid Start app
- Vigilmon HTTP monitors for the SSR app and its health endpoint
- A heartbeat for scheduled background tasks
- Alert channels (email and Slack)
- An uptime badge in your Solid Start UI using SolidJS reactivity
Prerequisites
- A Solid Start project (
npm create solid@latest) - A deployment target (Node.js server, Vercel, Netlify, or Cloudflare)
- A free Vigilmon account
Step 1: Add a Health API Route
Solid Start supports API routes alongside page routes in the src/routes/ directory. Create a health endpoint:
// 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;
// Database check
try {
// Replace with your actual DB check, e.g. Prisma, Drizzle, libSQL
// await db.execute("SELECT 1");
checks.database = "ok";
} catch (err) {
checks.database = `error: ${(err as Error).message}`;
degraded = true;
}
// Third-party API reachability
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";
degraded = true;
}
// Cache / KV check (optional)
try {
// await redis.ping();
checks.cache = "ok";
} catch (err) {
checks.cache = `error: ${(err as Error).message}`;
degraded = true;
}
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-07-03T...","checks":{"database":"ok","stripe":"ok","cache":"ok"}}
Step 2: Configure Vigilmon HTTP Monitors
Log in to Vigilmon → Monitors → New Monitor:
Monitor 1: Solid Start App (SSR)
| Field | Value |
|---|---|
| URL | https://yourapp.com/ |
| Method | GET |
| Expected status | 200 |
| Expected body | A stable string from your rendered HTML (e.g. your page title) |
| Check interval | 1 minute |
Monitor 2: Health API Route
| Field | Value |
|---|---|
| URL | https://yourapp.com/api/health |
| Method | GET |
| Expected status | 200 |
| Check interval | 1 minute |
Separating these two monitors means a Node.js crash and a database failure each trigger distinct alerts — accurate attribution speeds up incident response.
Step 3: Heartbeat for Background Tasks
Solid Start's server functions handle real-time work, but periodic jobs — email digests, report generation, data syncs — are typically run separately. Use a Vigilmon heartbeat to catch silent failures:
// src/lib/scheduler.ts
import cron from "node-cron";
const HEARTBEAT_URL = process.env.VIGILMON_HEARTBEAT_URL ?? "";
async function pingHeartbeat(): Promise<void> {
if (!HEARTBEAT_URL) return;
try {
await fetch(HEARTBEAT_URL, { signal: AbortSignal.timeout(5000) });
} catch {
// Monitoring must never crash the job
}
}
cron.schedule("*/10 * * * *", async () => {
try {
await processNotificationQueue();
await pingHeartbeat(); // Only ping on success
} catch (err) {
console.error("[scheduler] Queue processing failed:", err);
// No heartbeat ping → Vigilmon alerts after the grace window
}
});
async function processNotificationQueue(): Promise<void> {
// Your actual queue logic here
}
Start the scheduler alongside your Solid Start server:
// src/entry-server.tsx (or a separate process in larger apps)
import "./lib/scheduler";
import { createHandler, renderAsync } from "@solidjs/start/server";
// ... rest of your entry-server setup
Set up the heartbeat in Vigilmon:
- Monitors → New Heartbeat Monitor
- Set Expected interval to
25 minutes(2.5× the cron interval for a generous grace window) - Add the ping URL to your
.env:
VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/xxxxxxxx
Step 4: Display an Uptime Badge in Your Solid Start App
SolidJS's fine-grained reactivity — createSignal, createResource — makes it trivial to load external status data without unnecessary re-renders:
// src/components/StatusBadge.tsx
import { createResource, Show } from "solid-js";
const BADGE_URL = "https://vigilmon.online/api/badge/your-monitor-id.svg";
const STATUS_PAGE = "https://vigilmon.online/status/your-monitor-slug";
function StatusBadge() {
// Use createResource to fetch live status without blocking SSR
const [status] = createResource(async () => {
const res = await fetch(`${STATUS_PAGE}.json`).catch(() => null);
return res?.ok ? res.json() : null;
});
return (
<a
href={STATUS_PAGE}
target="_blank"
rel="noopener noreferrer"
aria-label="Service uptime status"
class="inline-flex items-center gap-2"
>
<img src={BADGE_URL} alt="Uptime" width={120} height={20} />
<Show when={status()?.status}>
<span class={`status-indicator status-${status()!.status}`}>
{status()!.status}
</span>
</Show>
</a>
);
}
export default StatusBadge;
Add it to your root layout:
// src/routes/(layout).tsx
import { Outlet } from "@solidjs/router";
import StatusBadge from "~/components/StatusBadge";
export default function Layout() {
return (
<div>
<main>
<Outlet />
</main>
<footer class="site-footer">
<StatusBadge />
</footer>
</div>
);
}
Step 5: Set Up Alert Channels
In Vigilmon's Alert Channels settings:
- Alert Channels → Email → add your on-call address
- Attach the channel to both HTTP monitors and the heartbeat
Slack
- Create a Slack Incoming Webhook for
#alerts - Alert Channels → Webhook → paste the URL
- 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 health route
curl -s https://yourapp.com/api/health | jq .
# 2. Force a DB failure — disconnect the database, restart the server
# Expected: /api/health returns 503; Vigilmon alerts within 2 minutes
# 3. Deploy a broken build that crashes the SSR server
# Expected: Monitor 1 alerts; Monitor 2 may also alert if health route is affected
# 4. Stop the scheduler without pinging the heartbeat
# Expected: alert fires after the grace window
# 5. Vigilmon → "Test Alert" button → confirm delivery to email/Slack
Summary
| Monitor | What It Catches | |---|---| | HTTP SSR check | Node.js crashes, broken deployments, routing failures | | HTTP health API | Database, cache, and third-party API failures | | Heartbeat | Silent scheduler crashes, queue processing failures |
Next Steps
- Create separate Vigilmon monitors for staging vs. production environments
- Use response time graphs to detect SSR latency regressions correlated with data loading bottlenecks
- Monitor individual server function endpoints that are critical to your business logic
- Configure multi-channel alerting: email for warnings, Slack or PagerDuty for critical failures
Ready to get started? Sign up for Vigilmon free — have your first monitor running in under 5 minutes.