Badges - TL;DR for your repository's README
Tags: github, tutorial, documentation, metadata
Published: 2022-07-15 16:54:00

Before I began actively using GitHub to work on my research publicly, I would sometimes end up on GitHub looking for a tool to accomplish some task or looking for a relevant library, etc. My first take on badges at the top of the README of a repository was along the lines of "what is this nonsense?", and I'd proceed to ignore that section of the README entirely. The more I've used GitHub I've discovered that in repositories where that section is well-organized and the badges linked to relevant information that it serves a very useful purpose. Essentially, the right mix of relevant and dynamic badges, displaying the right metadata, and linked to the right information becomes a TL;DR for your README. And with dynamic badges, the metadata is always up to date for the visitors of your repository without any intervention on your part.

__TL;DR__: Well-organized badges with relevant links == TL;DR for a repository's README.

The remainder of this post is organized as follows:
* [What are badges?](#what-are-badges)
* [Where do I get them?](#where-do-i-get-them)
* [Tips for using badges well](#tips-for-using-badges-well)
* [Repository Used in Examples](#repository-used-in-examples)
* [About Me](#about-me)

## What are badges?

Here are a couple example badges from one of my projects, including how they are linked: 

[![Maven Central](https://img.shields.io/maven-central/v/org.cicirello/chips-n-salsa.svg?label=Maven%20Central&logo=apachemaven)](https://search.maven.org/artifact/org.cicirello/chips-n-salsa) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/cicirello/Chips-n-Salsa?logo=GitHub)](https://github.com/cicirello/Chips-n-Salsa/releases) 

Without telling you anything you instantly know that the project publishes artifacts to Maven Central along with the latest version number, and you know the version of the latest GitHub release. If you follow the links, in the first case you end up on the Maven Central page for the library where you find all you need to import the library, and in the second case you end up on the releases tab of the GitHub repository.

## Where do I get them?

There are three main sources of README badges: (1) [badge generation services](#badge-generation-services), (2) [service specific badges](#service-specific-badges), and (3) [tools that you can run locally](#tools-you-can-run-yourself). Let's look at all three cases.

### Badge generation services 

[Shields](https://github.com/badges/shields) is probably the most widely used badge generation service. Another is [Badgen](https://github.com/badgen/badgen.net). Shields has a larger variety with support for a wider variety of services, etc, but Badgen has a good variety as well, along with a few that Shields doesn't yet have. Most of these are dynamic badges, updating relevant information as things change (e.g., with new release version, build status, coverage percentage, etc). And both support both dynamic and static custom badges.

### Service specific badges 

Some services that you might use as part of your project may provide badges specific to their service. For example, if you use [Zenodo](https://zenodo.org/) to create DOIs for your releases, Zenodo provides a dynamic badge that updates with the DOI of the latest release, which you can link to the Zenodo archive of the release. Here is an example from the same project as above: 

[![DOI](https://zenodo.org/badge/273074441.svg)](https://zenodo.org/badge/latestdoi/273074441) 

[Snyk](https://snyk.io/) provides security score and vulnerability count badges, which you can link to the relevant pages, as in these examples: 

[![Snyk security score](https://snyk-widget.herokuapp.com/badge/mvn/org.cicirello/chips-n-salsa/badge.svg)](https://snyk.io/vuln/maven%3Aorg.cicirello%3Achips-n-salsa) [![Snyk Known Vulnerabilities](https://snyk.io/test/github/cicirello/Chips-n-Salsa/badge.svg)](https://snyk.io/test/github/cicirello/Chips-n-Salsa)

Some badges may display static, yet still useful, metadata. For example, many of my repositories relate to my research, and as an academic also relate to journal articles I've published, such as an article in the [Journal of Open Source Software](https://joss.theoj.org/), which provides each article with a badge that can be linked directly to the full-text of the article, such as: 

[![JOSS DOI](https://joss.theoj.org/papers/10.21105/joss.02448/status.svg)](https://doi.org/10.21105/joss.02448)

### Tools you can run yourself 

In some cases, there may be tools that you can run yourself as part of your CI/CD workflows. For example, last week I posted about the [jacoco-badge-generator](https://github.com/cicirello/jacoco-badge-generator), which can be used as either a GitHub Action or as a local CLI tool to parse a JaCoCo coverage report, generate coverage badges, as well as for performing PR checks. Here is a link to that DEV.to post:

{% link https://dev.to/cicirello/the-jacoco-badge-generator-github-action-is-now-also-available-as-a-cli-tool-from-pypi-3ma0 %}

## Tips for using badges well

If you just grab the URLs for all of the badges even remotely relevant to your repository from Shields or Badgen, and just haphazardly place them at the top of your README without linking them to anything, they may detract from the readability of your repository's README, rather than improving it. I have two tips related to using badges well to provide a TL;DR that is useful to the visitors of your repository, as well as to yourself and any collaborators, specifically [organization](#tip-1-organization) and [link to relevant information](#tip-2-every-badge-should-link-to-something-relevant).

### Tip 1: Organization 

If your project only has need for a few badges, perhaps five or less, just putting them in a row is probably sufficient. But if your README has more than that, it is worth thinking a bit about how to organize them. I've seen a variety of approaches to this that are effective. The approach that I take is with a markdown table with one row for each category of badge. Here is an example from one of my repositories (the very case I've used earlier for a few examples). Note that this example table looks differently here on DEV.to than it does on GitHub. They appear to process tables differently. It looks better on GitHub (for the intended purpose of this table).

| __Publications About the Library__ | [![JOSS DOI](https://joss.theoj.org/papers/10.21105/joss.02448/status.svg)](https://doi.org/10.21105/joss.02448) |
| :--- | :--- |
| __Packages and Releases__ | [![Maven Central](https://img.shields.io/maven-central/v/org.cicirello/chips-n-salsa.svg?label=Maven%20Central&logo=apachemaven)](https://search.maven.org/artifact/org.cicirello/chips-n-salsa) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/cicirello/Chips-n-Salsa?logo=GitHub)](https://github.com/cicirello/Chips-n-Salsa/releases) |
| __Build Status__ | [![build](https://github.com/cicirello/Chips-n-Salsa/workflows/build/badge.svg)](https://github.com/cicirello/Chips-n-Salsa/actions/workflows/build.yml) [![docs](https://github.com/cicirello/Chips-n-Salsa/workflows/docs/badge.svg)](https://chips-n-salsa.cicirello.org/api/) [![CodeQL](https://github.com/cicirello/Chips-n-Salsa/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/cicirello/Chips-n-Salsa/actions/workflows/codeql-analysis.yml) |
| __JaCoCo Test Coverage__ | [![coverage](https://raw.githubusercontent.com/cicirello/Chips-n-Salsa/badges/jacoco.svg)](https://github.com/cicirello/Chips-n-Salsa/actions/workflows/build.yml) [![branches coverage](https://raw.githubusercontent.com/cicirello/Chips-n-Salsa/badges/branches.svg)](https://github.com/cicirello/Chips-n-Salsa/actions/workflows/build.yml) |
| __Security__ | [![Snyk security score](https://snyk-widget.herokuapp.com/badge/mvn/org.cicirello/chips-n-salsa/badge.svg)](https://snyk.io/vuln/maven%3Aorg.cicirello%3Achips-n-salsa) [![Snyk Known Vulnerabilities](https://snyk.io/test/github/cicirello/Chips-n-Salsa/badge.svg)](https://snyk.io/test/github/cicirello/Chips-n-Salsa) |
| __DOI__ | [![DOI](https://zenodo.org/badge/273074441.svg)](https://zenodo.org/badge/latestdoi/273074441) |
| __License__ | [![GitHub](https://img.shields.io/github/license/cicirello/Chips-n-Salsa)](https://github.com/cicirello/Chips-n-Salsa/blob/master/LICENSE) |
| __Support__ | [![GitHub Sponsors](https://img.shields.io/badge/sponsor-30363D?logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/cicirello) [![Liberapay](https://img.shields.io/badge/Liberapay-F6C915?logo=liberapay&logoColor=black)](https://liberapay.com/cicirello) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?logo=ko-fi&logoColor=white)](https://ko-fi.com/cicirello) |

Is this the only way to organize this set of badges? Of course not. Is this the best way to do so? Probably not. I've rearranged stuff as I've added to it, or as I've used it. For example, the metadata isn't just for visitors to your repository. It is there for you too. 

If you like the table approach, I recommend using bold on the row labels because GitHub-flavored markdown tables use bold by default on the header row assuming that it consists in column headings. If you don't bold the row labels, then only the top row will have a bold row label. I also recommend either explicitly left aligning the columns or centering the columns. The example above is left aligned. The reason is that GitHub-flavored markdown by default centers the column headings, but not the contents of the columns. So if you leave it to the default, only the top row will be centered. The structure that I use for left alignment is as follows, which looks better on GitHub than here on DEV for the purpose of organizing badges.

```markdown
| __Category One__ | badge markup with links here |
| :--- | :--- |
| __Category Two__ | badge markup with links here |
| __Category Three__ | badge markup with links here |
```

Or if you want to center everything, the following should work:

```markdown
| __Category One__ | badge markup with links here |
| :---: | :---: |
| __Category Two__ | badge markup with links here |
| __Category Three__ | badge markup with links here |
```

### Tip 2: Every Badge Should Link to Something Relevant

Visitors to your repository will likely click on some of your badges, expecting to be taken to more detailed information related to the metadata displayed in the badge. In the example table above, every badge links to something relevant. For some of these, what to link to is obvious (e.g., package repository badges, release badges, license badges, among others). For a few, it is slightly less so. For example, for build status badges for builds run on GitHub Actions, it would be nice if it was possible to link directly to the specific workflow run that corresponds to the displayed status. As far as I'm aware, that is not possible, so in my example, I have that linked to the list of runs of the relevant workflow, although in the case of the status of building the docs, I link to the live API docs that I serve from GitHub Pages instead.

The markup to link a build status badge to the corresponding list of workflow runs is as follows:

```markdown
[![ALTERNATE-TEXT](BADGE-URL-GOES-HERE)](https://github.com/USERID/REPO/actions/workflows/WORKFLOW-FILE-NAME.yml)
```

GitHub actually generates a status badge for each of your GitHub Actions workflows, with a URL of the form:

```markdown
https://github.com/USERID/REPO/workflows/NAME-OF-YOUR-WORKFLOW/badge.svg
```

You can combine the above two with:

```markdown
[![ALTERNATE-TEXT](https://github.com/USERID/REPO/workflows/NAME-OF-YOUR-WORKFLOW/badge.svg)](https://github.com/USERID/REPO/actions/workflows/WORKFLOW-FILE-NAME.yml)
```

## Repository Used in Examples

If you want to look at the examples within the broader context, as well as to see the actual result of formatting as a table as it appears on GitHub, all examples in this post are from the following repository.

{% github cicirello/Chips-n-Salsa %}


## About Me

Personal Website:

{% embed https://www.cicirello.org %}

DEV.to Profile:

{% user cicirello %}

GitHub Profile:

{% github cicirello/cicirello %}