pnpm install
pnpm run build:packagesThe library talks to the GitHub API through the tokens its caller passes in, so anything that actually fetches needs a Personal Access Token of your own — the tests do not, they run against recorded responses.
pnpm run test # unit tests
pnpm run lint # oxlint
pnpm run typecheck # tsc
pnpm check-all # every check CI runs, cheapest failure firstcheck-all is the one to reach for before opening a pull request:
it runs the list above and the rest of CI in one command, stopping at the first failure.
Card tests assert on the rendered DOM rather than on snapshots, with one snapshot suite for the WakaTime card. If a change to that card's markup was intentional, update it:
pnpm --filter ./packages/core/ run test:update:snapshotpnpm server:standalone # the cards alone, against the root .env, restarting on every edit
pnpm server:hosted # build the documentation site as the image does, then serve it tooBoth read PAT_1 from a .env at the repository root; without it every card but WakaTime draws the no_tokens error.
The hosted one serves the built site as a snapshot, so an edit to a page or to the anvil needs the command run again.
pnpm run docs # the site's dev server — the `run` is required, `pnpm docs` is a pnpm builtin
pnpm docs:cards # redraw the card previews the pages showThe previews are committed, so redraw them when a card's output changes.
That needs PAT_1 in the root .env, which is why CI cannot keep them current.
The GraphQL queries live in packages/core/src/graphql/queries/*.graphql,
and their TypeScript types are generated from GitHub's published schema into packages/core/src/graphql/generated/.
Those generated files are committed, so if you change a query,
regenerate them and include the result in your PR:
pnpm --filter ./packages/core/ run generate-graphql-typesCI runs pnpm --filter ./packages/core/ run check-graphql-types,
which fails if the committed types no longer match the queries.
Never edit the generated files by hand — change the .graphql file and regenerate.
pnpm install installs a lefthook pre-commit hook that formats, lints and tests.
A workflow that commits sets LEFTHOOK: 0 to skip it:
the lint needs the types astro sync writes into apps/docs/.astro, which a fresh checkout has not.
The pull request it opens runs the full CI anyway.
We have stopped the addition of new themes to decrease maintenance efforts. If you are considering contributing your theme just because you are using it personally, then instead of adding it to our theme collection, you can use the card customization options.
GitHub Stats Forge supports multiple languages. If we are missing your language, you can contribute it!
Each card owns its wordings in the locales.ts beside its renderer —
cards/stats/locales.ts and so on,
with common/locales.ts for the few more than one card draws.
Add your language code to each key, using the code listed in AVAILABLE_LOCALES
in common/localize.ts:
title: {
en: `{name}'{apostrophe} GitHub Stats`,
it: `Statistiche GitHub di {name}`,
},A table doesn't need to be complete — a missing wording falls back to en,
so translating one key is still worth a pull request.
Keep the {name} placeholders: you may use fewer than en does,
but never one it does not supply.
A wording that depends on a number is written as plural forms instead:
{ one: '{count} repository', other: '{count} repositories' }and Intl.PluralRules picks the form for your language.
pnpm run test checks all of that.
In short, when you submit changes, your submissions are understood to be under the same MIT License that covers the project. Feel free to contact the maintainers if that's a concern.
We use GitHub issues to track public bugs. Report a bug by opening a new issue.
Great Feature Requests tend to have:
- A quick idea summary
- What & why do you want to add the specific feature
- Additional context like images, links to resources to implement the feature, etc.