← back to gallery

Gen-Floor

Live $/image and $/second floor for generative-media APIs

aipricingimage-genvideo-genfal.aireplicateleaderboard
Open product ↗

gen-floor

Live $/image and $/second floor tracker for generative-media APIs. Token-floor for pixels and frames — cheapest model per category right now, biggest weekly movers, full price history per model. Real data only, no auth, no mocks.

Live: https://holyai.me/gen-floor/
Port: 4829
Base path: /gen-floor

---

What it does

gen-floor answers three questions for anyone shopping for generative-media inference:

  1. What's the cheapest provider right now for text-to-image / image-to-image / text-to-video / image-to-video?
  2. What dropped this week? Which models cut their per-image or per-second price in the last 7 / 14 / 30 days?
  3. How has a specific model's price moved? Every model has a full snapshot history with an inline sparkline.

The dashboard is dark-themed, framework-free vanilla JS, and entirely public (no login, no admin panel).

Data sources

Every price on the dashboard is pulled live from a public source. No seed data, no mocks, no random jitter. If a fetcher fails, the run is logged in the Fetch log tab and the dashboard shows "awaiting data" instead of filling in fakes.

| Source | Endpoint | Refresh | What we extract |
|------------------|-----------------------------------------------------------------------------------|-----------|-----------------|
| fal.ai | GET https://fal.ai/api/models?page=N&size=40 (paginated, ~34 pages, ~1,350 models) | every 15 min | id, title, category, modelLab, modelFamily, pricingInfoOverride markdown, and the URL/thumb/license metadata |
| Replicate | GET https://replicate.com/<owner>/<slug> for ~30 curated high-signal model slugs | every 60 min | Pricing parsed from the rendered HTML's natural-language phrases ("333 images for $1", "$0.40 per second", etc.) |

Curated Replicate slug list lives in fetchers/replicate-slugs.js — add or remove models freely; bad slugs 404 and the run logs them then carries on.

Normalization

Because providers price in different units, we normalize each snapshot to two comparable scalars:

These assumptions are documented in the in-app About tab and are intentionally honest about being approximations.

The Movers view ignores any model whose pricing unit changed between snapshots — a $0.05/sec → $5/video isn't a real "spike", it's a unit shift.

Stack

Local development

npm install
cp .env.example .env
npm start
# → http://localhost:4829/gen-floor/

The first fal.ai fetch fires ~5 seconds after boot and the first Replicate fetch ~25 seconds after boot, so the dashboard populates without manual intervention.

API

All endpoints are mounted under BASE_PATH=/gen-floor. None require auth.

| Method | Path | Returns |
|--------|--------------------------------------------|---------|
| GET | /gen-floor/health | { ok, models, last_fetch_at, last_fetch_iso, uptime_s } — 200 always |
| GET | /gen-floor/api/floors[?limit=N] | Cheapest N models per canonical category |
| GET | /gen-floor/api/models[?category=&source=&q=] | Latest snapshot per model, sortable / filterable |
| GET | /gen-floor/api/models/<id>/history[?limit=N] | Snapshot history for one model |
| GET | /gen-floor/api/movers[?days=7&limit=10] | Top-N drops + spikes over the last N days |
| GET | /gen-floor/api/categories | Per-category tracked counts + cheapest model |
| GET | /gen-floor/api/fetch-log[?limit=50] | Per-run audit log for cron health checks |

Schema

snapshots(
  id, source, model_id, model_title, model_family, model_lab,
  category, unit, price_usd,
  price_per_image_norm, price_per_second_norm,
  raw_pricing_text, meta_json, fetched_at
)

fetch_log(
id, source, started_at, finished_at, status,
models_seen, models_priced, error
)
```

Snapshots are append-only. A daily maintenance cron at 00:05 UTC prunes rows older than 90 days while always keeping the most-recent snapshot per model so the "latest" view never goes empty.

What's intentionally not here

License

UNLICENSED. Code is published for transparency, not redistribution.