# How to Use GitHub Actions to Generate Static SVG Cards for GitHub Readme Stats

> Generate static SVG cards for GitHub Readme Stats using GitHub Actions. Automate updates, avoid API limits, and ensure 100 uptime for your profile.

- Repository: [Anurag Hazra/github-readme-stats](https://github.com/anuraghazra/github-readme-stats)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Use a scheduled GitHub Actions workflow to run the `readme-tools/github-readme-stats-action`, save the generated SVGs to your profile repository, and embed them with relative paths to eliminate API rate limits and ensure 100% uptime.**

The `anuraghazra/github-readme-stats` project renders dynamic GitHub statistics as SVG cards, but relying on the public Vercel instance exposes you to rate limiting and downtime. By configuring **GitHub Actions to generate static SVG cards for GitHub Readme Stats**, you can pre-render these images directly in your profile repository, serving them as static assets that load instantly without external API calls. This approach leverages the card generation logic found in [`src/cards/stats.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/stats.js) and [`src/cards/top-languages.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/top-languages.js) to produce reliable, self-hosted statistics.

## Why Static SVGs Outperform On-Demand Rendering

Relying on the public API endpoint for GitHub Readme Stats subjects your profile to Vercel’s serverless function limits and GitHub API rate caps. When traffic spikes, cards may fail to load or display error messages. Static generation solves this by running the rendering logic once per day (or on demand) and committing the resulting SVG files directly to your repository. Visitors fetch these files from GitHub’s CDN rather than triggering live API requests, ensuring consistent performance regardless of external service availability.

## Architecture and Key Components

The static generation pipeline consists of four coordinated components:

- **`readme-tools/github-readme-stats-action`** – A reusable action that invokes the internal card rendering modules from the `anuraghazra/github-readme-stats` repository, passing parameters to [`src/index.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/index.js) which routes to the appropriate card generator.
- **Workflow file** ([`.github/workflows/grs.yml`](https://github.com/anuraghazra/github-readme-stats/blob/main/.github/workflows/grs.yml)) – Defines the cron schedule and orchestration steps that check out your repository, generate cards, and commit changes.
- **Card generators** ([`src/cards/stats.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/stats.js), [`src/cards/top-languages.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/top-languages.js)) – Core JavaScript modules that construct the SVG markup based on GitHub API data.
- **Profile repository** (`USERNAME/USERNAME`) – Stores the generated SVG files (e.g., `profile/stats.svg`) and serves them as static assets via relative paths in your README.

## Configure the GitHub Actions Workflow

Create a workflow file in your profile repository to automate daily regeneration of your statistics cards.

### Set Up the Workflow File

Create [`.github/workflows/grs.yml`](https://github.com/anuraghazra/github-readme-stats/blob/main/.github/workflows/grs.yml) with the following structure. This configuration triggers daily at 03:00 UTC and supports manual execution via the Actions tab.

```yaml
name: Update README cards

on:
  schedule:
    - cron: "0 3 * * *"
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate stats card
        uses: readme-tools/github-readme-stats-action@v1
        with:
          card: stats
          options: username=${{ github.repository_owner }}&show_icons=true
          path: profile/stats.svg
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Commit cards
        run: |
          git config user.name "github-actions"
          git config user.email "github-actions@users.noreply.github.com"
          git add profile/*.svg
          git commit -m "Update README cards" || exit 0
          git push

```

### Generate Multiple Card Types

Add additional steps to render different cards using the same action. Each step specifies a unique `card` parameter and output `path`:

```yaml
      - name: Generate top-languages card
        uses: readme-tools/github-readme-stats-action@v1
        with:
          card: top-langs
          options: username=${{ github.repository_owner }}&layout=compact&langs_count=8
          path: profile/top-langs.svg
          token: ${{ secrets.GITHUB_TOKEN }}

```

Valid `card` values include `stats`, `top-langs`, and `pin`, corresponding to the rendering logic in [`src/cards/stats.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/stats.js), [`src/cards/top-languages.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/top-languages.js), and [`src/cards/repo-card.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/repo-card.js) respectively.

## Embedding Static SVGs in Your README

Reference the committed SVG files using relative paths in your [`README.md`](https://github.com/anuraghazra/github-readme-stats/blob/main/README.md). Since the files reside in your repository, GitHub serves them from its CDN without triggering external API calls:

```markdown
![My GitHub stats](./profile/stats.svg)
![Top Languages](./profile/top-langs.svg)

```

This relative path approach ensures your cards render even if the public Vercel instance is offline or rate-limited.

## Handling Private Contributions with PATs

The default `GITHUB_TOKEN` provided to workflows only accesses public repository data. To include private contribution statistics in your cards, create a Personal Access Token (PAT) with `repo` scope and store it as a repository secret (e.g., `PAT_STATS`). Reference this secret in your workflow:

```yaml
        with:
          token: ${{ secrets.PAT_STATS }}

```

The action passes this token to the underlying fetch logic in [`src/fetchers/stats-fetcher.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/fetchers/stats-fetcher.js), enabling access to private commit data while keeping the rendered SVGs public.

## Summary

- **GitHub Actions** automates the generation of GitHub Readme Stats SVGs using the `readme-tools/github-readme-stats-action`.
- The workflow runs on a schedule (e.g., `0 3 * * *`) or manually via `workflow_dispatch`, executing card generation logic from [`src/cards/stats.js`](https://github.com/anuraghazra/github-readme-stats/blob/main/src/cards/stats.js) and related modules.
- Generated SVGs are committed to your profile repository (e.g., `profile/stats.svg`) and embedded via relative paths, eliminating external API dependencies.
- Use a **Personal Access Token** instead of `GITHUB_TOKEN` if you need to render statistics from private repositories.

## Frequently Asked Questions

### How often should I schedule the workflow to update my stats?

Run the workflow once daily using the cron expression `0 3 * * *` to balance freshness with resource usage. GitHub Actions provides 2,000 free minutes per month for private repositories and unlimited minutes for public repositories, making daily updates cost-free for profile repositories.

### Can I generate cards for repositories other than my own profile?

Yes. Specify any GitHub username in the `options` parameter (e.g., `options: username=torvalds&show_icons=true`). However, ensure you comply with GitHub’s Terms of Service regarding data usage, and note that private data for other users remains inaccessible regardless of your token permissions.

### What happens if the SVG generation fails?

If the `readme-tools/github-readme-stats-action` fails due to API errors or misconfiguration, the workflow exits without committing changes. Your README continues displaying the last successfully generated SVG files. Monitor the Actions tab for failure notifications and verify your token permissions if errors persist.

### Do I need to host my own instance of GitHub Readme Stats?

No. The `readme-tools/github-readme-stats-action` bundles the core logic from `anuraghazra/github-readme-stats`, including the card renderers in `src/cards/`. The action executes this logic directly within the GitHub Actions runner without requiring a separate Vercel deployment or external server.