Track your GitHub followers, unfollowers and following relationships.
Githubster is a free, open-source tool that helps you understand your public GitHub social graph. It requests profile data directly from the GitHub API in your browser, without requiring a Githubster account.
- Not Following Back — people you follow who don't follow you back
- You Don't Follow Back — people who follow you but you don't follow back
- Mutuals — people you follow who also follow you
- Following — everyone you follow
- Followers — everyone who follows you
- Profile Overview — top languages, total stars, repositories
- Sort users by name (A→Z, Z→A)
- Search and filter within each tab
- Share profile link with one click
- Keyboard shortcut (
/) to focus search - Loading progress with skeleton animation
- Optional GitHub token for higher rate limits
- Dark/Light theme
- 20 languages supported (i18n with RTL)
- Web app manifest for standalone installation (GitHub data still requires a network connection)
- Browser-based profile analysis — usernames and optional tokens are sent directly to GitHub, not to a Githubster API
- SEO optimized with structured data (JSON-LD)
# Install dependencies
npm install
# Run development server
npm run devOpen http://localhost:3000 in your browser.
The production site runs on Cloudflare Workers using OpenNext. It uses Workers KV
for the prerendered page cache and a Durable Object queue for the hourly
/api/stars revalidation. GitHub profile requests still run directly in the
visitor's browser. No database, R2 subscription, or Hetzner connection is required.
The same KV namespace retains the last successful repository star count if
GitHub rate-limits a shared Workers egress IP. Each deploy seeds that snapshot
from a successful build-time response; runtime refreshes update it when possible.
Use Node.js 24 or newer and install the locked dependencies with npm ci.
Authenticate with npx wrangler login if needed. The Worker and its bindings are
configured in wrangler.jsonc.
Copy .env.example to .env.production.local for production builds and fill in
the public Umami settings. NEXT_PUBLIC_* values are embedded during the build,
so changing analytics settings requires rebuilding the app. Local Worker preview
also reads these environment files. Never commit production environment files.
Set the IndexNow runtime secrets separately:
npx wrangler secret put INDEXNOW_KEY
npx wrangler secret put INDEXNOW_SECRETThe verification key must stay the same as the existing public IndexNow key. Use a separate random secret of at least 32 characters for authenticated submissions.
npm run lint
npm run typecheck
npm run cf:build
npm run cf:preview # optional local workerd preview of the built app
npm run cf:deploy
npm run cf:smokecf:deploy deploys the existing .open-next build and populates the remote KV
cache; run cf:build first after source or build-time environment changes.
public/_headers gives hashed Next.js assets immutable browser caching.
The githubster.com/* and www.githubster.com/* Worker routes keep the existing
proxied DNS records. The apex redirects to https://www.githubster.com with the
path and query intact. Both domains are served by the Worker without calling the
Hetzner origin. Keep the old origin available during the migration rollback
window. If its PM2 process has been stopped, run ssh hetzner 'pm2 restart githubster && pm2 save'
first, then remove just these two Worker routes in Cloudflare to restore origin
traffic. For later Worker releases, npx wrangler rollback restores the previous
Worker version. Do not delete the cache namespace or Durable Object binding as
part of a rollback.
After deployment, check the main and localized pages, /sitemap.xml,
/robots.txt, /api/stars, /{INDEXNOW_KEY}.txt, the /jp alias, and the CSS/JS
assets. POST /api/indexnow without valid authentication must return 401.
npm run build creates a complete standalone deployment in .next/standalone. The post-build step copies both .next/static and public into that directory, so deploy the entire .next/standalone directory and start it with:
node server.jsDeploying only server.js or only the standalone JavaScript files will cause /_next/static/* assets to return 404, leaving the site without styles and client-side behavior.
Without a token, GitHub normally allows 60 REST API requests per hour per IP address. An authenticated personal account normally gets 5,000 requests per hour, but GitHub can apply different limits in some situations.
To create a token:
- Open GitHub Settings → Developer settings → Fine-grained tokens.
- Create a fine-grained token with an expiration date and grant only the minimum access GitHub requires for the public endpoints you use.
- Paste it into the optional token field. The value stays in the current page state, is used only for direct requests to
api.github.com, and is cleared when the page is reloaded or closed.
GitHub recommends fine-grained tokens, limited permissions, and expiration dates. See Keeping your API credentials secure and permissions required for fine-grained tokens.
- Next.js 16 — React framework with Turbopack
- React 19 — UI library
- TypeScript 6 — type safety
- Tailwind CSS 4 — utility-first styling
- @tanstack/react-virtual — virtualized lists for large datasets
- GitHub REST API — data source
- Content Security Policy (CSP) headers
- Strict-Transport-Security (HSTS)
- X-Content-Type-Options, X-Frame-Options
- Permissions-Policy
- Profile analysis runs in the browser; Githubster does not persist usernames, GitHub responses, or optional tokens
- The optional token is a masked password field and can be revealed or cleared explicitly
- If Umami is configured, the site loads the configured analytics script; Githubster does not send GitHub tokens to it
- IndexNow submission requires a separate server-side bearer secret
Copy .env.example to .env.local and set only the integrations you use.
| Variable | Purpose |
|---|---|
INDEXNOW_KEY |
Public IndexNow verification key, also served at /{INDEXNOW_KEY}.txt |
INDEXNOW_SECRET |
Private bearer secret required by POST /api/indexnow; use a random value of at least 32 characters, different from the public key |
NEXT_PUBLIC_UMAMI_WEBSITE_ID |
Optional Umami website identifier |
NEXT_PUBLIC_UMAMI_URL |
Optional analytics script URL |
Trigger IndexNow from a trusted deployment workflow or server environment:
curl --request POST https://www.githubster.com/api/indexnow \
--header "Authorization: Bearer $INDEXNOW_SECRET"GET /api/indexnow is intentionally unsupported, and the secret must never use a NEXT_PUBLIC_ prefix.
The support section links to Ko-fi, PayPal, and GitHub. The Ko-fi floating-chat widget is loaded after page hydration from storage.ko-fi.com.
After deploying a release that changes public pages:
- Verify
https://www.githubster.com/_next/static/assets return200in browser DevTools. - Add and verify the
https://www.githubster.com/property in Google Search Console and Bing Webmaster Tools. - Submit
https://www.githubster.com/sitemap.xml, then request indexing for the homepage and the new/tools/and/guides/pages. - Trigger the protected IndexNow endpoint from a trusted deployment workflow after setting
INDEXNOW_KEYandINDEXNOW_SECRET. - Review Search Console queries, pages, and CTR weekly; improve existing pages with impressions before adding new ones.
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -am 'Add my feature') - Push to the branch (
git push origin feature/my-feature) - Open a Pull Request
MIT
