@brad-frost-web/eddie-reporter
v0.42.0
Published
The Eddie-reporter — a zero-dependency usage reporter installed on downstream Eddie products. It statically scans a product for Eddie asset usage (components, recipes, pages, tokens) and reports the activity back to Eddie's Brain, so adoption and activity
Downloads
507
Readme
@brad-frost-web/eddie-reporter
The Eddie-reporter — a zero-dependency usage reporter you install on downstream Eddie products. It statically scans a product for Eddie asset usage (components, recipes, page templates, and design tokens) and reports that activity back to Eddie's Brain, so adoption and activity of the design system become a living, breathing feedback loop instead of a point-in-time guess.
Why this exists
Eddie's Brain already knows coverage (what the system offers) and, via the
adoption scanner, coarse adoption (which org repos declare an Eddie
dependency in package.json). What it couldn't see was activity: which
assets a product actually uses, how heavily, and when it last changed.
The reporter closes that gap. It turns "16 repos depend on Eddie" into "these
products use ed-card 240 times, nobody has touched ed-r-legacy-banner in 90
days, and ed-p-app-dashboard is the most-forked template this quarter." That
signal flows into .eddie-brain/activity.json and out through the
eddie_get_activity MCP tool.
Design principles
- Zero dependencies. Node built-ins only. It installs instantly and adds no supply-chain surface to the products it ships to.
- Static & read-only. It reads source text and counts references. It never executes the product, never reads runtime/user data, and never mutates the host. Reports are deterministic and privacy-friendly.
- Never breaks a build. A failed beacon is logged, not thrown. The CLI exits
0even when delivery fails. - Degrades gracefully. If there's no network (or you don't want telemetry), it writes a local artifact your CI can commit — the brain's org scan or a human can pick it up later.
Install & use
Run it with no install via npx:
npx @brad-frost-web/eddie-reporter --event build \
--endpoint https://ds.bradfrost.com/reportOr add it as a dev dependency and wire it into a build/postbuild script:
// package.json
{
"scripts": {
"postbuild": "eddie-report --event build"
}
}Set the endpoint once via env so scripts stay clean:
export EDDIE_REPORT_ENDPOINT="https://ds.bradfrost.com/report"
export EDDIE_REPORT_TOKEN="…" # optionalRun it on a schedule
The loop is designed to run unattended, on both ends:
- Product side. Copy
templates/eddie-report.ymlto your product's.github/workflows/and set theEDDIE_REPORT_ENDPOINTsecret. It beacons weekly (cron), on every push tomain/develop, and on demand. Products that deploy elsewhere can use a Netlify/Vercel scheduled function, apostbuild/postdeployhook, or a plain server cron. - System side. The hosted
POST /reportendpoint durably captures each beacon in a Netlify Blobs store (serverless filesystems are ephemeral). The schedulededdie-activityworkflow in eddie-design-system then flushes that store into.eddie-brain/activity.json(eddie-brain activity flush), refreshes adoption, and opens a PR — so the ledger stays live with zero manual steps.
CLI
eddie-report [dir] [options]
--endpoint <url> Brain ingestion URL (env: EDDIE_REPORT_ENDPOINT)
--token <token> Bearer token (env: EDDIE_REPORT_TOKEN)
--event <name> build | deploy | install | ci | dev | manual (default: manual)
--out <path> Local artifact path (default: .eddie/usage-report.json; '' to skip)
--dry-run Scan and print, but don't POST or write
--json Print the full report JSON to stdout
--quiet Suppress the human summaryProgrammatic API
import { buildReport, sendReport } from '@brad-frost-web/eddie-reporter';
const report = buildReport({ dir: process.cwd(), event: 'build' });
await sendReport(report, { endpoint: process.env.EDDIE_REPORT_ENDPOINT });What a report looks like
{
"schema": "eddie-usage-report/1",
"reporterVersion": "0.39.0",
"generatedAt": "2026-07-14T00:00:00.000Z",
"event": "build",
"product": {
"id": "bradfrost.com",
"repo": "Brad-Frost-Web/bradfrost.com",
"branch": "main",
"commit": "a1b2c3d…",
"environment": "ci"
},
"eddie": {
"declared": { "@brad-frost-web/eddie-web-components": "^0.37.0" },
"packages": ["design-tokens", "web-components"]
},
"usage": {
"components": { "ed-card": 24, "ed-button": 18 },
"recipes": { "ed-r-site-header": 1 },
"pages": { "ed-p-app-dashboard": 1 },
"tokens": { "--ed-theme-color-content-default": 63 },
"filesScanned": 210,
"filesMatched": 47
},
"totals": { "distinctComponents": 2, "distinctRecipes": 1, "distinctPages": 1, "distinctTokens": 1, "occurrences": 107 }
}The bigger picture
This reporter is the first leg of a two-way system↔product relationship. See
docs/VISION.md for the full map of where this goes —
usage-weighted health, deprecation radar, drift nudges, a public adoption
dashboard, and closing the loop back into governance.
