CLI tool
mdo/github-buttons avatar
mdo/github-buttons

mdo/github-buttons: static star, fork and follower buttons for a README

Showcase the success of any GitHub repo or user with these simple, static buttons with dynamic counts.

2,897 stars263 forksJavaScriptApache-2.0

At a glance

What is it?
GitHub Buttons renders count badges as a single static HTML file served from ghbtns.com. It suits READMEs and personal sites that want a star or follower count without a build step or a runtime dependency.
Who is it for?
Adopt mdo/github-buttons if you want a star, fork, watch, sponsor or follower count in a README or static page and you are willing to depend on the ghbtns.com host. Do not adopt it if you need an SLA, an offline build, or counts rendered without JavaScript.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 93 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What mdo/github-buttons actually puts on the page

GitHub Buttons produces a small button that links to a repository or a user profile and displays a live count next to the label: stars, forks, watchers, sponsors, or followers. The README describes it as static buttons with dynamic counts, and that pairing is the whole point. The button markup is fixed HTML; only the number changes, and it changes because the iframe it lives in fetches fresh data.

The target audience is narrow and specific. It is for people writing a README, a project landing page, or a personal site who want a star count visible without adding a JavaScript framework, a build plugin, or a server route. If your site is already a React or Vue application with its own data layer, this project solves a problem you do not have.

The project is not a general badge service. Shields.io and similar tools cover build status, coverage, package versions and dozens of other metrics. GitHub Buttons covers GitHub social signals only, and the README links to a second implementation, ntkme/github-buttons, as a related project rather than positioning itself as the only option.

How the iframe, the source files and the build fit together

The source is split across three files in src/: the HTML, the CSS, and the JavaScript. Those are not shipped separately. The build script runs inline-source over src/btn.html and pipes the result through html-minifier-terser, producing one compiled file at docs/github-btn.html. Everything the button needs ends up in that single document.

That compiled file is what the iframe loads. An embed points an iframe at a URL on ghbtns.com, the document inside the frame runs its own script, calls the GitHub API for the requested count, and writes the number into the button. The parent page never talks to the API, never holds a token, and never sees a JSON response. The counts are dynamic from the reader's perspective, but the embedding page itself stays static.

The repository also builds a Jekyll site. The npm start script runs build, docs-serve and watch in parallel, so a local edit to src/ triggers a rebuild of the compiled button while Jekyll serves the documentation. The docs/ directory holds both the compiled button and the Jekyll site, which is why the build output path and the documentation path are the same tree. That coupling is convenient for a single-maintainer project and awkward for anyone who wants the button file without the site around it.

Installing it locally and embedding a first button

The README states that local development requires Node.js, Ruby, and Bundler. Clone the repository and install both dependency sets. The README gives these two commands:

bash
npm i
bundle i

After that, npm run build compiles the source into docs/github-btn.html. The README documents this command directly:

bash
npm run build

The Jekyll site is served locally with Bundler, and the README says to open http://127.0.0.1:4000 to browse it:

bash
bundle exec jekyll serve

For the common case, you do not build anything. You visit ghbtns.com, the homepage the README points to, and copy the generated snippet. The embed is an iframe whose src points at the hosted button document with query parameters for the account, the repository, and the display options. The README's own example of the compiled artifact is the file at docs/github-btn.html, and the hosted URL serves that same document.

The README does not publish the full parameter table. It directs readers to ghbtns.com for that, so the authoritative list of options lives on the site rather than in the repository text. Treat the site as the reference and the repository as the implementation.

The ghbtns.com dependency is the real constraint

Every embed points at ghbtns.com. The README documents no self-hosting path for the hosted service, no Docker image, and no npm package you install into your own app. If that host is unreachable, or if the GitHub API call inside the frame fails, the button renders without a number or does not render at all. The reader sees a broken or empty badge on your page, and there is nothing your build can do about it.

