heartbeat
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data β all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v16View latest version
A serverless monitoring solution for your home server with real-time push notifications.
- Web UI: https://halffullheartbeat.val.run
- Heartbeat Endpoint:
POST https://halffullheartbeat.val.run/heartbeat
- Go to https://www.val.town/v/halffullheart/heartbeat/generate-vapid-keys
- Click "Run" to generate your VAPID keys
- Copy the keys from the output
- Go to your val settings: https://www.val.town/v/halffullheart/heartbeat
- Click "Environment Variables"
- Add these three variables:
VAPID_PUBLIC_KEY- from step 1VAPID_PRIVATE_KEY- from step 1VAPID_EMAIL- your email (e.g.,mailto:you@example.com)
Add a cron job or scheduled task on your home server to ping the heartbeat endpoint every 15 minutes:
Linux/Mac (crontab):
# Add to crontab (run: crontab -e) */15 * * * * curl -X POST https://halffullheartbeat.val.run/heartbeat
Windows (Task Scheduler PowerShell):
# Run every 15 minutes $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-Command "Invoke-WebRequest -Uri https://halffullheartbeat.val.run/heartbeat -Method POST"' $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 15) Register-ScheduledTask -TaskName "ServerHeartbeat" -Action $action -Trigger $trigger
Docker (if your server runs Docker):
# Run this container on your server docker run -d --name heartbeat --restart unless-stopped \ alpine/curl:latest sh -c \ "while true; do curl -X POST https://halffullheartbeat.val.run/heartbeat; sleep 900; done"
Simple Bash Script:
#!/bin/bash # Save as heartbeat.sh and run: ./heartbeat.sh & while true; do curl -X POST https://halffullheartbeat.val.run/heartbeat sleep 900 # 15 minutes done
- Open the web UI: https://halffullheartbeat.val.run
- Click "Enable Notifications"
- Grant notification permissions when prompted
- Your Server: Sends a heartbeat every 15 minutes to the
/heartbeatendpoint - Monitor: Checks every 15 minutes if a heartbeat was received in the last hour
- Notifications: If no heartbeat for 1+ hour, sends push notifications to all subscribers
- Web UI: Real-time status display that updates every 30 seconds
Your server calls this endpoint every 15 minutes.
Response:
{ "success": true, "timestamp": 1234567890 }
Get current server status.
Response:
{ "lastHeartbeat": 1234567890, "isOnline": true, "minutesSince": 5, "currentTime": 1234567890 }
Subscribe to push notifications (called automatically by web UI).
- main.ts: HTTP endpoint with web UI (PWA)
- monitor.ts: Interval function (runs every 15 minutes)
- SQLite Database: Stores heartbeats and notification subscriptions
- Web Push: VAPID-based push notifications
heartbeats table:
id- Auto-increment primary keytimestamp- Unix timestamp in milliseconds
subscriptions table:
id- Auto-increment primary keyendpoint- Push notification endpoint (unique)p256dh- Public key for encryptionauth- Authentication secretcreated_at- Subscription timestamp
- β Real-time server status monitoring
- β PWA (Progressive Web App) installable on mobile
- β Push notifications when server goes down
- β Beautiful, responsive UI
- β Automatic cleanup of invalid subscriptions
- β CORS-enabled API
- β Service Worker for offline support
- Environment variables for sensitive keys
- VAPID keys for authenticated push notifications
- CORS headers for API access
- Unique subscription endpoints per device
- Server is considered "down" after 1 hour without heartbeat
- Monitor runs every 15 minutes (configurable in monitor.ts)
- Notifications sent to all active subscribers
- Invalid subscriptions automatically removed
- SQLite database scoped to this val
No notifications?
- Check that VAPID environment variables are set
- Ensure you granted notification permissions
- Check monitor.ts logs for errors
Server showing offline?
- Verify your server's cron job is running
- Check that the heartbeat endpoint is reachable
- Look at the heartbeat timestamps in the database
Test the heartbeat:
curl -X POST https://halffullheartbeat.val.run/heartbeat
For issues or questions, check the Val Town documentation: https://docs.val.town