Etch.js is a small, JSX-compatible virtual DOM library purpose-built for building UI components in Atom editor packages and Electron applications. Its synchronous rendering model makes it reliable for editor tooling, but that reliability depends entirely on your backend services staying up. Vigilmon gives you the visibility you need: continuous HTTP monitoring, heartbeat checks, and instant alerts via email or Slack when something goes wrong.
What You'll Build
- A health API endpoint for your Etch.js backend or Electron app's companion server
- Vigilmon HTTP monitors for your app's web presence and health endpoint
- A heartbeat for scheduled background tasks (file watchers, sync jobs)
- Alert channels (email and Slack)
- An uptime status indicator in your Etch.js UI
Prerequisites
- An Etch.js project (Atom package or Electron app)
- Node.js backend or companion server for the health endpoint
- A free Vigilmon account
Step 1: Add a Health Endpoint
Etch.js renders UI in the browser/Electron renderer process. Health checks belong in your main process or companion HTTP server:
// main-server.js (Electron main process or standalone Node server)
const http = require("http");
const server = http.createServer(async (req, res) => {
if (req.url === "/health" && req.method === "GET") {
const checks = {};
let degraded = false;
// Check local file system or plugin state
try {
const fs = require("fs");
fs.accessSync(process.env.PLUGIN_DATA_DIR ?? ".", fs.constants.R_OK);
checks.filesystem = "ok";
} catch (err) {
checks.filesystem = `error: ${err.message}`;
degraded = true;
}
// Check remote API (e.g. language server)
try {
const resp = await fetch("http://localhost:2089/health", {
signal: AbortSignal.timeout(2000),
});
checks.languageServer = resp.ok ? "ok" : `http_${resp.status}`;
} catch {
checks.languageServer = "unreachable";
// Not critical for all users — leave degraded = false here
}
const body = JSON.stringify({
status: degraded ? "degraded" : "ok",
timestamp: new Date().toISOString(),
checks,
});
res.writeHead(degraded ? 503 : 200, {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(body),
});
res.end(body);
} else {
res.writeHead(404);
res.end();
}
});
server.listen(process.env.HEALTH_PORT ?? 9090, () => {
console.log("Health server on port", process.env.HEALTH_PORT ?? 9090);
});
Test it:
curl http://localhost:9090/health | jq .
# {"status":"ok","timestamp":"2026-06-29T...","checks":{"filesystem":"ok","languageServer":"ok"}}
Step 2: Configure Vigilmon HTTP Monitors
Log in to Vigilmon → Monitors → New Monitor:
Monitor 1: App Web Presence (if applicable)
| Field | Value |
|---|---|
| URL | https://yourapp.com/ |
| Method | GET |
| Expected status | 200 |
| Expected body | Stable string from your landing page |
| Check interval | 1 minute |
Monitor 2: Health API
| Field | Value |
|---|---|
| URL | https://yourapp.com/health or http://your-vps:9090/health |
| Method | GET |
| Expected status | 200 |
| Check interval | 1 minute |
Step 3: Heartbeat for Background Tasks
Etch.js–backed tools often run file watchers, background indexers, or sync tasks. A Vigilmon heartbeat catches silent failures:
// background-tasks.js
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 {
// Never crash the background task due to monitoring failure
}
}
async function runIndexer() {
// Your file indexing / background sync logic
console.log("Running background indexer...");
}
// Run every 15 minutes
setInterval(async () => {
try {
await runIndexer();
await pingHeartbeat();
} catch (err) {
console.error("[background] Indexer failed:", err);
// No ping → Vigilmon alert fires after grace window
}
}, 15 * 60 * 1000);
Set up the heartbeat in Vigilmon:
- Monitors → New Heartbeat Monitor
- Set Expected interval to 30 minutes
- Copy the ping URL to your
.envor plugin settings:
VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/xxxxxxxx
Step 4: Display Uptime Status in Your Etch.js UI
Etch.js components use a synchronous render() method and update() for state changes:
/** @jsx etch.dom */
const etch = require("etch");
const BADGE_URL = "https://vigilmon.online/api/badge/your-monitor-id.svg";
const STATUS_URL = "https://vigilmon.online/status/your-monitor-slug";
class StatusBadgeComponent {
constructor() {
this.loaded = false;
etch.initialize(this);
}
render() {
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"
on={{ load: () => this.markLoaded() }}
style={`opacity: ${this.loaded ? 1 : 0}; transition: opacity 0.2s;`}
/>
</a>
);
}
markLoaded() {
this.loaded = true;
etch.update(this);
}
async update() {
await etch.update(this);
}
async destroy() {
await etch.destroy(this);
}
}
module.exports = StatusBadgeComponent;
Use it inside an Atom panel or Electron view:
const StatusBadgeComponent = require("./status-badge-component");
// In your package activate() or Electron window
const badge = new StatusBadgeComponent();
document.querySelector("#footer").appendChild(badge.element);
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 http://localhost:9090/health | jq .
# 2. Simulate filesystem inaccessible → confirm health returns 503
# Expected: Vigilmon alerts within 2 minutes
# 3. Stop the background task → 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 | Landing page or download server failures | | HTTP health API | Filesystem, language server, and dependency failures | | Heartbeat | Background indexer crashes, silent sync failures |
Next Steps
- Create separate monitors for dev and production companion servers
- Use Vigilmon's response time graphs to detect slow indexer runtimes
- 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.