Skip to content

feat: add star-tracker worker#52

Merged
wavekat-eason merged 22 commits into
mainfrom
feat/star-tracker
May 15, 2026
Merged

feat: add star-tracker worker#52
wavekat-eason merged 22 commits into
mainfrom
feat/star-tracker

Conversation

@wavekat-eason
Copy link
Copy Markdown
Contributor

Summary

Adds tools/star-tracker/ — a Cloudflare Worker, planned for stars.wavekat.com, that tracks GitHub star events via webhook and renders a cumulative star-history chart as SVG or PNG for any GitHub org/user.

  • Multi-tenant self-serve: anyone signs in with GitHub, registers an org/user slug, installs the webhook we hand back, and embeds the chart anywhere via <img src=".../<slug>/chart.svg">.
  • Ownership verified at registration: personal slugs must match the logged-in user's login; org slugs require GitHub admin role (checked via read:org OAuth scope).
  • HMAC SHA-256 webhook signature verification with a per-tenant secret.
  • D1-backed: users, tenants, repos, stars, events.
  • SVG renderer (step chart) + PNG via @resvg/resvg-wasm.
  • "Backfill all repos" one-click, plus single-repo backfill.
  • Nightly cron reconciliation to repair missed webhook deliveries.
  • Server-rendered dashboard: eye-icon secret reveal, live chart preview with a light/dark toggle.

Setup (after merge)

  1. cd tools/star-tracker && make install && make create-db — paste the database_id into wrangler.toml
  2. Register a prod GitHub OAuth App with callback https://stars.wavekat.com/auth/callback
  3. make secrets (prompts for GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, JWT_SECRET)
  4. make migrate && make deploy
  5. Enable the [[routes]] block in wrangler.toml (or wire the route in the dashboard) and point stars.wavekat.com DNS

For local dev, create a second OAuth App with callback http://localhost:8787/auth/callback, copy .dev.vars.example to .dev.vars with those credentials and PUBLIC_URL=http://localhost:8787, then make migrate-local && make dev.

Test plan

  • make install && make migrate-local && make dev boots cleanly
  • Sign-in with GitHub completes the OAuth round-trip
  • Registering a slug you own succeeds; one you don't is rejected with 403
  • "Backfill all" populates D1 with stargazers; chart preview refreshes
  • GitHub-delivered star event webhook updates the chart within seconds
  • /<slug>/chart.svg and /<slug>/chart.png render correctly, including ?theme=dark
  • Eye toggle hides/reveals the webhook secret

🤖 Generated with Claude Code

wavekat-eason and others added 2 commits May 15, 2026 18:42
Cloudflare Worker at stars.wavekat.com that tracks GitHub star events via
org-level webhook and renders a cumulative star-history chart as SVG/PNG.

Multi-tenant: anyone signs in with GitHub, registers an org/user slug (we
verify admin role via OAuth read:org), installs the webhook, and embeds
the chart anywhere with /<slug>/chart.svg.

- Hono + signed-cookie sessions
- D1 schema for users, tenants, repos, stars, events
- HMAC SHA-256 webhook verification with per-tenant secret
- SVG renderer + resvg-wasm PNG rasterisation
- Backfill all repos for an org (one click) or single-repo backfill
- Nightly cron reconciliation against the GitHub API
- Server-rendered dashboard with eye-toggle secret reveal and live chart preview with light/dark toggle

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The light chart's white background blended into the dark page background;
add a subtle bordered + shadowed frame so the chart edges are visible in
both themes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 15, 2026

wavekat-eason and others added 20 commits May 15, 2026 18:47
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Also clarify "total stars" → "GitHub stars" so the metric is unambiguous
when the chart is embedded outside GitHub.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The PNG rasterisation path via resvg-wasm hit rendering errors in
production. SVG embeds work everywhere PNG did (GitHub, npm, blog
posts) so drop the wasm dependency and the /:slug/chart.png route.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Draws the chart line in over 1.6s using stroke-dashoffset and fades
the fill area in alongside. Uses pathLength="1" so the animation
duration is consistent regardless of how many points are plotted.

CSS-only so it works when the SVG is embedded via <img> on GitHub
READMEs. Honours prefers-reduced-motion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Big orgs would blow the Worker subrequest budget and GitHub rate
limit on backfill. Repos with >5k stars now get a sampled curve (~15
pages, first+last star per page); backfill-all sorts by star count
desc and syncs the top 100, reporting exact/sampled/skipped counts.
Chart shows "≈ includes sampled data" when any repo is sampled.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds ?split=N (up to 8) to render one line per top repo instead of the
merged tenant total, plus PRG redirects on tenant POST actions so reloads
don't re-fire the action.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Render ?split=N as stacked areas with an "others" bucket so top
  repos + others sums to the tenant total.
- Add a Top selector (Merged / 3 / 5 / 8) on the dashboard preview;
  swaps the chart src in place alongside the theme toggle.
- Sort the tracked-repos list by stargazer count.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Embed the wavekat org's own star chart on the star-tracker landing
page so visitors can see the output in context. Add the Apache-2.0
LICENSE (matching the rest of the ecosystem) and update the landing
footer accordingly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bucket points by x-pixel before path building and round coords to ints
so high-volume tenants don't generate multi-MB SVGs. Add ETag keyed by
latest event timestamp so clients revalidate cheaply between webhooks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Private repos: record star/repository events but exclude them from chart
output until they're publicized. Stars + Repositories webhook events; the
star payload's `repository.private` keeps the flag fresh even without the
Repositories subscription. Latest privacy flip is folded into the chart
ETag so caches bust the moment a repo is hidden or revealed.

Public org page at /<slug>: tracked tenants get a chart + repo list view
for non-owners; untracked slugs get an invite page (and a themed SVG at
/<slug>/chart.svg so README embeds for not-yet-tracked orgs become
self-explaining instead of broken-image icons).

Webhook status on owner page: ping/last-event timestamps and per-event
counts (stars added/removed, repos publicized/privatized) so owners can
verify their subscription set.

Embed snippets now wrap the <img> in a link back to the org page. Chart
gets a 1px rounded border (light + dark) and switches to monotone-cubic
smooth as the default; ?style=step opts back into step-after.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@wavekat-eason wavekat-eason merged commit 6f13ee1 into main May 15, 2026
4 checks passed
@wavekat-eason wavekat-eason deleted the feat/star-tracker branch May 15, 2026 09:23
wavekat-eason pushed a commit that referenced this pull request May 15, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.0.21](wavekat-com-v0.0.20...wavekat-com-v0.0.21)
(2026-05-15)


### Features

* add star-tracker worker
([#52](#52))
([6f13ee1](6f13ee1))
* add wavekat-asr to ecosystem
([#50](#50))
([f26f29b](f26f29b))
* auto-theme star-tracker embed snippet
([#55](#55))
([4989603](4989603))
* star-tracker recent trend, range, per-repo charts
([#54](#54))
([7189f91](7189f91))


### Bug Fixes

* keep star-tracker count fresh on webhook
([#56](#56))
([1fdf264](1fdf264))
* stop long embed snippets blowing out page width
([#57](#57))
([7b6b096](7b6b096))
* wrap star-tracker header on mobile
([#53](#53))
([82e92b9](82e92b9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant