Skip to content

The library

Terminal window
npm install @stats-forge/github-stats-forge-core
import { CardConfig, stats } from '@stats-forge/github-stats-forge-core/api';
const config = new CardConfig({
pats: [{ name: 'PAT_1', value: process.env.PAT_1 }],
});
const result = await stats({ username: 'octocat', show_icons: 'true' }, config);

A handler takes the query params its card accepts — as strings, the way a query string carries them — and the configuration for the deployment. The handlers are stats, topLangs, pin, contributedTo, gist, org, orgActivity and wakatime.

Nothing in the library reads process.env. The host builds the configuration and passes it in, which is what lets the same code run in an action, on a server and in a browser.

The GitHub Stats Forge action is these handlers and a step that writes the file; reach for the library where the action cannot go.

if (result.status === 'success') {
// result.content is the card, as SVG
} else {
// result.content is the failure, drawn as a card
// result.error.code is why it failed
// result.error.param is the parameter at fault, when it names one
// result.retryable is whether trying again could help
}

Both branches carry a content you can serve: a failure is still an image, so a README shows the reason rather than a broken picture.

CodeWhat happenedRetryable
forbiddenThe token may not read a stat the query asked foryes
invalid_paramA parameter is malformed or not renderableno
missing_paramA parameter the card cannot render withoutno
not_allowedThe deployment does not serve that account or gistno
not_foundThe user, repository or gist does not existno
no_tokensThe deployment has no usable GitHub tokenyes
rate_limitedEvery token is rate limitedyes
upstreamGitHub or WakaTime failed to answer usablyyes

Branch on the code, never the message, and on retryable to choose between caching the failure and trying again. Troubleshooting has what each card reads.

const config = new CardConfig({
pats: [{ name: 'PAT_1', value: process.env.PAT_1 }],
usernameAllowlist: ['octocat'],
excludeRepositories: ['octocat/scratch'],
fetchMultiPageStars: 1,
fetch: myFetch,
requestTimeoutMs: 10_000,
});
FieldWhat it is
patsThe tokens to spend, each with the name of the variable it came from
usernameAllowlistThe GitHub logins this deployment draws, case-insensitively; omit for any
gistAllowlistThe same, for gist ids
excludeRepositoriesRepositories left out of every card
fetchMultiPageStarsHow many pages of starred repositories to read; Infinity for all
fetchThe transport every request goes through — swap it to cache, mock or proxy
requestTimeoutMsHow long one request may wait before it fails as upstream; omit to wait

CardConfig.fromEnv(process.env) builds the same thing from PAT_1…, ALLOWLIST, GIST_ALLOWLIST, EXCLUDE_REPO and FETCH_MULTI_PAGE_STARS, for a host that would rather configure through the environment. A PAT_ variable set to nothing is skipped.

A configuration is immutable. config.with({ pats }) returns a copy, which is how a host swaps in a token belonging to the request rather than to the deployment.

The handlers check an allowlist before fetching anything, so an identity the deployment does not serve fails as not_allowed and spends no rate limit. It covers username, the organization cards’ org and the gist card’s id, but not the WakaTime card, whose username is a WakaTime profile. Calling a render function directly skips the check.

Terminal window
npm install @stats-forge/github-stats-forge-catalog
import { findCard } from '@stats-forge/github-stats-forge-catalog';
const card = findCard('stats');
for (const option of card.options) {
// option.name is the query param, option.label what to call it,
// option.kind which control to draw, option.choices what it accepts
}

Anything offering those params to somebody — a form, a generator, an editor — needs each one’s name and accepted values. The catalog holds them, read off the handlers’ own OPTIONS (topLangs.OPTIONS.layout is what ?layout= accepts), so it cannot offer a value the api would reject. The CLI’s prompts and this site’s card builder are both forms over it.

card.render is the handler, so a form can draw what it is building; card.needsToken says whether that costs a GitHub token.

ImportWhat it holds
@stats-forge/github-stats-forge-core/apiThe card handlers, CardConfig, ApiResult
@stats-forge/github-stats-forge-core/fetchersThe GitHub and WakaTime fetchers on their own
@stats-forge/github-stats-forge-core/themesThe theme table