Asbir

Asbir Stats

Login

Documentation

What this is

Asbir Stats is a full-screen dashboard for displaying live numbers from any JSON API — built for TV/kiosk displays. Each dashboard polls its own endpoint on a schedule, caches the result on the server, and lays the stats out in a grid that fills the screen with no scrollbars.

Logging in

Every login uses a Dashboard Code and a Password, both verified on the server.

  • As a dashboard — enter the Code an admin set for that dashboard, along with its password (the admin password also works here, for any dashboard). You'll be taken straight to that dashboard, and only that one.
  • As admin — there's a reserved administrator login, entered the same way (Code + Password), that sees every dashboard and can create, edit, or delete any of them from Settings. Ask whoever set up this instance for the admin credentials.

Setting up a dashboard

From Settings (admin) or a dashboard's own kebab menu, you can configure:

  • Title — the display name shown on the dashboard.
  • Dashboard Code — the login identifier for this dashboard. Only an admin can set or change it; a dashboard's own session can view but not edit it.
  • Password — leave blank when creating a dashboard to fall back to the shared admin password. Editing a dashboard never shows its current password back to you — leave the field blank there to keep it unchanged.
  • API Endpoint — leave blank to preview with demo data.
  • Refresh Interval — how often the server re-fetches your API.
  • Font Size and Background Darkness — per-dashboard appearance.

API format

Your endpoint should return JSON in one of these shapes:

1. An array of stat objects

[
  {
    "label": "Daily Active Users",
    "value": 8412,
    "change": 18.4,
    "changeLabel": "vs yesterday"
  },
  {
    "label": "New Sign-ups",
    "value": 964,
    "change": -4.1,
    "changeLabel": "vs yesterday",
    "trend": [1080, 1050, 1020, 1005, 990, 980, 970, 964],
    "color": "#f59e0b"
  }
]

2. A wrapper object with a stats/data/metrics array

{
  "stats": [
    {
      "label": "Revenue",
      "value": 45230,
      "change": 12.5,
      "unit": "$",
      "changeLabel": "vs last month"
    }
  ]
}

This shape can also include a sibling meta.title, which overrides the dashboard's configured title for as long as this response is showing (falls back to the dashboard's own title if omitted, or if using the array or flat-object shapes above/below, which have no room for a sibling meta):

{
  "meta": { "title": "Q3 Sales" },
  "stats": [
    { "label": "Revenue", "value": 45230, "change": 12.5, "unit": "$" }
  ]
}

3. A flat object of label → number pairs

{ "Revenue": 45230, "Users": 8412 }

(Flat objects have no change value, so no arrow is shown for them.)

Stat fields

  • label (string, required)
  • value (number or string, required) — aliases: current, count, total
  • change (number, optional) — percentage vs. the previous period, shown with a green ↑ or red ↓. Aliases: delta, percentChange, diff. Omit it entirely for a stat that shouldn't show an arrow.
  • changeLabel (string, optional) — a label shown beside the change value, e.g. "vs yesterday". Only used when change is present. Aliases: compareLabel, vsLabel.
  • unit (string, optional) — e.g. $ or %. Everything except % is prefixed; % is suffixed.
  • meta (string, optional) — a secondary line shown under the value, used only when change is omitted.
  • trend (number[], optional) — a short history (oldest first) rendered as a soft area-chart background behind the card. Aliases: history, series. Omitted entirely if there's no history to show.
  • color (string, optional) — accent color (any CSS color) for that card's trend background. If omitted, cards cycle through a fixed palette by position.

Text / “leaderboard” stats

If value is a string instead of a number, it renders as a highlighted name rather than a big number with an arrow — useful for a "top title this week" style stat:

{ "label": "Top Title", "value": "The Last Voyage", "meta": "2,481 plays today" }

Refreshing & caching

  • Each dashboard's data is cached on the server for its configured Refresh Interval, so multiple viewers don't multiply calls to your API.
  • The kebab menu's Refresh button bypasses the cache for one immediate pull, then resumes the normal schedule.
  • If your endpoint is unreachable or returns something unrecognized, the dashboard falls back to demo data and shows an error note in the header.

Security note

This app uses a single shared admin password plus per-dashboard passwords, intended as simple access control for an internal/trusted display — not a hardened multi-tenant auth system. The admin password also works as a master password for logging into any individual dashboard directly.

Dashboard records (including passwords, in plaintext) are stored server-side — in a Vercel Blob store in production, or a local JSON file in development — rather than in a database with proper credential hashing.

← Back to Login