← back to gallery

Vibe Survival

Live survival tracker for vibe-coded apps on Lovable, v0, Bolt, Replit Agent.

dev-toolsvibe-codinglovablev0boltreplituptimesurvival-analysishacker-news
Open product ↗

vibe-survival

Live survival-rate tracker for vibe-coded apps shipped on Lovable, v0, Bolt.new, Replit Agent, a0.dev, Databutton, and Create.xyz. Discovers public apps from Hacker News, HEAD-checks each every 12 hours, exposes a dashboard.

What it does

  1. Every 30 minutes, queries the public Hacker News Algolia search API for each tracked platform's primary domain, paginates through results, normalizes each URL, and inserts any new app.
  2. Every 12 hours, sends a HEAD request (with a GET Range: bytes=0-0 fallback) to every tracked app. Logs the response code and elapsed time. Updates apps.current_alive and, on the first transition from alive → dead, sets apps.funeral_at.
  3. Exposes a vanilla-JS dashboard with: top-line counters, an interactive survival curve (Chart.js), a per-platform leaderboard with T+7 / T+30 / T+90 survival rates, a "recent funerals" feed, and a "long-livers" leaderboard.

Stack

Run locally

git clone <repo>
cd vibe-survival
cp .env.example .env
npm install
npm start
# open http://localhost:4801/vibe-survival/

Data sources (real, public, no auth)

| Name | URL | Fetch frequency | On failure |
|------------------|------------------------------------------------------------------------------------------|-----------------|---------------------------------------------|
| HN Algolia search | https://hn.algolia.com/api/v1/search?query=<domain>&restrictSearchableAttributes=url | every 30 min | per-platform error stored in run_log |
| App HEAD probe | direct HTTPS HEAD on each tracked app URL | every 12 h | row inserted in checks with error text |

Discovery domains used as HN search queries: lovable.app, v0.app, v0.dev, bolt.host, replit.app, replit.dev, a0.dev, databutton.com, create.xyz.

No mocks. No hardcoded survival numbers. No Math.random(). If discovery returns zero, the dashboard shows zero.

HTTP API (all public — no auth)

| Method | Path | Description |
|--------|-------------------------------------------------------------------|----------------------------------------------------------|
| GET | /vibe-survival/health | smoke check, always 200 |
| GET | /vibe-survival/api/stats | total / alive / dead counters + per-platform breakdown |
| GET | /vibe-survival/api/platforms | per-platform T+7 / T+30 / T+90 survival |
| GET | /vibe-survival/api/apps?platform=&status=alive\|dead&limit=&offset= | paginated app list |
| GET | /vibe-survival/api/app/:id | app detail + last 30 health-check rows |
| GET | /vibe-survival/api/funerals?limit=20 | most recent flips from alive → dead |
| GET | /vibe-survival/api/long-livers?limit=20 | oldest still-alive apps |
| GET | /vibe-survival/api/survival-curve?platform=&max_age=90 | survival-curve points for charts |
| GET | /vibe-survival/api/refresh-status | cron job state |
| POST | /vibe-survival/api/refresh?what=discover\|healthcheck\|both | kick a job async (returns 202) |

Survival math

For each age cut-off T (days), we compute alive_now / discovered_at_least_T_days_ago. This is a current-snapshot approximation — not a Kaplan–Meier estimator — but it's an honest summary of "of all apps we saw at least T days ago, what fraction is alive right now?" The methodology section in the UI explains this in plain language.

Architecture notes

Deploy

DEPLOY_MANIFEST.json is the RNDLAB orchestrator manifest. Drop the project into the RNDLAB watcher's source tree and the orchestrator will rsync → systemd → nginx → showcase → thumbnail it.

License

MIT