FUNDING.yml alone won't show a Sponsor button: notes from auditing 42 repos
Yesterday I published three OSS repositories and thought the sponsorship plumbing was done. My account-wide FUNDING.yml was inherited, and querying the API returned the funding links just fine. Then I opened the repo pages: no Sponsor button anywhere.
The API said “it’s there”; the page said “it isn’t.” The cause turned out to be a two-layer design in GitHub, and one of the layers only bites people who create repos from the CLI. I ended up auditing all 42 of my public repositories, so here are the notes.
The Sponsor button is a two-layer system
The button only renders when two independent settings are both in place.
| Layer | What it does | Where it lives |
|---|---|---|
| FUNDING.yml | What to show (the list of links) | .github/FUNDING.yml |
| Sponsorships flag | Whether to show it at all | Repo Settings → Features checkbox |
For FUNDING.yml, one file in a repository named .github becomes the default for every public repo in the account. Mine lists GitHub Sponsors and Ko-fi, and it was inheriting into new repos exactly as documented.
The other layer is the trap. Creating FUNDING.yml through the web UI turns the flag on for you. Creating the repo with gh repo create or a plain git push leaves the flag off. Browser users never learn the flag exists; CLI users trip over it silently.
And this flag is not in the REST API at all. It only exists in GraphQL as hasSponsorshipsEnabled, which is why you won’t find it among the gh repo edit options. Enabling it looks like this:
id=$(gh api graphql -f query='{ repository(owner: "you", name: "repo") { id } }' \
--jq '.data.repository.id')
gh api graphql -f query='
mutation($id: ID!) {
updateRepository(input: {repositoryId: $id, hasSponsorshipsEnabled: true}) {
repository { name hasSponsorshipsEnabled }
}
}' -f id="$id"
“The API returns it” and “it’s displayed” are different claims
That was my mistake at the start. GraphQL returned both funding links, so I reported the button as live. What the response actually proves is that FUNDING.yml is inherited — nothing more. The button has its own switch.
The reliable check is to ask the rendered page:
curl -s "https://github.com/you/repo" | grep -c "Sponsor this project"
# 1 means the sidebar section is rendering
What auditing 42 repositories turned up
Suspecting more of the same, I swept every public repo on my account.
| State | Repos | Action |
|---|---|---|
| Button showing | 12 | (3 of them fixed that same morning) |
| Active repos of mine, flag off | 9 | Enabled via GraphQL |
| Archived | 18 | Left alone |
| Forks | 3 | Left alone |
All 12 of the showing buttons were hand-fixed: 3 that morning, 9 the day before. In other words, the number of repos where the button appeared on its own was 0 out of 42. The audit surfaced a second problem too: nine repos still carried per-repo FUNDING.yml files from an earlier setup pass, and eight of those were stale — GitHub Sponsors only, no Ko-fi. A per-repo file overrides the account default, so those eight repos had been quietly hiding the Ko-fi link. I deleted all nine and consolidated on the single file in .github.
Copying FUNDING.yml into each repository is how the two-source problem starts. Update the default later and the stale per-repo copies keep winning forever.
The audit script for your own account is short:
OWNER=you
gh repo list "$OWNER" --visibility public --limit 200 --json name --jq '.[].name' |
while read -r name; do
flag=$(gh api graphql -f query="{ repository(owner: \"$OWNER\", name: \"$name\") \
{ hasSponsorshipsEnabled } }" --jq '.data.repository.hasSponsorshipsEnabled')
echo "$flag $name"
done | sort
Every false line is a repo with no button.
What I decided not to touch
Flipping everything to true was not the goal.
The 18 archived repos are read-only, so the mutation fails anyway. Unarchiving would work, but I could not summon the ambition to solicit sponsorships on a ten-year-old Android sample.
The 3 forks I skipped on purpose. A fork inherits the upstream FUNDING.yml, which carries the original author’s sponsorship links. One of mine, a terminal app fork, still points at the connectbot maintainer’s GitHub Sponsors. Replacing that with my own button would mean collecting support on someone else’s work. The upstream settings stay as they are.
The dish is free; the missed chances accumulate quietly
To be honest about revenue: my Sponsors numbers are not worth reporting yet. But with no dish set out, zero is guaranteed. GitHub Sponsors charges no platform fee on individual sponsorships, and Ko-fi takes 0% on donations, so the total cost of being sponsorable is the five minutes of setup. If you ship OSS as an indie developer, this belongs in the same breath as creating the repository.
One confession to close. I had hit this exact trap the day before, on a different repository, and had written myself a note about the fix. The next day I shipped three new repos and missed it three times in a row. Memory doesn’t scale, so the flag mutation and the rendered-page check are now part of my repo-publishing checklist. This post is an extension of that checklist.
Was this article helpful?