A personal API health dashboard that monitors your side project endpoints, tracks latency and response health, and alerts you when something breaks — with a public status page you can share with anyone.
Built in a weekend. Ships on Sunday.
- Add any URL and DevPulse starts pinging it on your schedule
- Records status code, latency, and payload size on every ping
- Three health states — Healthy, Degraded (slow but up), Down
- Session-based monitoring — you control when it runs, no wasted resources
- Per-endpoint ping intervals (1, 5, 15, 30 min)
- Incident tracking — opens on first failure, resolves on recovery
- Public
/status/[slug]page — shareable, no login required - Alert history with full incident timeline
- Project-based grouping for multiple side projects
| Layer | Tech |
|---|---|
| Framework | Next.js 16 (App Router) |
| Backend | Elysia.js (mounted inside Next.js) |
| Database | Neon Postgres (serverless) |
| ORM | Drizzle |
| API client | Eden Treaty (type-safe) |
| Data fetching | TanStack Query |
| UI | shadcn/ui + Tailwind |
| Runtime | Bun |
src/
├── app/
│ ├── (dashboard)/
│ │ ├── dashboard/page.tsx # main dashboard
│ │ ├── endpoints/
│ │ │ ├── new/page.tsx # add endpoint form
│ │ │ └── [id]/
│ │ │ ├── page.tsx # endpoint detail
│ │ │ └── edit/page.tsx # edit endpoint
│ │ ├── alerts/page.tsx # alert history
│ │ └── layout.tsx # sidebar layout
│ ├── status/[slug]/page.tsx # public status page
│ ├── api/
│ │ ├── [[...slugs]]/route.ts # elysia mount point
│ │ └── cleanup/route.ts # retention cron
│ └── page.tsx # landing page
├── server/
│ ├── routes/
│ │ ├── projects.ts
│ │ ├── endpoints.ts
│ │ ├── pings.ts
│ │ ├── sessions.ts
│ │ └── alerts.ts
│ └── worker/
│ ├── pinger.ts # core ping logic + incident handling
│ └── scheduler.ts # per-endpoint setTimeout scheduler
├── db/
│ ├── index.ts # drizzle client
│ └── schema.ts # all tables
├── components/
│ ├── dashboard/
│ │ ├── sidebar.tsx
│ │ ├── endpoints-table.tsx # react query live table
│ │ ├── endpoint-detail.tsx # react query live detail
│ │ ├── endpoint-actions.tsx # delete / pause / edit
│ │ ├── add-endpoint-form.tsx
│ │ ├── edit-endpoint-form.tsx
│ │ └── monitoring-session.tsx # start/stop session + countdown
│ └── providers.tsx # react query provider
└── lib/
├── client.ts # eden treaty client
├── queries.ts # react query hooks
└── utils
└── health.ts # getHealthState()
projects → id, name, slug, created_at
endpoints → id, project_id, name, url, interval_minutes,
degraded_ms, timeout_ms, alert_email,
is_active, last_checked_at, created_at
pings → id, endpoint_id, status_code, latency_ms,
payload_bytes, pinged_at
[index on (endpoint_id, pinged_at)]
incidents → id, endpoint_id, type, started_at, resolved_at
alert_logs → id, endpoint_id, incident_id, type, sent_at
monitoring_sessions → id, project_id, started_at, ends_at, stopped_at
git clone https://github.com/grimmy-dev/DevPulse
cd devpulse
bun installcp .example.env .env.localFill in .env.local:
DATABASE_URL=your_neon_connection_stringnpx drizzle-kit pushbun devDevPulse uses a session-based scheduler instead of an always-on cron.
- Pick a duration (15 min, 30 min, 1 hr, 2 hr) and hit Start monitoring
- DevPulse immediately pings all active endpoints in the project
- Each endpoint is re-pinged according to its own
intervalMinutesusingsetTimeoutchains - When the session expires (or you hit Stop) — all timers clear, no more pings
- Session state is persisted in Postgres — survives page reloads
This means zero resource usage when you're not actively monitoring. Intentional for free-tier hosting.
| State | Condition |
|---|---|
| Healthy 🟢 | Status < 500 and latency < degraded threshold |
| Degraded 🟡 | Status < 500 but latency > degraded threshold |
| Down 🔴 | Status >= 500 or timeout / network failure |
- Opens on first failed ping (down or degraded)
- Suppresses repeat alerts while incident is open
- Resolves when endpoint returns healthy
- Recovery is logged to
alert_logs
All routes are mounted under /api via Elysia.
GET /api/health
GET /api/projects
POST /api/projects
GET /api/projects/slug/:slug
DELETE /api/projects/:id
GET /api/endpoints?projectId=
POST /api/endpoints
GET /api/endpoints/summary?projectId=
GET /api/endpoints/:id/detail
PATCH /api/endpoints/:id
DELETE /api/endpoints/:id
GET /api/pings?endpointId=&limit=
GET /api/sessions/:projectId
POST /api/sessions
PATCH /api/sessions/:projectId/stop
GET /api/alerts?projectId=
Every project gets a public status page at:
/status/[project-slug]
No login required. Shows all endpoints, health state, last 10 ping sparklines, uptime over 30 days, and incident history. Safe to share with users or teammates.
- Email alerts via Resend (stubs already in place)
- Auth for multi-user support
- Latency charts over time
- Webhook alerts (Slack, Discord)
- Response body assertions
- SSL certificate expiry monitoring


