npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ai-gui/plugin-bigscreen

v0.40.0

Published

Animated data walls for AIGUI — counting KPIs, sweeping gauges, growing ranks, self-drawing charts, turning 3D bars and globes, on a grid the model lays out.

Readme

@ai-gui/plugin-bigscreen

Animated data walls for AIGUI: KPIs that count up, gauges that sweep, rank bars that grow, charts that draw themselves, and 3D bars and globes that turn — on a grid the model lays out.

Install

pnpm add @ai-gui/plugin-bigscreen echarts
# for the chart3d, globe and graph3d panels
pnpm add echarts-gl

echarts-gl is an optional peer: without it the chart3d, globe and graph3d panels show a one-line note and the rest of the wall is unaffected. It is imported lazily, once, the first time such a panel mounts.

Usage

import { bigscreen } from "@ai-gui/plugin-bigscreen"
import { buildSystemPrompt } from "@ai-gui/core"

<AIRenderer plugins={[bigscreen()]} />

const system = buildSystemPrompt({ registry, plugins: [bigscreen()], locale: "zh-CN" })

The model then emits:

```bigscreen
{
  "title": "华东区销售大屏",
  "subtitle": "2026 年 8 月",
  "panels": [
    { "kind": "kpi", "title": "本月营收", "value": 12843000, "prefix": "¥", "delta": 0.124, "trend": [8.1, 8.6, 9.2, 9.0, 10.4, 11.9, 12.8], "span": 3 },
    { "kind": "gauge", "title": "目标完成率", "value": 82, "unit": "%", "span": 3 },
    { "kind": "rank", "title": "门店排行", "span": 6, "unit": "万", "items": [{ "name": "上海", "value": 320 }, { "name": "杭州", "value": 245 }] },
    { "kind": "chart3d", "title": "品类 × 月份", "span": 6, "type": "bar3D", "xAxis": ["6月", "7月", "8月"], "yAxis": ["家电", "服饰"], "data": [[0, 0, 120], [1, 0, 150], [2, 0, 180], [0, 1, 90], [1, 1, 110], [2, 1, 140]] },
    { "kind": "globe", "title": "出口流向", "span": 6, "arcs": [{ "from": [121.47, 31.23], "to": [8.68, 50.11], "label": "上海→法兰克福" }, { "from": [121.47, 31.23], "to": [-74.01, 40.71], "label": "上海→纽约" }] }
  ]
}
```

Panels

| kind | what it draws | fields | | --- | --- | --- | | kpi | one number counted up from zero, a coloured delta, a sparkline | value, unit, prefix, decimals, delta (a fraction), upIsGood, trend, label | | gauge | a dial or a ring sweeping to the value; with thresholds, amber past the first and red past the second, for metrics where higher is worse | value, max, unit, style (dial / ring), thresholds | | rank | horizontal bars, longest first, growing in | items, unit, top | | chart | any ECharts option in the wall's palette, with entrance animation | option | | chart3d | bar3D, scatter3D, surface or line3D, slowly turning | type, data, xAxis, yAxis, rotate | | globe | a globe with arcing routes and sized points | arcs, points, rotate | | timeline | a swim-lane per source, a point per claim, lines between claims — contradicts in danger red | lanes, items, links, from, to | | graph3d | entities and typed edges, laid out by force-atlas2 on the GPU, coloured by type | nodes, edges, types, focus, rotate |

Every panel takes title, span (columns of the grid, default 4 of 12) and height. The screen takes title, subtitle, theme (dark by default, or light), accent (hex) and columns.

Clicks

A timeline claim with a url opens it in a new tab, opener cut off. A host that has its own idea of what a claim is takes the click instead, and a graph entity has no default at all:

bigscreen({
  events: {
    onItemClick: (item) => openClaim(item.id),
    onNodeClick: (node) => selectEntity(node.id),
  },
})

Why the protocol looks like this

Presentation, not evidence. @ai-gui/plugin-dashboard is the block for a BI board over real queries: the host writes every number and the model may only propose the layout. This block lets the model lay out numbers it was given — a summary, a demo, a briefing — and its prompt spec says, in the first paragraph, never to invent one. A wall of counting numbers looks like evidence, which is exactly why the rule is there.

Nothing fetched. ECharts' globe wants a texture and the usual one is a photograph loaded from a URL. Here the texture is painted on a canvas in the page and handed over as a data URL — a deep sphere with a graticule, the look a data wall's globe has anyway — so a fence can never make the page load anything.

One palette. Charts get the wall's colours, font, transparent background and animation laid under whatever the model wrote; the model's own settings win wherever they overlap. Series colours start from the accent, so a screen reads as one thing.

Unknown fields are refused. A model that wrote sparkline or refresh wanted something on the screen, and a panel quietly missing it is the wrong screen.

Options

  • maxPanels?: number — refuse a screen with more panels than this, default 24.
  • maxSourceBytes?: number — refuse a fence larger than this before parsing it, default 64 KiB.
  • animate?: booleanfalse draws every panel at its final state: no count-ups, no sweeps, no rotation. Default true.
  • theme?: "dark" | "light" — the host's palette; a theme in the fence wins. Absent both, the renderer's theme context decides, and dark is the fallback.

Charts are drawn on canvas (WebGL needs it, and the animations are smoother there) and follow their panel on resize. Everything is disposed on unmount.

Not in this version, and the prompt spec tells the model to fall back to plain charts or prose: live refresh, interactive filters, tables, choropleth maps, video.

See the root README for the full plugin list.