DEV Community

Wilson Xu
Wilson Xu

Posted on

Generate Beautiful GitHub Repo Cards in Your Terminal

Generate Beautiful GitHub Repo Cards in Your Terminal

How many times a day do you open github.com just to check a repo's star count, last update, or license? If you're anything like me, the answer is embarrassingly high. Browser tabs pile up, the GitHub UI takes its sweet time loading, and you lose context switching away from your terminal.

That friction is exactly why I built repocard-cli — a zero-config Node.js tool that fetches any GitHub repository's metadata and renders a beautiful, bordered card right in your terminal. One command, instant results, no browser required.

npm install -g repocard-cli
repocard facebook/react
Enter fullscreen mode Exit fullscreen mode

In this article, I'll walk through the design decisions behind the tool: why terminal dashboards beat web UIs for quick lookups, how we talk to the GitHub API, how boxen and chalk turn raw JSON into gorgeous output, and how SVG export and side-by-side comparison round out the feature set.


Why Terminal Dashboards Beat Web UIs for Quick Checks

Developers already live in the terminal. We run git commands, spin up dev servers, manage containers, and SSH into remote machines — all without leaving the shell. So why do we context-switch to a browser just to check if a repo is still maintained?

Speed. A single repocard vercel/next.js returns in under a second. Compare that to opening Chrome, navigating to the repo page, waiting for the JS bundle to hydrate, and scrolling past the file tree to find the stats you actually care about.

Focus. Terminal output is distraction-free. No notification badges, no trending sidebar, no "Explore repositories" carousel. You get exactly the data you asked for and nothing else.

Scriptability. Because repocard-cli writes to stdout, you can pipe its output into other tools. Want a daily Slack digest of star counts for your team's repos? Combine repocard --json with jq and a webhook script, and you're done in five lines of bash.

Offline muscle memory. Once you internalize repocard owner/name, it's faster than any bookmark. Your fingers already know the way.

The broader trend here is clear: the best developer tools meet you where you already are. Tools like gh (GitHub CLI), lazygit, and k9s have proven that terminal-native interfaces aren't a compromise — they're an upgrade.


Fetching Repo Data from the GitHub API

Under the hood, repocard-cli makes a single call to the GitHub REST API's /repos/{owner}/{name} endpoint. The implementation is deliberately simple:

async function fetchRepo(slug: string): Promise<RepoData> {
  const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
  const headers: Record<string, string> = {
    'Accept': 'application/vnd.github+json',
    'User-Agent': 'repocard-cli/1.0',
  };
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  const res = await fetch(`https://api.github.com/repos/${slug}`, { headers });
  if (!res.ok) {
    if (res.status === 404) throw new Error(`Repository '${slug}' not found.`);
    if (res.status === 403) throw new Error('GitHub API rate limit exceeded. Set GITHUB_TOKEN to increase the limit.');
    throw new Error(`GitHub API error: ${res.status} ${res.statusText}`);
  }
  return (await res.json()) as RepoData;
}
Enter fullscreen mode Exit fullscreen mode

A few design choices worth calling out:

  1. Token is optional. Unauthenticated requests get 60 calls per hour — plenty for casual use. If you hit the limit, just export GITHUB_TOKEN or GH_TOKEN (the same variable the official GitHub CLI uses) and you jump to 5,000 requests per hour.

  2. Meaningful error messages. A 404 tells you the repo doesn't exist. A 403 tells you why (rate limit) and how to fix it (set a token). Good CLI tools don't make users guess.

  3. Typed response. The RepoData interface models every field we care about — star count, fork count, language, license, topics, archive status, and more. TypeScript catches mismatches at compile time instead of at 2 AM in production.

The single-endpoint approach keeps the tool fast. One HTTP round trip, one JSON parse, done. No need to paginate contributors or aggregate workflow runs for what is fundamentally a snapshot card.


Rendering Bordered Cards with boxen and chalk

Raw API data is useful but ugly. The magic of repocard-cli is in how it presents that data. Two npm packages do the heavy lifting:

chalk handles color. Each programming language gets its own hex color — JavaScript is #f1e05a, Rust is #dea584, Go is #00ADD8 — matching GitHub's own language dot convention. Stats use semantic colors: yellow for stars, blue for forks, red for issues. The result feels immediately familiar to anyone who's spent time on GitHub.

