Adds `disable_animations` to the gist card so it matches the stats,
top-languages, repo and wakatime cards.
## Changes
- `packages/core/src/cards/gist.ts`: new `disable_animations` option
(default `false`). When it is `true`, `card.disableAnimations()` is
called. The default output stays the same, with the title fade-in still
animated.
- `packages/core/src/api/gist.ts`: reads the query param and passes it
through `parseBoolean`.
- Wizard (`buildCardUrl.ts`): appends `disable_animations=true` for the
gist card when "Enable Animations?" is unchecked. `Customize.tsx` now
shows that checkbox for the gist card. All five card types now support
it, so I removed the card-type condition around the checkbox. Keeping it
would have tripped `@typescript-eslint/no-unnecessary-condition`.
- Docs: added `disable_animations` to the options table in
`gist-pin.md`.
## Tests
- `renderGistCard.test.ts`: by default the blanket `animation-duration:
0s` rule is absent, and `disable_animations: true` adds it.
- `buildCardUrl.test.ts`: the gist URL gets `disable_animations=true`
when animations are turned off.
- `gist.test.js` (backend contract): added `disable_animations: "true"`
to the many-params snapshot request. The only snapshot change is the
added rule.
- `xss.test.js`: added `disable_animations` to the gist API param list.
## Verified locally (Node 24)
- New tests before the fix: 2 failing (render + wizard URL). After the
fix, all pass.
- `pnpm run test`: 40 files, 766 tests passed
- `pnpm run lint`: ok
- `pnpm run typecheck`: ok
- `prettier --check` on the changed files: ok
Closes#614
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
Adds `disable_animations` to the repo (pin) card, so it behaves like the
stats, top-languages and wakatime cards.
## One thing worth a maintainer's eye
The issue says the title animation is on today and that
`disable_animations=false` should preserve current behaviour. Those two
can't both hold: `renderRepoCard` calls `card.disableAnimations()`
unconditionally (inherited from upstream), which emits `* {
animation-duration: 0s !important; animation-delay: 0s !important; }`,
so the `.header` fade-in has never actually run. You can see the rule in
the committed `pin.test.js.snap` on master.
I went with consistency: the call is now conditional, so the default
(`false`) animates the title like the other cards, and `true` keeps the
card static. That flips two existing pin snapshots, which is the visible
part of this diff. If you'd rather keep the card static by default, it's
a one-line change to `disable_animations = true` — say the word.
## Changes
- `packages/core/src/cards/repo.ts` — new `disable_animations` option,
`card.disableAnimations()` is now conditional.
- `packages/core/src/api/pin.js` — reads the query param and passes it
through `parseBoolean`.
- `apps/frontend/src/wizard/Home/buildCardUrl.ts` +
`stages/Customize.tsx` — the existing "Enable Animations?" checkbox is
now shown for the pin card and appends the param.
- `apps/frontend/src/content/docs/docs/cards/repo-pin.md` — documented.
## Tests
- `renderRepoCard.test.ts`: two cases, default renders without the
blanket rule, `disable_animations: true` renders with it.
- `buildCardUrl.test.ts`: pin URL gets `disable_animations=true` when
animations are turned off in the wizard.
- `pin.test.js`: `disable_animations=true` added to the many-params
snapshot request, same as the stats/top-langs/wakatime contract tests
do.
## Verified
`pnpm run typecheck`, `pnpm run lint` and the full `vitest run` suite
pass locally (755 passed, 6 skipped). I had to run vitest with
`--pool=threads`; the default forks pool times out spawning workers on
my Windows box, unrelated to this change.
Closes#612
---------
Co-authored-by: qwist1233-cpu <qwist1233@users.noreply.github.com>
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
This allows for better matching misspelled language names (such as
Typescript vs TypeScript).
I also lower-cased all colours, not just some.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
- use 4 parallel workers instead of 3
More PATs were added to the server recently, so no single PAT should
make too many requests to GitHub.
- Allow /api/repeat-recent to take up to 10 min.
The Vercel timeout was increased to 600 s via
https://vercel.com/docs/functions/configuring-functions/duration#dashboard.
This is a rewrite of #510 on top of the commits by luojiyin1987 so that
they are still credited as contribution.
---------
Co-authored-by: luojiyin <luojiyin@hotmail.com>
Fixes#509
## What
The five API handlers (`index`, `gist`, `pin`, `top-langs`, `wakatime`)
attach structured error details to their results while keeping the
`status` value stable:
```js
return {
status: "error - temporary",
error: describeError(err),
content: renderError({ ... }),
};
```
`describeError()` in `common/error.ts` returns `{ type?, message }`, for
example:
- `{ type: "MAX_RETRY", message: "Downtime due to GitHub API rate
limiting ..." }`
- `{ type: undefined, message: 'Missing params "username" ...' }`
## Why this shape
- `status` keeps its exact value, so the `=== "error - temporary"`
comparisons in `apps/backend/router.js` keep working. Error cache
headers (10 minutes) are unaffected.
- The npm package contract only gains an optional field, so external
callers see a backward-compatible extension.
- Unattended jobs can log `result.error.type` / `result.error.message`
to tell rate limits, token problems, network failures, and validation
errors apart.
## Tests
Full suite passes (724 tests). No snapshot changes: cache headers and
status values are identical to `master`.
Thanks to the review feedback on the first version of this PR, which
appended details to the status string and broke exact comparisons.
Dropped the unmaintained (from June 2020) and untyped `save-svg-as-png`
for `wizard/components/Card/downloadSvgAsPng.ts`:
`XMLSerializer` ➡️ data URL ➡️ `<img>` ➡️ `<canvas>` ➡️ `toBlob`.
The card SVGs are self-contained, so the library's style-inlining bought
nothing.
`Display.tsx` now reaches the card through a ref forwarded via
`CardImage` to `SvgInline`, rather than `getElementById("svg-wrapper")`.
Verified against the old library before removing it: both paths
converted the stats and repo cards at `scale: 2`, and the PNGs were
diffed pixel by pixel in Chromium (via LLM).
Dimensions match exactly; the few differing pixels are the library's,
which [copies rules matching nothing in the
SVG](https://github.com/exupero/saveSvgAsPng/blob/96484668c131d8a4babd82faa8a9d5bfdcaed64a/src/saveSvgAsPng.js#L212-L214)
out of the host page's stylesheets, and the injected font declaration
shifts the glyphs.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
- Text and number fields now use daisyUI's `.input` instead of
hand-rolled Tailwind,
and `NumericSection` adds `validator` so its existing `min`/`max` show a
hint.
- Fixed two contrast bugs in `index.css`:
1. an override was suppressing daisyUI's focus ring.
2. disabled text was at 2.5:1 contrast in the light theme (now 5.3:1 /
7.4:1 dark).
- Replaced two hand-rolled pieces with what daisyUI already ships: the
delete-account
modal is a native `<dialog>` plus `.modal`, gaining Esc, focus trap and
focus restore
while dropping
- `useOutsideAlerter` hook
- `createPortal`
- `LoginBox`'s `isOpaque` prop
- The card placeholders use `.skeleton`, removing
`react-loading-skeleton`.
- The sticky card panel on steps 3 and 5 was pinned at a fixed `top-32`,
so the progress bar covered up to 57px of it.
`ProgressBar` now exposes its measured height for the panels to stack
against.
- Section controls had no accessible name:
`Section` takes a `titleId` for its heading and the five sections point
at it with `aria-labelledby`.
## Screenshots
### Card position on step 3
| Before | After |
|
------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------
|
|

|

|
### Disabled field
| Before | After |
|
------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------
|
|

|

|
### Elsewhere
| Dark theme | Delete-account dialog |
|
----------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------
|
|

|

|
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
The wizard ran the whole `apps/backend` router in the browser.
#536 added `node:crypto` to `src/common/database.js`, Vite's browser
stub for a Node builtin throws on the first named-export causing e2e
tests timeouts.
`pg` already needed a `rolldownOptions.external` escape hatch for the
same reason.
- `src/wizard/renderCard.ts` maps a card URL's pathname to the matching
`packages/core` handler and `SvgInline` calls it.
`mock-http.ts` and the the `pg` external are removed alongside backend
dependency.
Resolves the `// will be solved by npm package`
https://github.com/stats-organization/github-stats-extended/blob/2e8537db4eb6ce932b8d072f764960e436f612af/apps/frontend/src/wizard/components/Card/SvgInline.tsx#L76-L78
- ~~`e2e/stubCardApi.ts` fulfils the card endpoints, so the `Display`
stage's fetch of `https://<host>/api…` no longer logs network errors
during e2e.~~ If `process.env.STUB_CARD_API` is set, vite will now serve
a stub card. This avoids network error logs during e2e tests without the
backend server running.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
- `setCSS({ light, dark })` now takes `(colors: CardColors) => string`
builders instead of CSS strings.
`Card` holds both palettes, so it calls `dark` only when it has dark
colors.
- Every card drops its `dark: darkColors ? … : null` ternary and its
`lightColors` destructuring,
each builder reads the colors of its own scheme from its parameter.
- `CardColors` moved to `common/color.ts` and is exported from there;
`Card.ts` had a duplicate 5-field copy.
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
Another step of #140
- `api/gist.js` ➡️ `api/gist.ts`
- The handler parses (`parseFloat`, `parseBoolean`); the card still
defaults.
Passing `undefined` for an absent param keeps every default in one
place.
- `CommonOptions` ➡️ `CommonCardOptions`, now extending `ColorParams`
since cards spread
their options into `getLightDarkColors`.
- `locale` moved onto the four cards that read it: the gist card has no
translated text.
The gist handler no longer takes or validates it, so
`/api/gist?locale=xx` renders the card instead of "Language not found".
Docs has been updated.
- `border_radius` is now validated at the boundary: `?border_radius=abc`
returns a permanent `Invalid number input for parameter "border_radius"`
instead of a temporary error leaking `Card`'s internal `Invalid border
radius: "NaN"`.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
* Extend scripts/assert-deduped.ts to treat e.g. `2.1.0` and
`2.1.0(axios@1.18.1)` as the same version.
----
* Delayed upgrade to typescript 7, because of peer dependency issues.
* Delayed axios upgrade, because of type incompatibilities with
axios-mock-adapter.
* Upgrade axios-cache-interceptor only a bit, to stay compatible with
the unchanged axios version.
* Upgrade astro, \@astrojs/markdown-satteri and
\@astrojs/markdown-remark only a bit, because their latest versions lead
to two different versions of satteri being installed, which leads to
type conflicts.
* Delayed upgrade to graphql 17, because there we get:
<details>
<summary>error message</summary>
```txt
> @stats-organization/github-readme-stats-core@2.1.5 check-graphql-types
/home/runner/work/github-stats-extended/github-stats-extended/packages/core
> node scripts/generate-graphql-types --check
file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/graphql@17.0.2/node_modules/graphql/type/validate.mjs:36
throw new Error(errors.map((error) => error.message).join('\n\n'));
^
Error: Interface field Node.id is not deprecated, so implementation
field Project.id must not be deprecated.
Interface field Node.id is not deprecated, so implementation field
ProjectCard.id must not be deprecated.
Interface field Node.id is not deprecated, so implementation field
ProjectColumn.id must not be deprecated.
Interface field Reactable.databaseId is not deprecated, so
implementation field PullRequest.databaseId must not be deprecated.
Interface field Reactable.databaseId is not deprecated, so
implementation field PullRequestReview.databaseId must not be
deprecated.
Interface field Reactable.databaseId is not deprecated, so
implementation field PullRequestReviewComment.databaseId must not be
deprecated.
Interface field Comment.authorAssociation is not deprecated, so
implementation field TeamDiscussion.authorAssociation must not be
deprecated.
Interface field UniformResourceLocatable.resourcePath is not deprecated,
so implementation field TeamDiscussion.resourcePath must not be
deprecated.
Interface field UniformResourceLocatable.url is not deprecated, so
implementation field TeamDiscussion.url must not be deprecated.
Interface field Comment.authorAssociation is not deprecated, so
implementation field TeamDiscussionComment.authorAssociation must not be
deprecated.
Interface field UniformResourceLocatable.resourcePath is not deprecated,
so implementation field TeamDiscussionComment.resourcePath must not be
deprecated.
Interface field UniformResourceLocatable.url is not deprecated, so
implementation field TeamDiscussionComment.url must not be deprecated.
at assertValidSchema
(file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/graphql@17.0.2/node_modules/graphql/type/validate.mjs:36:15)
at validateImpl
(file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/graphql@17.0.2/node_modules/graphql/validation/validate.mjs:20:5)
at validate
(file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/graphql@17.0.2/node_modules/graphql/validation/validate.mjs:15:11)
at validateGraphQlDocuments
(file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/@graphql-tools+utils@11.2.2_graphql@17.0.2/node_modules/@graphql-tools/utils/esm/validate-documents.js:19:20)
at
file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/@graphql-codegen+core@6.2.0_graphql@17.0.2/node_modules/@graphql-codegen/core/esm/codegen.js:89:40
at
file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/@graphql-codegen+plugin-helpers@7.2.1_graphql@17.0.2/node_modules/@graphql-codegen/plugin-helpers/esm/profiler.js:5:49
at async codegen
(file:///home/runner/work/github-stats-extended/github-stats-extended/node_modules/.pnpm/@graphql-codegen+core@6.2.0_graphql@17.0.2/node_modules/@graphql-codegen/core/esm/codegen.js:76:24)
at async
file:///home/runner/work/github-stats-extended/github-stats-extended/packages/core/scripts/generate-graphql-types.js:229:21
at async Promise.all (index 0)
at async
file:///home/runner/work/github-stats-extended/github-stats-extended/packages/core/scripts/generate-graphql-types.js:227:19
Node.js v24.20.0
/home/runner/work/github-stats-extended/github-stats-extended/packages/core:
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL
@stats-organization/github-readme-stats-core@2.1.5 check-graphql-types:
`node scripts/generate-graphql-types --check`
Exit status 1
```
</details>
- frontend: remove line break from page icon
- frontend: add `all_time_contribs` to "all stats" option
- frontend: add mock data for `all_time_contribs`
- Built on top of #531
---
- `starlight-theme.css` shrink-wraps `.card-preview-link` instead of
every `a:has(> img)`,
so links around non-card images (the Vercel deploy button on the Deploy
page) keep their prose layout.
- The walk is now two flat passes: collect every image, then rewrite
each once.
Nothing is spliced mid-iteration, so a copy the plugin adds is never
revisited.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
The Vercel function has a timeout of ca 5 min. By giving curl a bit more
time, the call should be ended by Vercel instead of curl normally. This
will turn the pipeline green.
Handle timeouts, "RESOURCE_LIMITS_EXCEEDED" type responses and empty
responses. For the first two we retry with less data; for the last we
retry 3 times.
- add `all_time_contribs` stat that shows the number of repositories a
user has contributed to across all years — not just the past year like
the default `contribs` stat.
- add parameter `contribs_include_own_repos` to include the user's own
repositories in the `contribs` and `all_time_contribs` stats. By
default, both stats exclude them and only count repositories owned by
other users or organizations.
---------
Co-authored-by: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com>
> TL;DR: I have added the translation keys for Traditional Chinese to
ensure that the statistics card does not show error messages due to lack
of translation keys.
Now, when I set the locale to "zh-tw", the thumbnail does not show
anything, but directly tells me that the i18n key for the corresponding
language is missing.
Therefore, I created this pull request to complete the translation key
for Traditional Chinese to ensure that users can see the statistics card
normally.
<img width="591" height="137" alt="image"
src="https://github.com/user-attachments/assets/d2a6e599-2a26-4b3f-b9d9-a79ffbb8e2e0"
/>
At the same time, I also suggest that you consider setting the i18n
Fallback project, so that when the translation key is lacking, the
system will try to display the content in English (or display the
missing translation key, or use any other language).
> [!NOTE]
> Just a POC, marking as draft until #515 and #516 are merged.
- Adds `apps/frontend/src/plugins/rehypeCardImages.ts`:
a `/api` image that names no theme is emitted twice, once per site theme
— `light_github` / `dark_github` or the `*_repocard` pair.
One that names a theme is left untouched.
- Every `/api` image also gets `loading="lazy" decoding="async"`,
so the theme is not using costs no request.
- Drops the inline `<img>`/`<a>` HTML from `docs/index.md` and
`customization/theming.md`;
previews on the other docs pages became theme-aware without being
edited.
Once the other docs PRs are merged I'll rebase and apply the same change
everywhere.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
- The generator writes
`apps/frontend/src/content/docs/docs/customization/themes.md`, but the
workflow still described a README.
- Renamed the workflow/job to "Generate Themes Doc" and reworded its
steps.
- PR metadata now reads `docs(frontend): update available themes page`,
branch `update_themes_doc/patch`, with the docs page linked in the body.
- Push filter also watches `scripts/generate-theme-readme.js`.
- Adds one `astro` group in `.github/dependabot.yml`
- `@astrojs/starlight` and its plugins ride along with Astro core bumps,
since a Starlight upgrade usually tracks the Astro version anyway.
Another step of #140
- `cards/wakatime.js` ➡️ `cards/wakatime.ts`
- Test and snapshot renamed to `renderWakatimeCard.test.ts` /
`renderWakatimeCard.test.ts.snap`;
the snapshot are unchanged.
- New `common/languageColors.ts` owns the language-color table:
the gist and wakatime cards repeated `(languageColors as Record<string,
string>)[name] || "#858585"` three times, and top-languages declared a
fourth copy of that hex.
They now share `getLanguageColor()` / `DEFAULT_LANG_COLOR`, and typing
the table at the import removes the cast.
- Closes#461
---
- Turns `apps/frontend` into an [Astro](https://astro.build/) +
[Starlight](https://starlight.astro.build/) site.
Serves the docs at `/frontend/docs` and the card wizard at `/frontend`:
one dev server, one build, one deploy, and no Python in
`vercel-preparation.sh` or in the local setup.
- The wizard becomes a page of that site: a React island on Starlight's
`splash` layout,
so it inherits the header, footer and search.
Its own app bar, theme picker and Redux theme slice go away.
Starlight writes the `data-theme` daisyUI already reads, so one control
themes both halves.
- The `*.md` sources move to `apps/frontend/src/content/docs/docs/` with
a `title` in
frontmatter and Starlight's `:::note` asides, which lets Astro resolve
their links and
images natively (no markdown-conversion code of our own).
`starlight-links-validator` then fails the build on a dead internal
link.
- `packages/core/src/themes/README.md` is generated into the site
instead; README and CONTRIBUTING links follow the move.
- Tailwind now shares a page with Starlight, so `index.css` declares the
cascade-layer order
(its utilities must outrank Starlight's reset) and scopes the app's
element rules under
`.wizard`, leaving the site identical on both halves.
---
To try it out just run
```sh
pnpm --filter ./apps/frontend run dev
```
---
| Wizard | Documentation |
|--------|--------|
| <img width="1710" height="666" alt="Screenshot 2026-08-17 at 00 54 18"
src="https://github.com/user-attachments/assets/c5b29e34-5464-41f3-9d01-08f593c87660"
/> | <img width="1710" height="720" alt="Screenshot 2026-08-17 at 00 54
25"
src="https://github.com/user-attachments/assets/e7e3f414-bf62-441d-9f6e-537a20044b0b"
/> |
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
- `packages/core/tsconfig.json` covers `tests` but also set `outDir:
"build"`,
so a simple `tsc` emitted `build/tests`, which turbo then cached and
replayed on every later build.
- `tsconfig.base.json` now sets `noEmit: true`;
`packages/core/tsconfig.build.json` is the only config that opts back
in, and it takes the `outDir`.
- Removed `noEmit` from the typecheck and scripts configs.
- Removed `composite: true` from both apps: nothing references them as
TypeScript projects.
> [!NOTE]
> Local-only issue: CI never runs a standalone `tsc` and starts from a
clean checkout,
> so the polluted `build/` never showed up there.
- Card tests now assert with jest-dom matchers instead of reading nodes
by hand:
`toHaveTextContent`, `toHaveAttribute`, `toHaveStyle`,
`toBeInTheDocument`.
- Fixes assertions in `renderStatsCard.test.ts`:
`queryByTestId` returns `null`, so `toBeDefined()` could never fail.
One of them was checking `rank-percentile-text`, which is a CSS class
and not a test id.
- Index-existence checks became `toHaveLength(n)`;
- The five `toMatchInlineSnapshot` translation checks became explicit
`toHaveTextContent` with the same strings.
- `renderWakatimeCard.test.js` moved to the `screen` API
- `card.test.ts` uses `querySelector` over `getElementsBy*`.
Add a new optional stat for the stats card, "Total Contributions".
* I think this is something many users want. There are many issues where
people wonder why their "contributed to" or their "total commits"
doesn't match their contributions.
* This PR also introduces a way to fetch and sum stats which are only
available for 1 year at a time in the GitHub API. We could reuse this
later for more highly requested all-time stats if necessary.
I will add documentation in a separate PR.
---------
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
Co-authored-by: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com>
The queries moved to `src/graphql/queries/*.graphql` and their types are
generated from
GitHub's schema instead of hand-written.
- `scripts/generate-graphql-types.js` validates each query against
`@octokit/graphql-schema` and writes one file per query plus a shared
`common.ts`,
so a wrong field fails generation and a wrong variable fails `tsc`.
- `pnpm check-graphql-types` runs in CI, so the generated types can't
drift.
- `httpGraphQLRequest` takes a generated document: the four
`*QueryResponse` interfaces are gone and `GRAPHQL_REPOS_FIELD` is a real
fragment.
Untyped `request` stays exported for the backend, with a TODO for
considering its removal.
- Fixed nullability the hand-written types got wrong
- (a gist's `owner` and `files[].name`, `user`, `repositories.nodes`);
- `Lang.color` is nullable again
- `parseOwnerAffiliations` returns the schema's `RepositoryAffiliation`.
- `graphql` stays on 16: `@octokit/graphql-schema` needs `^16`.
> [!WARNING]
> The four `apps/backend` contract snapshots were refreshed:
> the recorded request text changed, the rendered SVGs did not.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
Another step of #140.
- `src/cards/top-languages.js` + its test ➡️ `.ts`.
- `fetchers/types.ts`: `Lang.color` made `string | null` to match
GitHub's nullable GraphQL `Language.color`.
The card already falls back to a default and a test pass `color: null`.
- Extracted the copy-pasted "resolve + validate language color" block
into `resolveLangColor`.
- Test uses the `screen` API, caches repeated `queryAll` results in
local variables, and types its language fixtures with `satisfies
TopLangData`.
Another step of #140.
- `src/cards/stats.js` + its test ➡️ `.ts`.
- Moved `createTextNode` out of the stats card into `common/render.js`
(next to the other SVG-node builders).
It was the one card export used by another card (repo).
- `I18n` gained a default type param (usable as a bare type),
and `Card`/`createTextNode` accept the possibly-undefined options cards
forward.
- Card tests now use the `screen` API instead of
`getByTestId(document.body, …)`.
See [recommended query
entrypoint](https://testing-library.com/docs/queries/about/#screen) and
cache repeated queries in local variables.
Also applied on the already-migrated `gist`/`repo` tests.
Upgrading pnpm to version 11 led to errors on Vercel on each request.
https://github.com/stats-organization/github-stats-extended/issues/458
shows an example stack trace. Vercel doesn't support pnpm 11 yet
according to [their docs](https://vercel.com/docs/package-managers). I
have tried understanding and fixing the actual issue, but had to give up
at some point. So for now let's downgrade to pnpm 10, wait for Vercel to
support pnpm 11, then upgrade again.
Additionally, #458 showed that we should direct users to use the
`release` branch when self-hosting. So this PR also updates the docs
accordingly.
> [!NOTE]
When this PR is approved I should create an issue for the pnpm 11
upgrade.
---------
Co-authored-by: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com>
- Bumps `packageManager` to `pnpm@11.20.0` and migrates
`onlyBuiltDependencies` to the new `allowBuilds` map.
- Adds
- `savePrefix: ""`
- `strictPeerDependencies`
- `engineStrict`
to `pnpm-workspace.yaml`.
Nothing fails today, so these only guard regressions.
- Regenerates the lockfile and dedupes.
Collapses two duplicates:
- `typescript-eslint` 8.64.0 → 8.65.0,
- `vite>lightningcss` override, guarded by a new `lint:deps` check so
the override can't silently drift.
- **axios stays on 1.18.1.** 1.19 adds a params generic that breaks 5
core tests typecheck
(https://github.com/stats-organization/github-stats-extended/pull/449).
Worth fixing in its own PR then.
Another step of #140
- `src/cards/repo.js` + its test ➡️ `.ts`
- Colocated each card's options type into its own file;
`types.ts` keeps only the shared `CommonOptions` and the options of the
js cards.
All `*CardOptions` are now `interface CardNameOptions extends
CommonOptions` (were `type` intersections).
- `fetchers/types.ts`: made `RepoInfo.description` and `primaryLanguage`
(and its fields) nullable to match the GraphQL schema.
The card already guards for these and the tests exercise them.
- `common/I18n.ts`: widened the constructor's `locale?: string` to
accept `undefined`, since cards forward possibly-undefined query
options.
Another step of #140, continues #426. Starts `cards/`.
- `src/cards/types.d.ts` ➡️ `types.ts`.
- `gist` card + test ➡️ `.ts`. Typed against `GistData` /
`Partial<GistCardOptions>`;
replaced the `// @ts-ignore` on the language-color lookup with a
`Record` cast.
- `Card.ts`: widened the constructor's `border_radius?: number` to `?:
number | undefined`:
cards forward possibly-undefined query options (same pattern as
`getCardColors`).
Needed by every card.
Follow-up to [the `themes/index.js` ➡️ `index.ts`
migration](https://github.com/stats-organization/github-stats-extended/pull/139),
which left the theme README generation pipeline pointing to files that
no longer exist.
* Renamed the workflow, script, and pnpm command to the consistent
`generate-theme-readme` (previously `generate-theme-doc` /
`theme-readme-gen`) and updated them to use the `.ts` source.
* Reduced workflow permissions from 12 declared scopes to the 2 actually
required:
* `contents: write`
* `pull-requests: write`
* Fixed the generated PR body, which incorrectly referenced language
files.
---
> [!NOTE]
> After this is merged, I'd consider applying the same permission
reduction and workflow rename to `update-langs.yml`.
- Swaps the third-party `fjogeleit/http-request-action` for a plain
`curl` step in `repeat-recent-requests.yml`:
the workflow only needs a POST with a timeout, so the action added no
value.
- The request carries only what the endpoint reads. `repeat-recent`
checks `req.method` and nothing else.
So the action's JSON body and headers were never used.
Each flag has a one-line comment explaining why it's there.
- Failure semantics are preserved: a `>= 400` status or a connection
failure still fails the job, and the response body and status are now
logged even on failure.
Example run:
https://github.com/marcalexiei/github-stats-extended/actions/runs/30751117550/job/91505220151
Related to
https://github.com/stats-organization/github-stats-extended/pull/430
> [(The failing Backend E2E test is expected, because this PR changes
the output of most cards, but in a non-visible
way.)](https://github.com/stats-organization/github-stats-extended/pull/430#issuecomment-5153247227)
- `ci.yml`: comment explaining what the job compares and why it fails.
- `CONTRIBUTING.md`: new "Tests" section, there was no testing
documentation before.
Removed the FAQ, whose three entries were all user questions, and
promoted Feature Request from `h3` to `h2`.
- `advanced_documentation`: kept the two useful FAQ answers, in context:
- language-card troubleshooting links under "Language stats algorithm",
- percent-encoding example (`&hide=jupyter%20notebook`) under "Hide
individual languages".
Demo labels changed from list items to `h4` headings: the images were
never indented into the list, so each label rendered as its own one-item
bullet.
- `deploy.md`: normalized the token-setup lists from `*` with 4 space
indents to `-` with 2 space indents.
Marker and indentation only, nesting preserved.
- `README.md`: the seven section headings were `h1`. With the HTML
`<h1>` in the banner that made eight top-level headings on one page, so
they are now `h2`.
Heading anchors are derived from the text, so the table of contents is
unaffected.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
Add support for light mode and dark mode without [brittle,
GitHub-specific
approaches](https://github.com/stats-organization/github-stats-extended/blob/master/docs/advanced_documentation.md#responsive-card-theme).
All endpoints accept new parameters: theme_light, theme_dark,
title_color_light,
title_color_dark, icon_color_light, icon_color_dark, etc.
> Priority (lowest -> highest):
> default theme -> `theme` param -> `theme_light`/`theme_dark` param
> -> general color params -> `*_light`/`*_dark` color params
Additionally, this PR adds the recently introduced `progBarBgColor`
parameter to `CardColors` and handles it together with the other colors
in color.ts, for consistency. And it adds one test for an archived
repository.
This PR is already too big, so I'll add documentation in a later PR, and
maybe also a simple new option for the frontend.
My main question here is: does the API and the intended behaviour make
sense? Bugs can be fixed later, but once the new parameters are
released, ideally we shouldn't change them anymore.
---------
Co-authored-by: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com>
Another step of #140, continues #415.
Last fetcher: `fetchers/` is now fully TS.
- `repo` fetcher + test ➡️ `.ts`.
Defines `RepoInfo` and `RepoQueryResponse`, calls
`retryer<RepoQueryResponse>(…)`
- `types.ts`: made `RepositoryData`'s PR/issue count fields optional:
they come from `fetchRepoUserStats`, which only sets them when the
matching `include_*` flag is on.
Another step of #140, continues #410.
- `stats` fetcher + test ➡️ `.ts`, threading typed GraphQL and
REST-search shapes through `retryer<…>`.
- Added a `src/_github-username-regex.d.ts` shim (package ships no
types).
- Fixed a bug caught by the types: statsFetcher expected pat in its
options object,
but the caller passed it as a second argument, so it was ignored.
Private-access users' token is now correctly passed to the main stats
query.
Another step of #140, continues #370.
- `wakatime` fetcher + test ➡️ `.ts`. Typed the props object and the
axios body (`axios.get<{ data: WakaTimeData }>`);
replaced the raw `err.response.status` access with an
`axios.isAxiosError` guard.
- `top-languages` fetcher + test ➡️ `.ts`, calling
`retryer<TopLanguagesQueryResponse>(…)`.
Split the single `let repoNodes` (reused across three shapes) into typed
values and simplified two of the three `reduce` calls (map-builder →
`for…of`, final sort ➡️ `Object.fromEntries`).
The flatten `reduce` is kept as-is — its order feeds the `repoCount`
logic.
- `types.ts`: added `count: number` to `Lang` (the fetcher always
produces it; the card only reads `name`/`color`/`size`).
* In the frontend, "Modify Parameters" step, a few options of several
dropdowns encoded multiple parameters in their value string. That didn't
work anymore since a recent change. This PR fixes the affected dropdown
options.
* Since a recent change, using the "ambient_gradient" theme for WakaTime
card didn't work anymore. This PR fixes that.
Another step of #140, continues #322.
Starts migrating `fetchers/`.
- `retryer` is now generic over the response payload:
`retryer<TData>(…)` returns `AxiosResponse<TData & ResponseErrors>` so
callers get their own `response.data` shape while the retryer still
reads `errors`/`message`.
Defaults to `unknown` so existing callers are unaffected.
- `src/fetchers/types.d.ts` ➡️ `types.ts` (references are extensionless,
so they resolve unchanged).
- `gist` fetcher + test ➡️ `.ts`, using `retryer<GistQueryResponse>(…)`.
> [!WARNING]
> Consider reviewing #375 first, as it resolves the "Resource limits for
this query exceeded" issue.
> This PR will likely conflict with it, so it's better to merge #375
first.
Load on Vercel is higher than expected. It seems the problem is that
Vercel's CDN evicts our responses before they go stale, because there
are relatively few requests per card. So the repeat-recent functionality
currently causes load without achieving much.
This PR increases ISR expiration time to see how this affects load in
practice. Setting this time via env var might be a task for later.
`HomeScreen` held ~16 separate `useState` hooks for card options and
threaded them through 34 props into `CustomizeStage`.
This consolidates them into a single typed `CardOptions` state object
(new `pages/Home/cardOptions.ts`), updated via a keyed setter.
### Changes
- `CustomizeStage` props go from 34 to 5; `buildCardUrl` takes `userId`,
`selectedCard` and `options`.
- Stage descriptions move into `STAGE_LABELS`, replacing a positional
string array in the JSX.
- The three GitHub-URL paste handlers in `CustomizeStage` share one
`pastedPathTail` helper.
- A failed OAuth `authenticate` call left the page stuck on the loading
spinner;
the exchange now runs in `try/catch/finally` and the redirect is parsed
with
`URLSearchParams` instead of substring matching.
- Related to #342
`stats` and `pin` already reject `username`/`repo`/`owner` that don't
match `safePattern` (`/^[-\w/.,]+$/`), but `top-langs`, `wakatime`, and
`gist` didn't.
This applies the same guard:
- `top-langs` + `wakatime`: reject a `username` containing unsafe
characters.
Matters most for `wakatime`, where `username` is interpolated into the
outbound request URL path.
- `gist`: same guard on its `id` param.
All three return the existing `error - permanent` card before any fetch.
## Additional change
Simplified the `layout` / `stats_format` checks in `top-langs`:
dropped the redundant `typeof x !== "string" ||` (a non-string already
fails `.includes(...)`),
keeping the `x !== undefined` guard so the params stay optional.
The advanced documentation file in the docs/ folder incorrectly links to
a nonexistent folder called "backend/" for the calculate rank logic.
This PR fixes the broken link by changing the link to
"packages/core/src/calculateRank.js".
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
* GitHub actually triggers the cron workflow every few hours. Because
they are overloaded I suppose. This PR is an attempt to give the
workflow more chances to be triggered.
* Sometimes we run into secondary rate limiting of the GitHub API when
repeating recent requests. Having less workers should fix this.
The frontend Playwright config only enables the chromium project, so CI
was needlessly downloading Firefox and WebKit.
Scope `playwright install` to `chromium` to speed up the e2e job.
Card URLs were built by hand-concatenating paths and query strings in
several places.
This replaces that with a typed, immutable per-card URL builder
(`cardUrl(cardType)`), so URLs are assembled in one place with proper
encoding.
## Changes
- New `models/CardUrl.ts`: one builder per card type, exposing only the
params that card supports.
`URLSearchParams` handles joining + encoding. Also carries a per-card
`filename()` for downloads.
- `getFullSuffix.ts` ➡️ `buildCardUrl.ts`: returns a builder instead of
a string.
- The builder is passed as a prop through all card components; no
hand-written `?`/`&` concatenation left.
- New `useCardDescriptor` hook resolves per-card display metadata (guest
hint + link) and owns the
Gist URL fetch, replacing the repeated `switch (selectedCard)` blocks in
`Home`.
- Added tests for `CardUrl`.
### Notes
- Params now go through `URLSearchParams`, so commas become `%2C` and
spaces `%20`.
The server decodes these before use, so rendered cards are unchanged.
- Builders are `useMemo`'d in `Home` to keep stable references.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
- Fixes#325
`eslint-plugin-react@7.37.5` doesn't declare support for ESLint 10,
producing an unmet-peer-dependency warning.
## Changes
- Swapped `eslint-plugin-react` ➡️ `@eslint-react/eslint-plugin` and
adopted its `recommended-typescript` config.
This also replaces `eslint-plugin-react-hooks` (the preset ships
equivalent `rules-of-hooks`/`exhaustive-deps`), so both old plugins are
removed.
- Fixed the violations the new preset surfaced:
- IIFEs-in-JSX in `Home.tsx` ➡️ lifted to `const` bindings.
- Ref naming (`*Ref`).
- 4 `set-state-in-effect` cases ➡️ rewritten as render-phase state
adjustment ([React
docs](https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes)).
- Extracted the shared debounced-input logic from
`TextSection`/`NumericSection` into a `useDebouncedField` hook.
- Added a standalone Playwright spec (`e2e/app-trends-auth.spec.ts`)
covering the `AppTrends` auth-driven stage transition.
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
Second wave of the `packages/core` TypeScript migration (#140),
continuing #292.
Converts the remaining `common/` modules and their tests from JSDoc
`.js` to real `.ts`.
## Changes
- **Modules ➡️ `.ts`**: `common/http`, `common/ops`, `common/render`,
`calculateRank`.
- **Tests ➡️ `.ts`**: `ops`, `flexLayout`, `render`, `calculateRank`.
- **`src/_emoji-name-map.d.ts`**: `declare module` shim.
`emoji-name-map` ships no types
and has no `@types` package (same as the existing
`@uppercod/css-to-object` shim).
- **`common/color.ts`**: widened `getCardColors` optional params to `?:
string | undefined`
so `renderError` can forward possibly-`undefined` colors under
`exactOptionalPropertyTypes`.
Adds light/dark theming to the frontend using the existing DaisyUI +
Tailwind setup.
- Theme picker dropdown in the header; selection is stored in Redux and
persisted to `localStorage`.
The toggle and each option show a sun/moon icon (shared `ThemeIcon`
component) so light/dark are easy to tell apart.
- Migrated hardcoded colors to DaisyUI tokens so the whole UI (and
toasts) follow the theme.
- `Button` now uses `variant` / `size` / `outline` props instead of raw
`btn-*` classes.
- Theme preview cards: (Select Theme grid and the final Display card)
sit on a two-tone backdrop (light or dark), chosen by the card theme so
previews stay consistent regardless of the app theme.
- Smooth theme-switch transitions: surfaces fade gently while
interactive elements stay snappy; respects `prefers-reduced-motion`.
- Added an e2e test for the picker.
<details><summary>Step 1</summary>
<p>
<img width="1710" height="811" alt="Screenshot 2026-06-24 at 06 54 40"
src="https://github.com/user-attachments/assets/38d629b5-eaa3-4fb1-b976-c56e7a840ced"
/>
<img width="1706" height="808" alt="Screenshot 2026-06-24 at 06 54 32"
src="https://github.com/user-attachments/assets/3811a574-016c-4a93-82a9-a340519f5257"
/>
</p>
</details>
<details><summary>Step 4</summary>
<p>
<img width="1709" height="899" alt="Screenshot 2026-06-24 at 06 56 22"
src="https://github.com/user-attachments/assets/4053b938-1faa-427b-b621-e79ce7b2c7b1"
/>
<img width="1705" height="894" alt="Screenshot 2026-06-24 at 06 55 41"
src="https://github.com/user-attachments/assets/8aace78a-f1ca-4d29-b57e-938f7b473e67"
/>
</p>
</details>
---------
Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
Starts migrating `packages/core` to TypeScript (#140).
- Converted the `common/` modules to `.ts`:
- `Card`, `I18n`, `color`, `config`, `constants`, `error`, `fmt`,
`html`, `icons`, `retryer`, `translations`.
- Replaced JSDoc types and `@ts-check`/`@ts-ignore` comments with real
TypeScript types.
- Enabled type-checking on the source and moved `noCheck` into the build
config.
- Converted the tests that target those modules to `.ts`:
- `fmt`, `i18n`, `card`, `color`, `html`, `retryer`.
- Converted `tests/_setup.ts` and moved the jest-dom matcher typing
there: augmenting vitest's `Matchers` interface (per the vitest docs) so
matchers like `toHaveAttribute` are typed on `expect(...)`.
- Added a `tests/css-to-object.d.ts` shim so `@uppercod/css-to-object`
resolves under `nodenext` (it ships types but doesn't expose them via
`exports`).
Bumps the typescript group with 1 update:
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).
Updates `@types/node` from 24.13.1 to 24.13.2
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the react group with 1 update in the / directory:
[@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react).
Updates `@types/react` from 19.2.16 to 19.2.17
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@@ -21,4 +21,4 @@ If you believe someone is violating the code of conduct, we ask that you report
- Repeated harassment of others. In general, if someone asks you to stop, then stop.
- **When we disagree, try to understand why.** Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
Based on the [Django Code of Conduct](https://www.djangoproject.com/conduct/).
Based on the [Django Code of Conduct](https://www.djangoproject.com/conduct/).
docker run -p 9000:80 --env-file apps/backend/.env github-stats-extended
```
### via pnpm
First install all dependencies:
```bash
pnpm install
pnpm run build:packages
```
To run the frontend dev server:
```bash
pnpm run dev:frontend
```
The easiest way to run and test the project is to deploy it to Vercel as described in the [deployment guide](../docs/deploy.md).
The frontend attempts to load stats cards from the backend in several places. To make this work locally, run the backend dev server in a separate terminal.
To run the backend dev server:
```bash
pnpm run build:packages
pnpm run dev:backend
```
### Environment Variables
To successfully render stats cards, your test server needs a valid [Personal Access Token](https://github-stats-extended.vercel.app/frontend/docs/deploy/#first-step-get-your-personal-access-token-pat). Set this PAT and any of the [other, optional environment variables](https://github-stats-extended.vercel.app/frontend/docs/deploy/#available-environment-variables) in [`apps/backend/.env`](./apps/backend/.env).
## Tests
```bash
pnpm run lint # eslint
pnpm run typecheck # tsc
pnpm run format:check # prettier
pnpm run test# unit tests
```
The **Backend E2E test** in CI compares the cards your branch renders against the ones served by the preview deployment, which is still on the last commit merged to master.
So if your PR changes card output at all, that job goes red until the preview catches up.
It's marked `continue-on-error`, so it won't block your PR, but do open it and check the diff is only what you expected.
If the change to card markup was intentional, update the snapshots:
```bash
pnpm --filter ./packages/core/ run test:update:snapshot
pnpm --filter ./apps/backend/ run test:update:snapshot
```
## GraphQL Queries
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:
```bash
pnpm --filter ./packages/core/ run generate-graphql-types
```
CI 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.
## Themes Contribution
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 card [customization options](../docs/advanced_documentation.md#customization).
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 card [customization options](https://github-stats-extended.vercel.app/frontend/docs/customization/common-options/).
## Translations Contribution
GitHub-Stats-Extended supports multiple languages. If we are missing your language, you can contribute it! You can check the currently supported languages [here](../docs/advanced_documentation.md#available-locales).
GitHub-Stats-Extended supports multiple languages. If we are missing your language, you can contribute it! You can check the currently supported languages [here](https://github-stats-extended.vercel.app/frontend/docs/customization/locales/).
To contribute your language you need to edit the [backend/src/translations.js](../backend/src/translations.js) file and add a new property to each object where the key is the language code in [ISO 639-1 standard](https://www.andiamo.co.uk/resources/iso-language-codes/) and the value is the translated string.
To contribute your language you need to edit the [packages/core/src/translations.ts](../packages/core/src/translations.ts) file and add a new property to each object where the key is the language code in [ISO 639-1 standard](https://www.andiamo.co.uk/resources/iso-language-codes/) and the value is the translated string.
## Any contributions you make will be under the MIT Software License
@@ -30,25 +89,7 @@ In short, when you submit changes, your submissions are understood to be under t
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/stats-organization/github-stats-extended/issues/new/choose). If there is already an open issue for your bug in the upstream repo [github-readme-stats](https://github.com/anuraghazra/github-readme-stats/issues) you don't need to report it here.
## Frequently Asked Questions (FAQs)
**Q:** How to hide Jupyter Notebook?
> **Ans:** &hide=jupyter%20notebook
**Q:** Language Card is incorrect
> **Ans:** Please read all the related issues/comments before opening any issues regarding language card stats:
Please report any security vulnerabilities to github.stats.extended@gmail.com. I will try to respond as quickly as possible, but since I am maintaining this project in my free time, please allow some time for a response.
Please report any security vulnerabilities to github.stats.extended@gmail.com. I will try to respond as quickly as possible, but since I am maintaining this project in my free time, please allow some time for a response.
This project is an [extended version](docs/fork.md) of [github-readme-stats](https://github.com/anuraghazra/github-readme-stats). It generates [various stats cards](#card-types), e.g. about your GitHub contributions, your top languages, etc. You can [customize](#advanced-customization) the cards via multiple parameters.
GitHub-Stats-Extended is the [extended, actively maintained successor](https://github-stats-extended.vercel.app/frontend/docs/fork/) of [github-readme-stats](https://github.com/anuraghazra/github-readme-stats). It generates [various stats cards](#card-types) about your GitHub contributions, your top languages and more. You can [customize](#documentation) the cards via multiple parameters.
## Table of Contents
# Table of Contents
- [Quick Start](#quick-start)
- [Migration from github-readme-stats](#migration-from-github-readme-stats)
- Change the `?username=` value to your GitHub username.
- Done!
## Quick Start
-----------------------
Copy and paste this into your markdown, then change the `?username=` value to your GitHub username:
As more comfortable alternative, use the [GitHub-Stats-Extended Wizard](https://github-stats-extended.vercel.app/frontend) to create your custom stats card. Copy the generated markdown code and paste it into your [GitHub profile README](https://docs.github.com/en/account-and-profile/how-tos/profile-customization/managing-your-profile-readme#adding-a-profile-readme). Done!
As a more comfortable alternative, use the [card wizard](https://github-stats-extended.vercel.app/frontend) to configure your card visually. Then copy the generated markdown into your [GitHub profile README](https://docs.github.com/en/account-and-profile/how-tos/profile-customization/managing-your-profile-readme#adding-a-profile-readme).
## Migration from github-readme-stats
To migrate from [github-readme-stats](https://github.com/anuraghazra/github-readme-stats) you only need to change the domain from `github-readme-stats.vercel.app` to `github-stats-extended.vercel.app`:
GitHub-Stats-Extended aims to be fully compatible with github-readme-stats. For details see [Compatibility Notes](https://github-stats-extended.vercel.app/frontend/docs/fork/#compatibility-notes).
The [GitHub-Stats-Extended Wizard](https://github-stats-extended.vercel.app/frontend) offers some essential customization options. For more advanced customization check out the [advanced documentation](docs/advanced_documentation.md).
## Documentation
# Acknowledgements
This project is based on [github-readme-stats](https://github.com/anuraghazra/github-readme-stats). On top of their functionality I added several new features and improvements. See [Fork Information](docs/fork.md) for a list of changes. The frontend I added to the project is based on [GitHub Trends](https://github.com/avgupta456/github-trends). Big thanks to [@anuraghazra](https://github.com/anuraghazra), [@avgupta456](https://github.com/avgupta456), [@rickstaa](https://github.com/rickstaa), [@qwerty541](https://github.com/qwerty541) and everyone else who worked on these projects! ❤️
The [card wizard](https://github-stats-extended.vercel.app/frontend) offers some essential customization options. For more advanced customization and other project info check out the [documentation](https://github-stats-extended.vercel.app/frontend/docs/cards/stats/).
# Self-Hosting
Since the GitHub API only allows a limited number of requests per hour, the public instance of GitHub-Stats-Extended at https://github-stats-extended.vercel.app/api could possibly hit the rate limiter. If you host your own instance you do not have to worry about anything. Also, if you don't want to give my GitHub-Stats-Extended instance access to your private contributions but still want to include these contributions in your stats, you can simply host your own instance.
## Acknowledgements
See [Deploy on your own](docs/deploy.md) for various deployment options.
This project is based on [github-readme-stats](https://github.com/anuraghazra/github-readme-stats). The card wizard is based on [GitHub Trends](https://github.com/avgupta456/github-trends). Big thanks to [@anuraghazra](https://github.com/anuraghazra), [@avgupta456](https://github.com/avgupta456), [@rickstaa](https://github.com/rickstaa), [@qwerty541](https://github.com/qwerty541) and everyone else who worked on these projects! ❤️
<tspan dy="1.2em" x="25">Help us take over the world with a deeply customizable</tspan><tspan dy="1.2em" x="25">React, TypeScript and GraphQL chat app that has enough</tspan><tspan dy="1.2em" x="25">text to wrap across multiple lines in the repository card.</tspan>
"Help us take over the world with a deeply customizable React, TypeScript and GraphQL chat app that has enough text to wrap across multiple lines in the repository card.",
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.