Thanks for helping keep this list short and honest. The whole point of the list is that every entry earned its place, so the bar is deliberately high and most of it is enforced by CI rather than by arguing in comments.
entries/<owner>--<name>.jsonis one file per listed project. That is the file you add, edit or delete.list.jsonholds the categories, the policy thresholds and the list metadata. It changes rarely;fmtkeeps categories and link sections in alphabetical order.README.md,docs/index.html,metadata.jsonand everything underbadges/are generated. CI rejects pull requests that touch them.- The generated
docs/folder is published with GitHub Pages at floatdrop.github.io/awesome-go, with search, filtering and sorting over the same data. - A nightly job refreshes star counts, removes repositories that were archived or deleted, and regenerates the README and badges. Nobody has to remember to clean up.
- Within each category the ten most-starred projects are shown first, each with its star count, and the rest are folded under a collapsed "More" block. Stars decide the order, humans decide who is on the list at all.
-
Make sure the project is not already listed and passes the entry rules.
-
Create
entries/<owner>--<name>.json, lowercase, with the two slashes of the repository path replaced by--:{ "$schema": "../schema/entry.schema.json", "repo": "owner/name", "description": "What it does, in one plain sentence.", "category": "existing-category-id" }Category ids are in
list.json.nameis optional and defaults to the repository name. Do not setadded; the bot fills it in on acceptance. -
Run the tooling and fix what it reports:
go run ./cmd/awesome fmt # canonical formatting and file naming go run ./cmd/awesome validate # offline rules GITHUB_TOKEN=$(gh auth token) go run ./cmd/awesome validate -remote # optional: the GitHub checks CI will run
-
Open a pull request with exactly one new entry and a sentence or two on why the project is awesome from your own experience. CI rejects pull requests that add more than one file under
entries/; splitting them makes each one reviewable.
Fully AI-generated pull requests are not accepted.
Enforced by CI on every pull request. The numbers live in the policy section of list.json, so if they change the README and this document follow.
| Rule | Why |
|---|---|
Repository is on GitHub, referenced as owner/name |
The tooling needs one canonical identity to check stars, status and renames. |
| At least 90 days old | Age filters out the weekend project that will be abandoned next weekend. |
| At least 200 stars | A low bar that still means real people have found it useful. |
| Pushed to within the last 365 days | Not required to be busy, just alive. |
| Has a license detected by GitHub | Unlicensed code cannot be used. |
Primary language is Go, or there is a go.mod at the root |
This is a Go list. |
| Not archived, not disabled, not a fork | Forks belong to the upstream entry; archived projects are removed automatically anyway. |
| Not already listed, including under an old name | Renamed repositories are followed through GitHub redirects. |
Description rules, also enforced:
- One sentence, at most 100 characters, starts with an uppercase letter, ends with a period.
- Says what the project does. No marketing ("blazing fast", "best", "powerful"), no leading article ("A", "The"), and no repeating the project name.
- Does not mention Go or Golang. Everything here is Go.
- Plain text: no Markdown, links or HTML.
A maintainer can waive individual rules with an explicit "exempt" list on the entry. The waiver is part of the entry file, so it is visible in the diff, in the history and to anyone reading the data:
"fork": the repository is a fork that became the maintained successor of its upstream (for examplego-viper/mapstructure)."inactive": a finished library that has not needed a commit in a while but is still the right answer."stars": below the star threshold but, in the maintainers' judgment, already the best option in its category."age": younger than the age threshold; use together with"stars"for a new project the maintainers stand behind.
Contributors should not add exemptions themselves; propose the entry and make the case in the pull request. Every exemption must be justified there, and the nightly job keeps listing inactive projects in its summary so they get looked at again.
Rules that need a human:
- An entry earns its place in one of two ways. Either it covers a need that no listed project in its category covers, or it does the same job better than a listed project. In the second case say which one and why; replacing the weaker entry is a normal outcome, not a hostile one. "Also popular" is not a third way in.
- The project must be something you would recommend to a colleague without caveats.
- The category must fit. Suggest a new category in the PR if none does, with at least three candidate entries for it.
- Deprecated, "maintenance mode" and thin wrappers around another listed project do not qualify even if they pass every automated check.
Documentation and other resources that are not a GitHub repository go under links/, one file per link, named after the title in lowercase with hyphens (A Tour of Go becomes links/a-tour-of-go.json):
{
"$schema": "../schema/link.schema.json",
"title": "A Tour of Go",
"url": "https://go.dev/tour/",
"description": "What the reader gets from it, in one plain sentence.",
"section": "documentation"
}Section ids are the link_sections in list.json. Links follow the same description rules as entries and count toward the one-addition-per-pull-request limit. Instead of star and age checks, CI requests the URL and requires an https link that answers without an error. A GitHub repository is always an entry, never a link. The nightly job reports links that stop answering but does not remove them. Some publishers block automated requests while the page works fine in a browser; a maintainer can then add "exempt": ["link-check"] to the link, which skips the live check and keeps every other rule.
A series, such as one interactive tour per Go release, is one link with a versions list, newest first, each with a label and a url. The link's own url must equal the newest version's, so the title always points at the latest installment. A new installment is a new first item in versions plus the updated url, not a new link.
Archived and deleted repositories are removed automatically every night. Anything else (unmaintained, superseded, no longer recommendable) is removed through a pull request that deletes the entry and explains why. The nightly job also lists projects with no pushes in the policy window in its job summary so they can be reviewed.
Every listed project gets its own badge: a small SVG with an 8-bit gopher in sunglasses, so it stands out among generic shields, and the project name in a colour of its own.
Embed it in your README:
[](https://floatdrop.github.io/awesome-go/#OWNER--NAME)Replace OWNER--NAME with your repository slug in lowercase, in both places. The link lands on your entry in the published list. The badge only exists while the project is listed; if the entry is removed the image disappears with the next sync.
Everything is stdlib Go, run through go run ./cmd/awesome <command>:
| Command | What it does |
|---|---|
validate |
Offline rules; -remote adds the GitHub checks, -base DIR limits them to entries not present under that directory. |
fmt |
Rewrites list.json and entries/ in canonical form and fixes file names; -check only verifies. |
compare |
Prints what the categories of new entries already hold, as Markdown; CI posts it on the pull request. -base DIR selects the new entries. |
refresh |
Fetches stars, activity and status into metadata.json, follows renames, stamps added dates. |
prune |
Removes archived, disabled and deleted repositories; reports stale ones. |
generate |
Writes README.md, docs/index.html and badges/*.svg. |
sync |
refresh, prune and generate in sequence; what the nightly job runs. |
Set GITHUB_TOKEN for anything that talks to GitHub. Unauthenticated requests are limited to 60 per hour.