Lightweight, open-source Uptime & SSL Monitor
A beautiful, dark-themed status page and uptime monitor — zero database, instant deploy.
| Feature | Serverless (Vercel) | Self-Hosted (Docker) |
|---|---|---|
| Real-time uptime monitoring | ✅ | ✅ |
| SSL certificate expiry tracking | ✅ | ✅ |
| Response-time sparkline graphs | ✅ | ✅ |
| Live green/yellow/red dot indicators | ✅ | ✅ |
| Auto-polls every 30 seconds | ✅ | ✅ |
| Zero external database | ✅ | ✅ |
| Config via a single JSON file | ✅ | ✅ |
| Dark-themed Vercel-style UI | ✅ | ✅ |
| One-click deploy | ✅ | — |
| Persistent history across restarts | — | ✅ (via volume) |
PingFlow reads its monitor list from pingflow.config.json, which lives inside the repo. No database setup is required — just fork and deploy.
-
Fork this repository on GitHub (click the Fork button, top-right).
-
Click the button below to deploy your fork to Vercel:
Replace
YOUR_USERNAMEwith your GitHub username after forking. -
Vercel will build and deploy in ~60 seconds. Your status page is live! 🎉
-
To add your own sites, edit
pingflow.config.jsonin your forked repo and push — Vercel auto-redeploys.
{
"monitors": [
{
"id": "my-app",
"name": "My App",
"url": "https://myapp.com",
"expectedStatus": 200
},
{
"id": "my-api",
"name": "My API",
"url": "https://api.myapp.com/health",
"expectedStatus": 200
}
]
}| Field | Type | Description |
|---|---|---|
id |
string |
Unique identifier (no spaces) |
name |
string |
Display name shown on the status page |
url |
string |
Full URL to monitor (http or https) |
expectedStatus |
number |
Expected HTTP status code (usually 200) |
This section is written for people who have never used Docker before. Follow every step in order.
Docker Desktop is a free app that lets you run containers on your computer.
-
Click "Download Docker Desktop" for your operating system (Windows / Mac / Linux).
-
Run the installer and follow the prompts (keep all defaults).
-
Once installed, open Docker Desktop from your Start Menu / Applications folder.
-
Wait until you see the green "Engine running" status in the bottom-left corner of the Docker Desktop window.
✅ Docker is ready when the whale icon in your system tray is steady (not animating).
Git lets you download ("clone") the PingFlow code.
- Go to https://git-scm.com/downloads
- Download and install Git for your OS (keep all defaults).
- Verify it worked: open a terminal and run:
git --version # Should print something like: git version 2.x.x
Open a terminal (PowerShell on Windows, Terminal on Mac/Linux) and run:
git clone https://github.com/YOUR_USERNAME/pingflow.git
cd pingflowReplace
YOUR_USERNAMEwith the GitHub username where the repo lives.
You should now be inside the pingflow folder.
Open pingflow.config.json in any text editor (Notepad works fine) and add your own URLs:
{
"monitors": [
{
"id": "my-site",
"name": "My Website",
"url": "https://example.com",
"expectedStatus": 200
}
]
}Save the file when done.
In your terminal (make sure you're still inside the pingflow folder), run:
docker compose up -dThat's it. Docker will:
- Download the Node.js base image (~50 MB, one time only)
- Install dependencies and build the app (~2 minutes first time)
- Start the server in the background
Open your browser and go to:
http://localhost:3000
You should see the PingFlow dark-themed status dashboard with all your monitors! 🎉
docker compose downBecause pingflow.config.json is bind-mounted into the container, you can edit it and just restart — no rebuild required:
# 1. Edit pingflow.config.json (add/remove monitors)
# 2. Restart the container to pick up changes:
docker compose restartIf you pull new changes from GitHub:
git pull
docker compose up -d --buildIf you're a developer and want to run the app locally:
- Node.js 20+
- npm 9+
# Install dependencies
npm install
# Start the development server
npm run devOpen http://localhost:3000.
The dev server hot-reloads on every file save. Edit pingflow.config.json and refresh to see changes instantly.
pingflow/
├── app/
│ ├── api/status/route.ts # GET /api/status — pings all monitors
│ ├── layout.tsx # Root layout (dark theme, metadata)
│ └── page.tsx # Status page (polls API every 30s)
├── components/
│ ├── HeaderBanner.tsx # Overall status hero banner
│ ├── MonitorCard.tsx # Per-monitor card
│ └── ui/
│ ├── StatusDot.tsx # Animated dot indicator
│ ├── StatusBadge.tsx # Pill badge (Operational / Degraded / Down)
│ ├── ResponseBars.tsx # Sparkline bar chart
│ └── SslBadge.tsx # SSL expiry badge
├── lib/
│ └── ping.ts # Core ping logic (fetch + TLS cert check)
├── types/
│ └── index.ts # Shared TypeScript types
├── pingflow.config.json # ← Edit this to add your monitors
├── Dockerfile # Multi-stage production Docker image
└── docker-compose.yml # One-command self-hosting
Browser → GET / → Next.js renders status page
↓ (every 30s)
Browser → GET /api/status
↓
reads pingflow.config.json
↓
Promise.all([ping(google), ping(github), ping(vercel)])
↓
returns JSON { overall, monitors[], checkedAt }
↓
Browser updates UI (dots, bars, badges)
- No database. History lives in the browser's React state — 30 data points per monitor (last 15 minutes at the default 30s interval).
- SSL checks use Node.js's built-in TLS stack — no third-party certs needed.
- Timeouts are enforced at 10 seconds via
AbortController— a hung monitor never blocks the others.
MIT © PingFlow contributors. Use it, fork it, ship it.