This is the case where GitHub Buttons is the wrong tool. A documentation site with an uptime commitment, an internal dashboard, or any page where a missing count is a visible defect should not embed a third-party iframe. The same applies to fully offline or air-gapped builds: the compiled file is in the repository, but the counts it displays come from a network call at view time.

The count is also only as fresh as the API response the frame receives. Caching behaviour is not described in the README, so anyone who needs a guaranteed refresh interval should verify it against the live host rather than assume it from the repository text. The README is silent on rate limits, on what happens when the GitHub API returns an error, and on whether the frame retries.

ntkme/github-buttons and the difference in approach

The README's See also section names ntkme/github-buttons at buttons.github.io. The two projects solve the same visible problem, a GitHub count rendered as a small button, and they are separate codebases with separate hosts.

The practical difference for an adopter is where the button document comes from and who maintains it. mdo/github-buttons compiles its HTML, CSS and JavaScript into one file under docs/ and serves it from ghbtns.com. Choosing between them is mostly a question of which host you are willing to depend on and which repository you want to track for fixes, because the embedding model, an iframe pointed at a hosted document, is the same shape in both.

If your requirement is neither of these, if you need the count as data rather than as a rendered badge, the right comparison is not another button project at all. It is calling the GitHub API from your own code and rendering the number yourself, which removes the third-party host but adds a token, a cache and a failure path you now own.

Maintenance, versioning and the Apache-2.0 licence

The last push to the repository was on 2026-07-01, and the repository is not archived. The most recent release is v4.2.3 from 2025-04-20. The release before that, v4.2.2, is dated 2022-12-15, so the gap between v4.2.2 and v4.2.3 is more than two years. That pattern suggests releases arrive when something needs fixing rather than on a schedule, which matters if you are pinning a version and expecting periodic updates.

Upgrade cost is low for embedders and higher for anyone running the code. If you only paste a snippet from ghbtns.com, upgrades happen on the host and your page does not change. If you forked the repository and self-host the compiled file, you absorb the build toolchain: Node.js, Ruby, Bundler, inline-source-cli, html-minifier-terser and Jekyll all have to keep working together.

The package.json sets private to true, so this is not published as an installable npm dependency. There is nothing to add to your own package.json and no semantic-version contract to rely on for the embed. The licence is Apache-2.0, and the README states the copyright as 2014-2022 Mark Otto. Apache-2.0 permits commercial use and modification and includes a patent grant; it also requires that you preserve notices and state significant changes. That is a summary of the licence text, not legal advice, and anyone redistributing a modified build should read LICENSE in the repository.

Editorial conclusion

Adopt mdo/github-buttons if you want a star, fork, watch, sponsor or follower count in a README or static page and you are willing to depend on the ghbtns.com host. Do not adopt it if you need an SLA, an offline build, or counts rendered without JavaScript. Before embedding anything, open ghbtns.com, copy the snippet for your repo, and confirm the count appears in the iframe. If the count stays empty, the problem is the host or the API it calls, not your markup.

Frequently asked questions

What is mdo/github-buttons used for?

It renders static buttons that link to a GitHub repository or profile and show a live watch, fork, sponsor, star or follower count. The README describes it as a way to showcase a repo's success, and the intended placement is a README or a personal site.

How do I add a GitHub star button to a README?

The README points to ghbtns.com as the starting point, where you copy the generated iframe snippet for your account and repository. The compiled button document the iframe loads is built from src/btn.html into docs/github-btn.html.

Can I self-host mdo/github-buttons instead of using ghbtns.com?

The repository contains the full source and a build that produces docs/github-btn.html, and the README documents npm run build for that. The README does not document a supported self-hosting setup for the hosted service, so you would be maintaining the deployment yourself.

Why is my GitHub button not working?

Embeds load a document from ghbtns.com that fetches the count at view time, so a missing number usually means the host or the underlying API call failed rather than a problem in your markup. The README does not document error handling or retry behaviour for that call.

Official sources

  1. License: Apache-2.0
  2. mdo/github-buttons on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mdo-github-buttons.svg)](https://hysenlabs.com/projects/mdo-github-buttons)