boxen draws the border. With borderStyle: 'round' and borderColor: 'cyan', we get a clean rounded box that frames the content without overwhelming it. Padding and margin are set to 1 to give the card breathing room.

The full card renderer builds up an array of lines:

  1. Title line — owner (cyan, bold) + separator (dim) + name (white, bold)
  2. Badges — yellow "ARCHIVED" or blue "FORK" badges when applicable
  3. Description — italicized and dimmed, truncated to fit the card width
  4. Stats row — stars, forks, watchers, and issues with Unicode symbols
  5. Details — language (with color dot), license, repo size, default branch, last updated, and homepage
  6. Topics — rendered as blue tag badges, up to 8
  7. Clone command — a ready-to-paste git clone URL

A --minimal flag collapses all of this into a single line for scripting or quick scans:

facebook/react - The library for web and native user interfaces.  ★ 232k  ⑂ 47.5k  ● JavaScript  [MIT]
Enter fullscreen mode Exit fullscreen mode

One subtle challenge is ANSI escape codes. When you colorize text with chalk, the string grows longer than what's visually rendered. The padRight helper strips ANSI codes before calculating padding widths, ensuring columns stay aligned even when every cell is a different color.


Adding SVG Export for README Embedding

Terminal output is great for developers, but what about READMEs, blog posts, and documentation? That's where SVG export comes in.

repocard facebook/react --svg-file card.svg
Enter fullscreen mode Exit fullscreen mode

The generateSVG function produces a self-contained SVG that mirrors the terminal card's layout. It uses a dark theme (#0d1117 background, matching GitHub's dark mode), Inter font loaded from Google Fonts, and the same language-color dot system.

The description is word-wrapped to 55 characters per line (up to 3 lines) to prevent overflow. Stats, language, license, and last-updated date are positioned dynamically based on the description height, so the card always looks balanced regardless of content length.

Because SVG is just XML, it renders natively in GitHub READMEs, browser previews, and any Markdown renderer. No external image hosting required — just commit the SVG to your repo and reference it:

![Repo Card](./card.svg)
Enter fullscreen mode Exit fullscreen mode

You can also pipe the raw SVG to stdout with --svg for integration with other tools or CI pipelines that generate documentation automatically.


Side-by-Side Repo Comparison

Choosing between two similar libraries? The --compare flag renders both repos in a side-by-side layout:

repocard facebook/react --compare vuejs/vue
Enter fullscreen mode Exit fullscreen mode

Each repo gets a 36-character-wide column showing its name, description, stats (stars, forks, watchers, issues), language, license, and last update. A dim vertical bar separates the columns.

Below the comparison, the tool generates a "winner summary" — plain-English statements like "facebook/react has more stars" or "vuejs/vue has more forks." It's a small touch, but it makes the output immediately actionable rather than forcing you to compare numbers manually.

The comparison card uses a magenta border (via boxen) to visually distinguish it from the default cyan single-repo card.

Under the hood, both repos are fetched concurrently, so the comparison adds minimal latency over a single card lookup.


Getting Started

Install globally and start using it immediately:

npm install -g repocard-cli

# Full card
repocard vercel/next.js

# Quick one-liner
repocard vercel/next.js --minimal

# Export SVG for your README
repocard vercel/next.js --svg-file card.svg

# Compare two repos
repocard expressjs/express --compare fastify/fastify

# Pipe JSON to jq
repocard vercel/next.js --json | jq '.stargazers_count'
Enter fullscreen mode Exit fullscreen mode

Set GITHUB_TOKEN to avoid rate limits:

export GITHUB_TOKEN=ghp_your_token_here
Enter fullscreen mode Exit fullscreen mode

The tool supports 30+ language colors, handles archived/forked repo badges, and gracefully errors on invalid input.


Wrapping Up

repocard-cli is a small tool that solves a small problem: getting GitHub repo information without leaving your terminal. But small tools that fit naturally into existing workflows tend to compound in value. Pipe it into scripts, embed SVGs in docs, compare libraries during evaluation — the use cases grow as you integrate it.

The full source is open on GitHub, MIT-licensed, and contributions are welcome. If there's a feature you'd like to see — chart output, multi-repo batch mode, GitLab support — open an issue or send a PR.

Give it a spin: npm install -g repocard-cli

Happy hacking.

Top comments (0)